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()) { |
| 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 () {" |
| 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; |
| 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; |
| 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 |