OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/test/base/web_ui_browsertest.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/lazy_instance.h" | |
13 #include "base/memory/ref_counted_memory.h" | |
14 #include "base/path_service.h" | |
15 #include "base/utf_string_conversions.h" | |
16 #include "base/values.h" | |
17 #include "chrome/browser/printing/print_preview_dialog_controller.h" | |
18 #include "chrome/browser/profiles/profile.h" | |
19 #include "chrome/browser/ui/browser.h" | |
20 #include "chrome/browser/ui/browser_commands.h" | |
21 #include "chrome/browser/ui/browser_navigator.h" | |
22 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
23 #include "chrome/browser/ui/webui/web_ui_test_handler.h" | |
24 #include "chrome/common/chrome_paths.h" | |
25 #include "chrome/common/url_constants.h" | |
26 #include "chrome/test/base/test_chrome_web_ui_controller_factory.h" | |
27 #include "chrome/test/base/test_tab_strip_model_observer.h" | |
28 #include "chrome/test/base/ui_test_utils.h" | |
29 #include "content/public/browser/navigation_controller.h" | |
30 #include "content/public/browser/url_data_source.h" | |
31 #include "content/public/browser/web_contents.h" | |
32 #include "content/public/browser/web_ui_controller.h" | |
33 #include "content/public/browser/web_ui_message_handler.h" | |
34 #include "net/base/net_util.h" | |
35 #include "testing/gmock/include/gmock/gmock.h" | |
36 #include "testing/gtest/include/gtest/gtest-spi.h" | |
37 #include "ui/base/resource/resource_bundle.h" | |
38 #include "ui/base/resource/resource_handle.h" | |
39 | |
40 using content::NavigationController; | |
41 using content::RenderViewHost; | |
42 using content::WebContents; | |
43 using content::WebUIController; | |
44 using content::WebUIMessageHandler; | |
45 | |
46 namespace { | |
47 | |
48 const FilePath::CharType kA11yAuditLibraryJSPath[] = FILE_PATH_LITERAL( | |
49 "third_party/accessibility-developer-tools/gen/axs_testing.js"); | |
50 const FilePath::CharType kMockJSPath[] = | |
51 FILE_PATH_LITERAL("chrome/third_party/mock4js/mock4js.js"); | |
52 const FilePath::CharType kWebUILibraryJS[] = FILE_PATH_LITERAL("test_api.js"); | |
53 const FilePath::CharType kWebUITestFolder[] = FILE_PATH_LITERAL("webui"); | |
54 base::LazyInstance<std::vector<std::string> > error_messages_ = | |
55 LAZY_INSTANCE_INITIALIZER; | |
56 | |
57 // Intercepts all log messages. | |
58 bool LogHandler(int severity, | |
59 const char* file, | |
60 int line, | |
61 size_t message_start, | |
62 const std::string& str) { | |
63 if (severity == logging::LOG_ERROR && | |
64 file && | |
65 std::string("CONSOLE") == file) { | |
66 error_messages_.Get().push_back(str); | |
67 } | |
68 | |
69 return false; | |
70 } | |
71 | |
72 } // namespace | |
73 | |
74 WebUIBrowserTest::~WebUIBrowserTest() {} | |
75 | |
76 void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { | |
77 user_libraries_.push_back(library_path); | |
78 } | |
79 | |
80 // Add a helper JS library to the given WebUIBrowserTest from a path relative to | |
81 // base::DIR_SOURCE_ROOT. | |
82 // static | |
83 void AddLibraryFromSourceRoot(WebUIBrowserTest* browser_test, | |
84 const FilePath& path) { | |
85 FilePath filePath; | |
86 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &filePath)); | |
87 filePath = filePath.Append(path); | |
88 browser_test->AddLibrary(filePath); | |
89 } | |
90 | |
91 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { | |
92 ConstValueVector empty_args; | |
93 return RunJavascriptFunction(function_name, empty_args); | |
94 } | |
95 | |
96 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, | |
97 Value* arg) { | |
98 ConstValueVector args; | |
99 args.push_back(arg); | |
100 return RunJavascriptFunction(function_name, args); | |
101 } | |
102 | |
103 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, | |
104 Value* arg1, | |
105 Value* arg2) { | |
106 ConstValueVector args; | |
107 args.push_back(arg1); | |
108 args.push_back(arg2); | |
109 return RunJavascriptFunction(function_name, args); | |
110 } | |
111 | |
112 bool WebUIBrowserTest::RunJavascriptFunction( | |
113 const std::string& function_name, | |
114 const ConstValueVector& function_arguments) { | |
115 return RunJavascriptUsingHandler( | |
116 function_name, function_arguments, false, false, NULL); | |
117 } | |
118 | |
119 bool WebUIBrowserTest::RunJavascriptTestF(bool is_async, | |
120 const std::string& test_fixture, | |
121 const std::string& test_name) { | |
122 ConstValueVector args; | |
123 args.push_back(Value::CreateStringValue(test_fixture)); | |
124 args.push_back(Value::CreateStringValue(test_name)); | |
125 | |
126 if (is_async) | |
127 return RunJavascriptAsyncTest("RUN_TEST_F", args); | |
128 else | |
129 return RunJavascriptTest("RUN_TEST_F", args); | |
130 } | |
131 | |
132 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name) { | |
133 ConstValueVector empty_args; | |
134 return RunJavascriptTest(test_name, empty_args); | |
135 } | |
136 | |
137 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name, | |
138 Value* arg) { | |
139 ConstValueVector args; | |
140 args.push_back(arg); | |
141 return RunJavascriptTest(test_name, args); | |
142 } | |
143 | |
144 bool WebUIBrowserTest::RunJavascriptTest(const std::string& test_name, | |
145 Value* arg1, | |
146 Value* arg2) { | |
147 ConstValueVector args; | |
148 args.push_back(arg1); | |
149 args.push_back(arg2); | |
150 return RunJavascriptTest(test_name, args); | |
151 } | |
152 | |
153 bool WebUIBrowserTest::RunJavascriptTest( | |
154 const std::string& test_name, | |
155 const ConstValueVector& test_arguments) { | |
156 return RunJavascriptUsingHandler( | |
157 test_name, test_arguments, true, false, NULL); | |
158 } | |
159 | |
160 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name) { | |
161 ConstValueVector empty_args; | |
162 return RunJavascriptAsyncTest(test_name, empty_args); | |
163 } | |
164 | |
165 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name, | |
166 Value* arg) { | |
167 ConstValueVector args; | |
168 args.push_back(arg); | |
169 return RunJavascriptAsyncTest(test_name, args); | |
170 } | |
171 | |
172 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name, | |
173 Value* arg1, | |
174 Value* arg2) { | |
175 ConstValueVector args; | |
176 args.push_back(arg1); | |
177 args.push_back(arg2); | |
178 return RunJavascriptAsyncTest(test_name, args); | |
179 } | |
180 | |
181 bool WebUIBrowserTest::RunJavascriptAsyncTest(const std::string& test_name, | |
182 Value* arg1, | |
183 Value* arg2, | |
184 Value* arg3) { | |
185 ConstValueVector args; | |
186 args.push_back(arg1); | |
187 args.push_back(arg2); | |
188 args.push_back(arg3); | |
189 return RunJavascriptAsyncTest(test_name, args); | |
190 } | |
191 | |
192 bool WebUIBrowserTest::RunJavascriptAsyncTest( | |
193 const std::string& test_name, | |
194 const ConstValueVector& test_arguments) { | |
195 return RunJavascriptUsingHandler(test_name, test_arguments, true, true, NULL); | |
196 } | |
197 | |
198 void WebUIBrowserTest::PreLoadJavascriptLibraries( | |
199 const std::string& preload_test_fixture, | |
200 const std::string& preload_test_name, | |
201 RenderViewHost* preload_host) { | |
202 ASSERT_FALSE(libraries_preloaded_); | |
203 ConstValueVector args; | |
204 args.push_back(Value::CreateStringValue(preload_test_fixture)); | |
205 args.push_back(Value::CreateStringValue(preload_test_name)); | |
206 RunJavascriptUsingHandler( | |
207 "preloadJavascriptLibraries", args, false, false, preload_host); | |
208 libraries_preloaded_ = true; | |
209 } | |
210 | |
211 void WebUIBrowserTest::BrowsePreload(const GURL& browse_to) { | |
212 content::TestNavigationObserver navigation_observer( | |
213 content::Source<NavigationController>( | |
214 &browser()->tab_strip_model()-> | |
215 GetActiveWebContents()->GetController()), | |
216 this, 1); | |
217 chrome::NavigateParams params(browser(), GURL(browse_to), | |
218 content::PAGE_TRANSITION_TYPED); | |
219 params.disposition = CURRENT_TAB; | |
220 chrome::Navigate(¶ms); | |
221 navigation_observer.WaitForObservation( | |
222 base::Bind(&content::RunMessageLoop), | |
223 base::Bind(&MessageLoop::Quit, | |
224 base::Unretained(MessageLoopForUI::current()))); | |
225 } | |
226 | |
227 void WebUIBrowserTest::BrowsePrintPreload(const GURL& browse_to) { | |
228 ui_test_utils::NavigateToURL(browser(), browse_to); | |
229 | |
230 TestTabStripModelObserver tabstrip_observer( | |
231 browser()->tab_strip_model(), this); | |
232 chrome::Print(browser()); | |
233 tabstrip_observer.WaitForObservation( | |
234 base::Bind(&content::RunMessageLoop), | |
235 base::Bind(&MessageLoop::Quit, | |
236 base::Unretained(MessageLoopForUI::current()))); | |
237 | |
238 printing::PrintPreviewDialogController* tab_controller = | |
239 printing::PrintPreviewDialogController::GetInstance(); | |
240 ASSERT_TRUE(tab_controller); | |
241 WebContents* preview_dialog = tab_controller->GetPrintPreviewForContents( | |
242 browser()->tab_strip_model()->GetActiveWebContents()); | |
243 ASSERT_TRUE(preview_dialog); | |
244 SetWebUIInstance(preview_dialog->GetWebUI()); | |
245 } | |
246 | |
247 const char WebUIBrowserTest::kDummyURL[] = "chrome://DummyURL"; | |
248 | |
249 WebUIBrowserTest::WebUIBrowserTest() | |
250 : test_handler_(new WebUITestHandler()), | |
251 libraries_preloaded_(false), | |
252 override_selected_web_ui_(NULL) {} | |
253 | |
254 void WebUIBrowserTest::set_preload_test_fixture( | |
255 const std::string& preload_test_fixture) { | |
256 preload_test_fixture_ = preload_test_fixture; | |
257 } | |
258 | |
259 void WebUIBrowserTest::set_preload_test_name( | |
260 const std::string& preload_test_name) { | |
261 preload_test_name_ = preload_test_name; | |
262 } | |
263 | |
264 namespace { | |
265 | |
266 // DataSource for the dummy URL. If no data source is provided then an error | |
267 // page is shown. While this doesn't matter for most tests, without it, | |
268 // navigation to different anchors cannot be listened to (via the hashchange | |
269 // event). | |
270 class MockWebUIDataSource : public content::URLDataSource { | |
271 public: | |
272 MockWebUIDataSource() {} | |
273 | |
274 private: | |
275 virtual ~MockWebUIDataSource() {} | |
276 | |
277 virtual std::string GetSource() OVERRIDE { | |
278 return "dummyurl"; | |
279 } | |
280 | |
281 virtual void StartDataRequest( | |
282 const std::string& path, | |
283 bool is_incognito, | |
284 const content::URLDataSource::GotDataCallback& callback) OVERRIDE { | |
285 std::string dummy_html = "<html><body>Dummy</body></html>"; | |
286 scoped_refptr<base::RefCountedString> response = | |
287 base::RefCountedString::TakeString(&dummy_html); | |
288 callback.Run(response); | |
289 } | |
290 | |
291 std::string GetMimeType(const std::string& path) const OVERRIDE { | |
292 return "text/html"; | |
293 } | |
294 | |
295 DISALLOW_COPY_AND_ASSIGN(MockWebUIDataSource); | |
296 }; | |
297 | |
298 // WebUIProvider to allow attaching the DataSource for the dummy URL when | |
299 // testing. | |
300 class MockWebUIProvider | |
301 : public TestChromeWebUIControllerFactory::WebUIProvider { | |
302 public: | |
303 MockWebUIProvider() {} | |
304 | |
305 // Returns a new WebUI | |
306 WebUIController* NewWebUI(content::WebUI* web_ui, const GURL& url) OVERRIDE { | |
307 WebUIController* controller = new content::WebUIController(web_ui); | |
308 Profile* profile = Profile::FromWebUI(web_ui); | |
309 content::URLDataSource::Add(profile, new MockWebUIDataSource()); | |
310 return controller; | |
311 } | |
312 | |
313 private: | |
314 DISALLOW_COPY_AND_ASSIGN(MockWebUIProvider); | |
315 }; | |
316 | |
317 base::LazyInstance<MockWebUIProvider> mock_provider_ = | |
318 LAZY_INSTANCE_INITIALIZER; | |
319 | |
320 } // namespace | |
321 | |
322 void WebUIBrowserTest::SetUpOnMainThread() { | |
323 logging::SetLogMessageHandler(&LogHandler); | |
324 | |
325 content::WebUIControllerFactory::UnregisterFactoryForTesting( | |
326 ChromeWebUIControllerFactory::GetInstance()); | |
327 | |
328 test_factory_.reset(new TestChromeWebUIControllerFactory); | |
329 | |
330 content::WebUIControllerFactory::RegisterFactory(test_factory_.get()); | |
331 | |
332 test_factory_->AddFactoryOverride( | |
333 GURL(kDummyURL).host(), mock_provider_.Pointer()); | |
334 | |
335 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_)); | |
336 test_data_directory_ = test_data_directory_.Append(kWebUITestFolder); | |
337 ASSERT_TRUE(PathService::Get(chrome::DIR_GEN_TEST_DATA, | |
338 &gen_test_data_directory_)); | |
339 | |
340 // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. | |
341 FilePath resources_pack_path; | |
342 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); | |
343 ResourceBundle::GetSharedInstance().AddDataPackFromPath( | |
344 resources_pack_path, ui::SCALE_FACTOR_NONE); | |
345 | |
346 AddLibraryFromSourceRoot(this, FilePath(kA11yAuditLibraryJSPath)); | |
347 AddLibraryFromSourceRoot(this, FilePath(kMockJSPath)); | |
348 AddLibrary(FilePath(kWebUILibraryJS)); | |
349 } | |
350 | |
351 void WebUIBrowserTest::CleanUpOnMainThread() { | |
352 logging::SetLogMessageHandler(NULL); | |
353 | |
354 test_factory_->RemoveFactoryOverride(GURL(kDummyURL).host()); | |
355 content::WebUIControllerFactory::UnregisterFactoryForTesting( | |
356 test_factory_.get()); | |
357 | |
358 test_factory_.reset(); | |
359 } | |
360 | |
361 void WebUIBrowserTest::SetWebUIInstance(content::WebUI* web_ui) { | |
362 override_selected_web_ui_ = web_ui; | |
363 } | |
364 | |
365 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { | |
366 return NULL; | |
367 } | |
368 | |
369 GURL WebUIBrowserTest::WebUITestDataPathToURL( | |
370 const FilePath::StringType& path) { | |
371 FilePath dir_test_data; | |
372 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &dir_test_data)); | |
373 FilePath test_path(dir_test_data.Append(kWebUITestFolder).Append(path)); | |
374 EXPECT_TRUE(file_util::PathExists(test_path)); | |
375 return net::FilePathToFileURL(test_path); | |
376 } | |
377 | |
378 void WebUIBrowserTest::OnJsInjectionReady(RenderViewHost* render_view_host) { | |
379 PreLoadJavascriptLibraries(preload_test_fixture_, preload_test_name_, | |
380 render_view_host); | |
381 } | |
382 | |
383 void WebUIBrowserTest::BuildJavascriptLibraries(string16* content) { | |
384 ASSERT_TRUE(content != NULL); | |
385 std::string utf8_content; | |
386 std::vector<FilePath>::iterator user_libraries_iterator; | |
387 for (user_libraries_iterator = user_libraries_.begin(); | |
388 user_libraries_iterator != user_libraries_.end(); | |
389 ++user_libraries_iterator) { | |
390 std::string library_content; | |
391 if (user_libraries_iterator->IsAbsolute()) { | |
392 ASSERT_TRUE(file_util::ReadFileToString(*user_libraries_iterator, | |
393 &library_content)) | |
394 << user_libraries_iterator->value(); | |
395 } else { | |
396 bool ok = file_util::ReadFileToString( | |
397 gen_test_data_directory_.Append(*user_libraries_iterator), | |
398 &library_content); | |
399 if (!ok) { | |
400 ok = file_util::ReadFileToString( | |
401 test_data_directory_.Append(*user_libraries_iterator), | |
402 &library_content); | |
403 } | |
404 ASSERT_TRUE(ok) << user_libraries_iterator->value(); | |
405 } | |
406 utf8_content.append(library_content); | |
407 utf8_content.append(";\n"); | |
408 } | |
409 content->append(UTF8ToUTF16(utf8_content)); | |
410 } | |
411 | |
412 string16 WebUIBrowserTest::BuildRunTestJSCall( | |
413 bool is_async, | |
414 const std::string& function_name, | |
415 const WebUIBrowserTest::ConstValueVector& test_func_args) { | |
416 ConstValueVector arguments; | |
417 base::FundamentalValue* is_async_arg = | |
418 base::Value::CreateBooleanValue(is_async); | |
419 arguments.push_back(is_async_arg); | |
420 base::StringValue* function_name_arg = | |
421 base::Value::CreateStringValue(function_name); | |
422 arguments.push_back(function_name_arg); | |
423 base::ListValue* baked_argument_list = new base::ListValue(); | |
424 ConstValueVector::const_iterator arguments_iterator; | |
425 for (arguments_iterator = test_func_args.begin(); | |
426 arguments_iterator != test_func_args.end(); | |
427 ++arguments_iterator) { | |
428 baked_argument_list->Append((*arguments_iterator)->DeepCopy()); | |
429 } | |
430 arguments.push_back(baked_argument_list); | |
431 return content::WebUI::GetJavascriptCall(std::string("runTest"), | |
432 arguments.get()); | |
433 } | |
434 | |
435 bool WebUIBrowserTest::RunJavascriptUsingHandler( | |
436 const std::string& function_name, | |
437 const ConstValueVector& function_arguments, | |
438 bool is_test, | |
439 bool is_async, | |
440 RenderViewHost* preload_host) { | |
441 | |
442 string16 content; | |
443 if (!libraries_preloaded_) | |
444 BuildJavascriptLibraries(&content); | |
445 | |
446 if (!function_name.empty()) { | |
447 string16 called_function; | |
448 if (is_test) { | |
449 called_function = | |
450 BuildRunTestJSCall(is_async, function_name, function_arguments); | |
451 } else { | |
452 called_function = | |
453 content::WebUI::GetJavascriptCall(function_name, | |
454 function_arguments.get()); | |
455 } | |
456 content.append(called_function); | |
457 } | |
458 | |
459 if (!preload_host) | |
460 SetupHandlers(); | |
461 | |
462 bool result = true; | |
463 | |
464 if (is_test) | |
465 result = test_handler_->RunJavaScriptTestWithResult(content); | |
466 else if (preload_host) | |
467 test_handler_->PreloadJavaScript(content, preload_host); | |
468 else | |
469 test_handler_->RunJavaScript(content); | |
470 | |
471 if (error_messages_.Get().size() > 0) { | |
472 LOG(ERROR) << "Encountered javascript console error(s)"; | |
473 result = false; | |
474 error_messages_.Get().clear(); | |
475 } | |
476 return result; | |
477 } | |
478 | |
479 void WebUIBrowserTest::SetupHandlers() { | |
480 content::WebUI* web_ui_instance = override_selected_web_ui_ ? | |
481 override_selected_web_ui_ : | |
482 browser()->tab_strip_model()->GetActiveWebContents()->GetWebUI(); | |
483 ASSERT_TRUE(web_ui_instance != NULL); | |
484 | |
485 test_handler_->set_web_ui(web_ui_instance); | |
486 test_handler_->RegisterMessages(); | |
487 | |
488 if (GetMockMessageHandler()) { | |
489 GetMockMessageHandler()->set_web_ui(web_ui_instance); | |
490 GetMockMessageHandler()->RegisterMessages(); | |
491 } | |
492 } | |
493 | |
494 // According to the interface for EXPECT_FATAL_FAILURE | |
495 // (http://code.google.com/p/googletest/wiki/AdvancedGuide#Catching_Failures) | |
496 // the statement must be statically available. Therefore, we make a static | |
497 // global s_test_ which should point to |this| for the duration of the test run | |
498 // and be cleared afterward. | |
499 class WebUIBrowserExpectFailTest : public WebUIBrowserTest { | |
500 public: | |
501 WebUIBrowserExpectFailTest() { | |
502 EXPECT_FALSE(s_test_); | |
503 s_test_ = this; | |
504 } | |
505 | |
506 protected: | |
507 virtual ~WebUIBrowserExpectFailTest() { | |
508 EXPECT_TRUE(s_test_); | |
509 s_test_ = NULL; | |
510 } | |
511 | |
512 static void RunJavascriptTestNoReturn(const std::string& testname) { | |
513 EXPECT_TRUE(s_test_); | |
514 s_test_->RunJavascriptTest(testname); | |
515 } | |
516 | |
517 static void RunJavascriptAsyncTestNoReturn(const std::string& testname) { | |
518 EXPECT_TRUE(s_test_); | |
519 s_test_->RunJavascriptAsyncTest(testname); | |
520 } | |
521 | |
522 private: | |
523 static WebUIBrowserTest* s_test_; | |
524 }; | |
525 | |
526 WebUIBrowserTest* WebUIBrowserExpectFailTest::s_test_ = NULL; | |
527 | |
528 // Test that bogus javascript fails fast - no timeout waiting for result. | |
529 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestFailsFast) { | |
530 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); | |
531 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | |
532 EXPECT_FATAL_FAILURE(RunJavascriptTestNoReturn("DISABLED_BogusFunctionName"), | |
533 "WebUITestHandler::JavaScriptComplete"); | |
534 } | |
535 | |
536 // Test that bogus javascript fails fast - no timeout waiting for result. | |
537 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestRuntimeErrorFailsFast) { | |
538 AddLibrary(FilePath(FILE_PATH_LITERAL("runtime_error.js"))); | |
539 ui_test_utils::NavigateToURL(browser(), GURL(kDummyURL)); | |
540 EXPECT_FATAL_FAILURE(RunJavascriptTestNoReturn("TestRuntimeErrorFailsFast"), | |
541 "WebUITestHandler::JavaScriptComplete"); | |
542 } | |
543 | |
544 // Test that bogus javascript fails async test fast as well - no timeout waiting | |
545 // for result. | |
546 IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestFailsAsyncFast) { | |
547 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); | |
548 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | |
549 EXPECT_FATAL_FAILURE( | |
550 RunJavascriptAsyncTestNoReturn("DISABLED_BogusFunctionName"), | |
551 "WebUITestHandler::JavaScriptComplete"); | |
552 } | |
553 | |
554 // Tests that the async framework works. | |
555 class WebUIBrowserAsyncTest : public WebUIBrowserTest { | |
556 public: | |
557 // Calls the testDone() function from test_api.js | |
558 void TestDone() { | |
559 RunJavascriptFunction("testDone"); | |
560 } | |
561 | |
562 // Starts a failing test. | |
563 void RunTestFailsAssert() { | |
564 RunJavascriptFunction("runAsync", | |
565 Value::CreateStringValue("testFailsAssert")); | |
566 } | |
567 | |
568 // Starts a passing test. | |
569 void RunTestPasses() { | |
570 RunJavascriptFunction("runAsync", Value::CreateStringValue("testPasses")); | |
571 } | |
572 | |
573 protected: | |
574 WebUIBrowserAsyncTest() {} | |
575 | |
576 // Class to synchronize asynchronous javascript activity with the tests. | |
577 class AsyncWebUIMessageHandler : public WebUIMessageHandler { | |
578 public: | |
579 AsyncWebUIMessageHandler() {} | |
580 | |
581 MOCK_METHOD1(HandleTestContinues, void(const ListValue*)); | |
582 MOCK_METHOD1(HandleTestFails, void(const ListValue*)); | |
583 MOCK_METHOD1(HandleTestPasses, void(const ListValue*)); | |
584 | |
585 private: | |
586 virtual void RegisterMessages() OVERRIDE { | |
587 web_ui()->RegisterMessageCallback("startAsyncTest", | |
588 base::Bind(&AsyncWebUIMessageHandler::HandleStartAsyncTest, | |
589 base::Unretained(this))); | |
590 web_ui()->RegisterMessageCallback("testContinues", | |
591 base::Bind(&AsyncWebUIMessageHandler::HandleTestContinues, | |
592 base::Unretained(this))); | |
593 web_ui()->RegisterMessageCallback("testFails", | |
594 base::Bind(&AsyncWebUIMessageHandler::HandleTestFails, | |
595 base::Unretained(this))); | |
596 web_ui()->RegisterMessageCallback("testPasses", | |
597 base::Bind(&AsyncWebUIMessageHandler::HandleTestPasses, | |
598 base::Unretained(this))); | |
599 } | |
600 | |
601 // Starts the test in |list_value|[0] with the runAsync wrapper. | |
602 void HandleStartAsyncTest(const ListValue* list_value) { | |
603 const Value* test_name; | |
604 ASSERT_TRUE(list_value->Get(0, &test_name)); | |
605 web_ui()->CallJavascriptFunction("runAsync", *test_name); | |
606 } | |
607 | |
608 DISALLOW_COPY_AND_ASSIGN(AsyncWebUIMessageHandler); | |
609 }; | |
610 | |
611 // Handler for this object. | |
612 ::testing::StrictMock<AsyncWebUIMessageHandler> message_handler_; | |
613 | |
614 private: | |
615 // Provide this object's handler. | |
616 virtual WebUIMessageHandler* GetMockMessageHandler() OVERRIDE { | |
617 return &message_handler_; | |
618 } | |
619 | |
620 // Set up and browse to kDummyURL for all tests. | |
621 virtual void SetUpOnMainThread() OVERRIDE { | |
622 WebUIBrowserTest::SetUpOnMainThread(); | |
623 AddLibrary(FilePath(FILE_PATH_LITERAL("async.js"))); | |
624 ui_test_utils::NavigateToURL(browser(), GURL(kDummyURL)); | |
625 } | |
626 | |
627 DISALLOW_COPY_AND_ASSIGN(WebUIBrowserAsyncTest); | |
628 }; | |
629 | |
630 // Test that assertions fail immediately after assertion fails (no testContinues | |
631 // message). (Sync version). | |
632 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestSyncOkTestFail) { | |
633 ASSERT_FALSE(RunJavascriptTest("testFailsAssert")); | |
634 } | |
635 | |
636 // Test that assertions fail immediately after assertion fails (no testContinues | |
637 // message). (Async version). | |
638 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncFailsAssert) { | |
639 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); | |
640 ASSERT_FALSE(RunJavascriptAsyncTest( | |
641 "startAsyncTest", Value::CreateStringValue("testFailsAssert"))); | |
642 } | |
643 | |
644 // Test that expectations continue the function, but fail the test. | |
645 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncFailsExpect) { | |
646 ::testing::InSequence s; | |
647 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
648 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); | |
649 ASSERT_FALSE(RunJavascriptAsyncTest( | |
650 "startAsyncTest", Value::CreateStringValue("testFailsExpect"))); | |
651 } | |
652 | |
653 // Test that test continues and passes. (Sync version). | |
654 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestSyncPasses) { | |
655 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
656 ASSERT_TRUE(RunJavascriptTest("testPasses")); | |
657 } | |
658 | |
659 // Test that test continues and passes. (Async version). | |
660 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPasses) { | |
661 ::testing::InSequence s; | |
662 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
663 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) | |
664 .WillOnce(::testing::InvokeWithoutArgs( | |
665 this, &WebUIBrowserAsyncTest::TestDone)); | |
666 ASSERT_TRUE(RunJavascriptAsyncTest( | |
667 "startAsyncTest", Value::CreateStringValue("testPasses"))); | |
668 } | |
669 | |
670 // Test that two tests pass. | |
671 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPassPass) { | |
672 ::testing::InSequence s; | |
673 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
674 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) | |
675 .WillOnce(::testing::InvokeWithoutArgs( | |
676 this, &WebUIBrowserAsyncTest::RunTestPasses)); | |
677 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
678 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) | |
679 .WillOnce(::testing::InvokeWithoutArgs( | |
680 this, &WebUIBrowserAsyncTest::TestDone)); | |
681 ASSERT_TRUE(RunJavascriptAsyncTest( | |
682 "startAsyncTest", Value::CreateStringValue("testPasses"))); | |
683 } | |
684 | |
685 // Test that first test passes; second fails. | |
686 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncPassThenFail) { | |
687 ::testing::InSequence s; | |
688 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
689 EXPECT_CALL(message_handler_, HandleTestPasses(::testing::_)) | |
690 .WillOnce(::testing::InvokeWithoutArgs( | |
691 this, &WebUIBrowserAsyncTest::RunTestFailsAssert)); | |
692 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); | |
693 ASSERT_FALSE(RunJavascriptAsyncTest( | |
694 "startAsyncTest", Value::CreateStringValue("testPasses"))); | |
695 } | |
696 | |
697 // Test that testDone() with failure first then sync pass still fails. | |
698 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestAsyncDoneFailFirstSyncPass) { | |
699 ::testing::InSequence s; | |
700 EXPECT_CALL(message_handler_, HandleTestContinues(::testing::_)); | |
701 EXPECT_CALL(message_handler_, HandleTestFails(::testing::_)); | |
702 | |
703 // Call runAsync directly instead of deferring through startAsyncTest. It will | |
704 // call testDone() on failure, then return. | |
705 ASSERT_FALSE(RunJavascriptAsyncTest( | |
706 "runAsync", Value::CreateStringValue("testAsyncDoneFailFirstSyncPass"))); | |
707 } | |
708 | |
709 // Test that calling testDone during RunJavascriptAsyncTest still completes | |
710 // when waiting for async result. This is similar to the previous test, but call | |
711 // testDone directly and expect pass result. | |
712 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestTestDoneEarlyPassesAsync) { | |
713 ASSERT_TRUE(RunJavascriptAsyncTest("testDone")); | |
714 } | |
715 | |
716 // Test that calling testDone during RunJavascriptTest still completes when | |
717 // waiting for async result. | |
718 IN_PROC_BROWSER_TEST_F(WebUIBrowserAsyncTest, TestTestDoneEarlyPasses) { | |
719 ASSERT_TRUE(RunJavascriptTest("testDone")); | |
720 } | |
OLD | NEW |