Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / dom_distiller / content / browser / test / dom_distiller_js_browsertest.cc
blob44572d2d15d16b6f085ca4d5d4943cc9730913c1
1 // Copyright 2015 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.
5 #include "base/callback.h"
6 #include "base/location.h"
7 #include "base/logging.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/time/time.h"
14 #include "base/values.h"
15 #include "components/dom_distiller/content/browser/web_contents_main_frame_observer.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "content/public/test/content_browser_test.h"
20 #include "content/shell/browser/shell.h"
21 #include "net/test/embedded_test_server/embedded_test_server.h"
22 #include "ui/base/resource/resource_bundle.h"
24 namespace {
26 // Helper class to know how far in the loading process the current WebContents
27 // has come. It will call the callback after DocumentLoadedInFrame is called for
28 // the main frame.
29 class WebContentsMainFrameHelper : public content::WebContentsObserver {
30 public:
31 WebContentsMainFrameHelper(content::WebContents* web_contents,
32 const base::Closure& callback)
33 : WebContentsObserver(web_contents), callback_(callback) {}
35 void DocumentLoadedInFrame(
36 content::RenderFrameHost* render_frame_host) override {
37 if (!render_frame_host->GetParent())
38 callback_.Run();
41 private:
42 base::Closure callback_;
45 } // namespace
47 namespace dom_distiller {
49 const char* kExternalTestResourcesPath =
50 "third_party/dom_distiller_js/dist/test/data";
51 // TODO(wychen) Remove filter when crbug.com/471854 is fixed.
52 const char* kTestFilePath =
53 "/war/test.html?console_log=0&filter=-*.SchemaOrgParserAccessorTest.*";
54 const char* kRunJsTestsJs =
55 "(function() {return org.chromium.distiller.JsTestEntry.run();})();";
57 class DomDistillerJsTest : public content::ContentBrowserTest {
58 public:
59 DomDistillerJsTest() : result_(NULL) {}
61 // content::ContentBrowserTest:
62 void SetUpOnMainThread() override {
63 AddComponentsResources();
64 SetUpTestServer();
65 content::ContentBrowserTest::SetUpOnMainThread();
68 void OnJsTestExecutionDone(const base::Value* value) {
69 result_ = value->DeepCopy();
70 js_test_execution_done_callback_.Run();
73 protected:
74 base::Closure js_test_execution_done_callback_;
75 const base::Value* result_;
77 private:
78 void AddComponentsResources() {
79 base::FilePath pak_file;
80 base::FilePath pak_dir;
81 #if defined(OS_ANDROID)
82 CHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_dir));
83 pak_dir = pak_dir.Append(FILE_PATH_LITERAL("paks"));
84 #else
85 PathService::Get(base::DIR_MODULE, &pak_dir);
86 #endif // OS_ANDROID
87 pak_file =
88 pak_dir.Append(FILE_PATH_LITERAL("components_tests_resources.pak"));
89 ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
90 pak_file, ui::SCALE_FACTOR_NONE);
93 void SetUpTestServer() {
94 base::FilePath path;
95 PathService::Get(base::DIR_SOURCE_ROOT, &path);
96 path = path.AppendASCII(kExternalTestResourcesPath);
97 embedded_test_server()->ServeFilesFromDirectory(path);
98 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
102 IN_PROC_BROWSER_TEST_F(DomDistillerJsTest, RunJsTests) {
103 // Load the test file in content shell and wait until it has fully loaded.
104 content::WebContents* web_contents = shell()->web_contents();
105 dom_distiller::WebContentsMainFrameObserver::CreateForWebContents(
106 web_contents);
107 base::RunLoop url_loaded_runner;
108 WebContentsMainFrameHelper main_frame_loaded(web_contents,
109 url_loaded_runner.QuitClosure());
110 web_contents->GetController().LoadURL(
111 embedded_test_server()->GetURL(kTestFilePath),
112 content::Referrer(),
113 ui::PAGE_TRANSITION_TYPED,
114 std::string());
115 url_loaded_runner.Run();
117 // Execute the JS to run the tests, and wait until it has finished.
118 base::RunLoop run_loop;
119 js_test_execution_done_callback_ = run_loop.QuitClosure();
120 // Add timeout in case JS Test execution fails. It is safe to call the
121 // QuitClosure multiple times.
122 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
123 FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(15));
124 web_contents->GetMainFrame()->ExecuteJavaScriptForTests(
125 base::UTF8ToUTF16(kRunJsTestsJs),
126 base::Bind(&DomDistillerJsTest::OnJsTestExecutionDone,
127 base::Unretained(this)));
128 run_loop.Run();
130 // By now either the timeout has triggered, or there should be a result.
131 ASSERT_TRUE(result_ != NULL) << "No result found. Timeout?";
133 // Convert to dictionary and parse the results.
134 const base::DictionaryValue* dict;
135 result_->GetAsDictionary(&dict);
136 ASSERT_TRUE(result_->GetAsDictionary(&dict));
138 ASSERT_TRUE(dict->HasKey("success"));
139 bool success;
140 ASSERT_TRUE(dict->GetBoolean("success", &success));
142 ASSERT_TRUE(dict->HasKey("numTests"));
143 int num_tests;
144 ASSERT_TRUE(dict->GetInteger("numTests", &num_tests));
146 ASSERT_TRUE(dict->HasKey("failed"));
147 int failed;
148 ASSERT_TRUE(dict->GetInteger("failed", &failed));
150 ASSERT_TRUE(dict->HasKey("skipped"));
151 int skipped;
152 ASSERT_TRUE(dict->GetInteger("skipped", &skipped));
154 VLOG(0) << "Ran " << num_tests << " tests. failed = " << failed
155 << " skipped = " << skipped;
156 // Ensure that running the tests succeeded.
157 EXPECT_TRUE(success);
159 // Only print the log if there was an error.
160 if (!success) {
161 ASSERT_TRUE(dict->HasKey("log"));
162 std::string console_log;
163 ASSERT_TRUE(dict->GetString("log", &console_log));
164 VLOG(0) << "Console log:\n" << console_log;
168 } // namespace dom_distiller