OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "chrome/browser/ui/webui/web_ui_browsertest.h" | 4 #include "chrome/browser/ui/webui/web_ui_browsertest.h" |
5 | 5 |
6 #include <string> | 6 #include <string> |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/at_exit.h" | |
10 #include "base/lazy_instance.h" | |
11 #include "base/memory/singleton.h" | |
9 #include "base/path_service.h" | 12 #include "base/path_service.h" |
10 #include "base/values.h" | 13 #include "base/values.h" |
11 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
12 #include "chrome/common/chrome_paths.h" | 15 #include "chrome/common/chrome_paths.h" |
13 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
14 #include "chrome/test/ui_test_utils.h" | 17 #include "chrome/test/ui_test_utils.h" |
15 #include "content/browser/tab_contents/tab_contents.h" | 18 #include "content/browser/tab_contents/tab_contents.h" |
16 #include "content/browser/webui/web_ui.h" | 19 #include "content/browser/webui/web_ui.h" |
17 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
21 #include "v8/include/v8.h" | |
18 | 22 |
19 static const FilePath::CharType* kWebUILibraryJS = | 23 namespace { |
20 FILE_PATH_LITERAL("test_api.js"); | 24 const FilePath::CharType* kWebUILibraryJS = FILE_PATH_LITERAL("test_api.js"); |
21 static const FilePath::CharType* kWebUITestFolder = FILE_PATH_LITERAL("webui"); | 25 const FilePath::CharType* kWebUITestFolder = FILE_PATH_LITERAL("webui"); |
22 static std::vector<std::string> error_messages_; | 26 |
27 base::LazyInstance<std::vector<std::string> > error_messages_( | |
28 base::LINKER_INITIALIZED); | |
29 | |
30 // GTEST registration happens at linker initialization. When | |
31 // |linker_initialized| is true, set up and tear down enough to enable the | |
32 // PathService to give us path to the test data directory. | |
33 FilePath GetTestDataDirectory(bool linker_initialized) { | |
34 scoped_ptr<base::AtExitManager> at_exit_manager; | |
35 if (linker_initialized) { | |
36 at_exit_manager.reset(new base::AtExitManager()); | |
37 chrome::RegisterPathProvider(); | |
38 } | |
39 | |
40 FilePath test_data_directory; | |
41 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory)); | |
42 return test_data_directory.Append(kWebUITestFolder); | |
43 } | |
23 | 44 |
24 // Intercepts all log messages. | 45 // Intercepts all log messages. |
25 bool LogHandler(int severity, | 46 bool LogHandler(int severity, |
26 const char* file, | 47 const char* file, |
27 int line, | 48 int line, |
28 size_t message_start, | 49 size_t message_start, |
29 const std::string& str) { | 50 const std::string& str) { |
30 if (severity == logging::LOG_ERROR) { | 51 if (severity == logging::LOG_ERROR) { |
31 error_messages_.push_back(str); | 52 error_messages_.Get().push_back(str); |
32 return true; | 53 return true; |
33 } else { | 54 } else { |
34 // For debugging messages while developing tests. | 55 // For debugging messages while developing tests. |
35 return false; | 56 return false; |
36 } | 57 } |
37 } | 58 } |
38 | 59 |
60 // Read the specified |library| into |content|, prepending |test_data_directory| | |
61 // when |library| is relative. | |
62 void ReadLibraryToString(const FilePath& test_data_directory, | |
63 const FilePath& library, | |
64 std::string* content) { | |
65 ASSERT_TRUE(content); | |
66 if (library.IsAbsolute()) { | |
Paweł Hajdan Jr.
2011/05/30 17:17:58
I think this may be error prone. Could you add two
Sheridan Rawlins
2011/05/31 23:15:00
David says we don't need the absolute case. I'll
Sheridan Rawlins
2011/06/08 14:24:45
The BIDI checker uses third party test script. Pu
| |
67 ASSERT_TRUE(file_util::ReadFileToString(library, content)); | |
68 } else { | |
69 ASSERT_TRUE(file_util::ReadFileToString(test_data_directory.Append(library), | |
70 content)); | |
71 } | |
72 } | |
73 | |
74 // Gets functions defined in |library_path| starting with "test". |testFuncs| | |
75 // may not be NULL. | |
76 bool GetTestFuncs(const FilePath& library_path, | |
77 std::vector<std::string>* testFuncs) { | |
78 DCHECK(testFuncs); | |
79 | |
80 std::string content = "var window = {};"; | |
81 ReadLibraryToString(GetTestDataDirectory(true), library_path, &content); | |
82 content.append( | |
83 "(function () {" | |
David Tseng
2011/05/30 20:44:49
Is there some way we can ask V8 to give us back th
Sheridan Rawlins
2011/05/31 23:15:00
The only way to get a variable from javascript is
| |
84 " var funcs = new Array();" | |
85 " for (var func in this) {" | |
86 " if (typeof this[func] == 'function')" | |
87 " funcs.push(func);" | |
88 " }" | |
89 " return funcs;" | |
90 "})()"); | |
91 | |
92 v8::HandleScope handle_scope; | |
93 v8::Persistent<v8::Context> context = v8::Context::New(); | |
94 v8::Context::Scope context_scope(context); | |
95 v8::Handle<v8::String> source = v8::String::New(content.data(), | |
96 content.size()); | |
97 v8::Handle<v8::Script> script = v8::Script::Compile(source); | |
98 v8::TryCatch trycatch; | |
99 v8::Handle<v8::Array> result = script->Run().As<v8::Array>(); | |
100 context.Dispose(); | |
101 if (result.IsEmpty()) { | |
102 v8::Handle<v8::Value> exception = trycatch.Exception(); | |
103 v8::String::AsciiValue exception_str(exception); | |
104 NOTREACHED() << "Exception: " << *exception_str; | |
Paweł Hajdan Jr.
2011/05/30 17:17:58
Why should a JS exception crash the entire test (t
Sheridan Rawlins
2011/05/31 23:15:00
Keep in mind this is a JS exception in examining t
| |
105 return false; | |
106 } | |
107 | |
108 for (uint32_t index = 0; index < result->Length(); ++index) { | |
109 v8::Local<v8::String> value(result->Get(index).As<v8::String>()); | |
110 if (value.IsEmpty()) { | |
111 return false; | |
112 } | |
113 v8::String::AsciiValue ascii(value); | |
114 testFuncs->push_back(std::string(*ascii, ascii.length())); | |
115 } | |
116 return true; | |
117 } | |
118 | |
119 } // namespace | |
120 | |
39 WebUIBrowserTest::~WebUIBrowserTest() {} | 121 WebUIBrowserTest::~WebUIBrowserTest() {} |
40 | 122 |
41 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { | 123 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name) { |
42 return RunJavascriptFunction(function_name, ConstValueVector()); | 124 return RunJavascriptFunction(function_name, ConstValueVector()); |
43 } | 125 } |
44 | 126 |
45 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, | 127 bool WebUIBrowserTest::RunJavascriptFunction(const std::string& function_name, |
46 const Value& arg) { | 128 const Value& arg) { |
47 ConstValueVector args; | 129 ConstValueVector args; |
48 args.push_back(&arg); | 130 args.push_back(&arg); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 bool WebUIBrowserTest::RunJavascriptTest( | 169 bool WebUIBrowserTest::RunJavascriptTest( |
88 const std::string& test_name, | 170 const std::string& test_name, |
89 const ConstValueVector& test_arguments) { | 171 const ConstValueVector& test_arguments) { |
90 return RunJavascriptUsingHandler(test_name, test_arguments, true); | 172 return RunJavascriptUsingHandler(test_name, test_arguments, true); |
91 } | 173 } |
92 | 174 |
93 WebUIBrowserTest::WebUIBrowserTest() | 175 WebUIBrowserTest::WebUIBrowserTest() |
94 : test_handler_(new WebUITestHandler()) {} | 176 : test_handler_(new WebUITestHandler()) {} |
95 | 177 |
96 void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() { | 178 void WebUIBrowserTest::SetUpInProcessBrowserTestFixture() { |
97 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_)); | 179 test_data_directory_ = GetTestDataDirectory(false); |
98 test_data_directory_ = test_data_directory_.Append(kWebUITestFolder); | |
99 | 180 |
100 // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. | 181 // TODO(dtseng): should this be part of every BrowserTest or just WebUI test. |
101 FilePath resources_pack_path; | 182 FilePath resources_pack_path; |
102 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); | 183 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); |
103 ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); | 184 ResourceBundle::AddDataPackToSharedInstance(resources_pack_path); |
104 | 185 |
105 AddLibrary(FilePath(kWebUILibraryJS)); | 186 AddLibrary(FilePath(kWebUILibraryJS)); |
106 } | 187 } |
107 | 188 |
108 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { | 189 WebUIMessageHandler* WebUIBrowserTest::GetMockMessageHandler() { |
109 return NULL; | 190 return NULL; |
110 } | 191 } |
111 | 192 |
112 void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) { | 193 int WebUIBrowserTest::AddJSToRegistry( |
194 const FilePath& library_path, | |
195 const char* test_case_name, const char* name, | |
196 const char* type_param, | |
197 const char* value_param, | |
198 ::testing::internal::TypeId fixture_class_id, | |
199 ::testing::internal::SetUpTestCaseFunc set_up_tc, | |
200 ::testing::internal::TearDownTestCaseFunc tear_down_tc, | |
201 ::testing::internal::TestMetaFactoryBase<std::string>* meta_factory) { | |
202 std::vector<std::string> testFuncs; | |
203 EXPECT_TRUE(GetTestFuncs(library_path, &testFuncs)); | |
204 for (std::vector<std::string>::const_iterator it = testFuncs.begin(); | |
205 it != testFuncs.end(); ++it) { | |
206 std::string test_name = *it + "/" + name; | |
David Tseng
2011/05/30 20:44:49
Should
std::string test_name = *it + "/" + nam
Sheridan Rawlins
2011/05/31 23:15:00
I prefer to have the C++ Testname available (as me
| |
207 ::testing::internal::MakeAndRegisterTestInfo( | |
208 test_case_name, test_name.c_str(), | |
209 type_param, | |
210 value_param, | |
211 fixture_class_id, | |
212 set_up_tc, | |
213 tear_down_tc, | |
214 meta_factory->CreateTestFactory(*it)); | |
215 } | |
216 return testFuncs.size(); | |
217 } | |
218 | |
219 void WebUIBrowserTest::BuildJavascriptLibraries(std::string* content) const { | |
113 ASSERT_TRUE(content != NULL); | 220 ASSERT_TRUE(content != NULL); |
114 std::string library_content, src_content; | 221 std::string library_content; |
115 | 222 |
116 std::vector<FilePath>::iterator user_libraries_iterator; | 223 std::vector<FilePath>::const_iterator user_libraries_iterator; |
117 for (user_libraries_iterator = user_libraries.begin(); | 224 for (user_libraries_iterator = user_libraries_.begin(); |
118 user_libraries_iterator != user_libraries.end(); | 225 user_libraries_iterator != user_libraries_.end(); |
119 ++user_libraries_iterator) { | 226 ++user_libraries_iterator) { |
120 if (user_libraries_iterator->IsAbsolute()) { | 227 ReadLibraryToString(test_data_directory_, *user_libraries_iterator, |
121 ASSERT_TRUE(file_util::ReadFileToString(*user_libraries_iterator, | 228 &library_content); |
122 &library_content)); | |
123 } else { | |
124 ASSERT_TRUE(file_util::ReadFileToString( | |
125 test_data_directory_.Append(*user_libraries_iterator), | |
126 &library_content)); | |
127 } | |
128 content->append(library_content); | 229 content->append(library_content); |
129 content->append(";\n"); | 230 content->append(";\n"); |
130 } | 231 } |
131 } | 232 } |
132 | 233 |
133 string16 WebUIBrowserTest::BuildRunTestJSCall( | 234 string16 WebUIBrowserTest::BuildRunTestJSCall( |
134 const std::string& function_name, | 235 const std::string& function_name, |
135 const WebUIBrowserTest::ConstValueVector& test_func_args) { | 236 const WebUIBrowserTest::ConstValueVector& test_func_args) { |
136 WebUIBrowserTest::ConstValueVector arguments; | 237 WebUIBrowserTest::ConstValueVector arguments; |
137 StringValue function_name_arg(function_name); | 238 StringValue function_name_arg(function_name); |
(...skipping 24 matching lines...) Expand all Loading... | |
162 called_function = WebUI::GetJavascriptCall(function_name, | 263 called_function = WebUI::GetJavascriptCall(function_name, |
163 function_arguments); | 264 function_arguments); |
164 } | 265 } |
165 content.append(UTF16ToUTF8(called_function)); | 266 content.append(UTF16ToUTF8(called_function)); |
166 } | 267 } |
167 SetupHandlers(); | 268 SetupHandlers(); |
168 logging::SetLogMessageHandler(&LogHandler); | 269 logging::SetLogMessageHandler(&LogHandler); |
169 bool result = test_handler_->RunJavascript(content, is_test); | 270 bool result = test_handler_->RunJavascript(content, is_test); |
170 logging::SetLogMessageHandler(NULL); | 271 logging::SetLogMessageHandler(NULL); |
171 | 272 |
172 if (error_messages_.size() > 0) { | 273 if (error_messages_.Get().size() > 0) { |
173 LOG(ERROR) << "Encountered javascript console error(s)"; | 274 LOG(ERROR) << "Encountered javascript console error(s)"; |
174 result = false; | 275 result = false; |
175 error_messages_.clear(); | 276 error_messages_.Get().clear(); |
176 } | 277 } |
177 return result; | 278 return result; |
178 } | 279 } |
179 | 280 |
180 void WebUIBrowserTest::SetupHandlers() { | 281 void WebUIBrowserTest::SetupHandlers() { |
181 WebUI* web_ui_instance = | 282 WebUI* web_ui_instance = |
182 browser()->GetSelectedTabContents()->web_ui(); | 283 browser()->GetSelectedTabContents()->web_ui(); |
183 ASSERT_TRUE(web_ui_instance != NULL); | 284 ASSERT_TRUE(web_ui_instance != NULL); |
184 web_ui_instance->register_callback_overwrites(true); | 285 web_ui_instance->register_callback_overwrites(true); |
185 test_handler_->Attach(web_ui_instance); | 286 test_handler_->Attach(web_ui_instance); |
186 | 287 |
187 if (GetMockMessageHandler()) | 288 if (GetMockMessageHandler()) |
188 GetMockMessageHandler()->Attach(web_ui_instance); | 289 GetMockMessageHandler()->Attach(web_ui_instance); |
189 } | 290 } |
190 | 291 |
191 void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { | 292 void WebUIBrowserTest::AddLibrary(const FilePath& library_path) { |
192 user_libraries.push_back(library_path); | 293 user_libraries_.push_back(library_path); |
193 } | 294 } |
194 | 295 |
195 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { | 296 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSamplePass) { |
196 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_downloads.js"))); | 297 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_passing.js"))); |
197 | 298 |
198 // Navigate to UI. | 299 // Navigate to UI. |
199 // TODO(dtseng): make accessor for subclasses to return? | 300 // TODO(dtseng): make accessor for subclasses to return? |
200 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | 301 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); |
201 | 302 |
202 ASSERT_TRUE(RunJavascriptTest("testAssertFalse")); | 303 ASSERT_TRUE(RunJavascriptTest("testAssertFalse")); |
203 ASSERT_TRUE(RunJavascriptTest("testInitialFocus")); | 304 ASSERT_TRUE(RunJavascriptTest("testInitialFocus")); |
305 } | |
306 | |
307 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, TestSampleFail) { | |
308 AddLibrary(FilePath(FILE_PATH_LITERAL("sample_failing.js"))); | |
309 | |
310 // Navigate to UI. | |
311 // TODO(dtseng): make accessor for subclasses to return? | |
312 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | |
313 | |
204 ASSERT_FALSE(RunJavascriptTest("testConsoleError")); | 314 ASSERT_FALSE(RunJavascriptTest("testConsoleError")); |
205 } | 315 } |
316 | |
317 WEB_UI_BROWSER_TEST_JS(WebUIBrowserTest, TestJSPass, | |
318 FILE_PATH_LITERAL("sample_passing.js")) { | |
319 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | |
320 } | |
321 | |
322 WEB_UI_BROWSER_TEST_JS_FALSE(WebUIBrowserTest, TestJSFail, | |
323 FILE_PATH_LITERAL("sample_failing.js")) { | |
324 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); | |
325 } | |
OLD | NEW |