| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_TEST_BASE_WEB_UI_BROWSER_TEST_H_ |
| #define CHROME_TEST_BASE_WEB_UI_BROWSER_TEST_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/memory/raw_ptr.h" |
| #include "chrome/browser/ui/webui/web_ui_test_handler.h" |
| #include "chrome/test/base/devtools_listener.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/javascript_browser_test.h" |
| #include "content/public/browser/devtools_agent_host_observer.h" |
| |
| namespace { |
| class WebUITestMessageHandler; |
| |
| // Observes new DevToolsAgentHost's and ensures code coverage is enabled and |
| // can be collected. |
| class WebUICoverageObserver : public content::DevToolsAgentHostObserver { |
| public: |
| explicit WebUICoverageObserver(base::FilePath devtools_code_coverage_dir); |
| ~WebUICoverageObserver() override; |
| |
| bool CoverageEnabled(); |
| void CollectCoverage(const std::string& test_name); |
| |
| protected: |
| // content::DevToolsAgentHostObserver |
| bool ShouldForceDevToolsAgentHostCreation() override; |
| void DevToolsAgentHostCreated(content::DevToolsAgentHost* host) override; |
| void DevToolsAgentHostAttached(content::DevToolsAgentHost* host) override; |
| void DevToolsAgentHostNavigated(content::DevToolsAgentHost* host) override; |
| void DevToolsAgentHostDetached(content::DevToolsAgentHost* host) override; |
| void DevToolsAgentHostCrashed(content::DevToolsAgentHost* host, |
| base::TerminationStatus status) override; |
| |
| private: |
| using DevToolsAgentMap = // agent hosts: have a unique devtools listener |
| std::map<content::DevToolsAgentHost*, |
| std::unique_ptr<coverage::DevToolsListener>>; |
| base::FilePath devtools_code_coverage_dir_; |
| DevToolsAgentMap devtools_agent_; |
| }; |
| |
| } // namespace |
| |
| namespace base { |
| class Value; |
| } // namespace base |
| |
| namespace content { |
| class RenderFrameHost; |
| class ScopedWebUIControllerFactoryRegistration; |
| class WebUI; |
| } // namespace content |
| |
| class TestChromeWebUIControllerFactory; |
| |
| // The runner of WebUI javascript based tests. |
| // See chrome/test/data/webui/test_api.js for the javascript side test API's. |
| // |
| // These tests should follow the form given in: |
| // chrome/test/data/webui/sample_downloads.js. |
| // and the lone test within this class. |
| class BaseWebUIBrowserTest : public JavaScriptBrowserTest { |
| public: |
| ~BaseWebUIBrowserTest() override; |
| |
| // Runs a javascript function in the context of all libraries. |
| // Note that calls to functions in test_api.js are not supported. |
| // Takes ownership of Value* arguments. |
| bool RunJavascriptFunction(const std::string& function_name); |
| bool RunJavascriptFunction(const std::string& function_name, base::Value arg); |
| bool RunJavascriptFunction(const std::string& function_name, |
| base::Value arg1, |
| base::Value arg2); |
| bool RunJavascriptFunction(const std::string& function_name, |
| std::vector<base::Value> function_arguments); |
| |
| // Runs a test fixture that may include calls to functions in test_api.js. |
| bool RunJavascriptTestF(bool is_async, |
| const std::string& test_fixture, |
| const std::string& test_name); |
| |
| // Runs a test that may include calls to functions in test_api.js. |
| // Takes ownership of Value* arguments. |
| bool RunJavascriptTest(const std::string& test_name); |
| bool RunJavascriptTest(const std::string& test_name, base::Value arg); |
| bool RunJavascriptTest(const std::string& test_name, |
| base::Value arg1, |
| base::Value arg2); |
| bool RunJavascriptTest(const std::string& test_name, |
| std::vector<base::Value> test_arguments); |
| |
| // Runs a test that may include calls to functions in test_api.js, and waits |
| // for call to testDone(). Takes ownership of Value* arguments. |
| bool RunJavascriptAsyncTest(const std::string& test_name); |
| bool RunJavascriptAsyncTest(const std::string& test_name, base::Value arg); |
| bool RunJavascriptAsyncTest(const std::string& test_name, |
| base::Value arg1, |
| base::Value arg2); |
| bool RunJavascriptAsyncTest(const std::string& test_name, |
| base::Value arg1, |
| base::Value arg2, |
| base::Value arg3); |
| bool RunJavascriptAsyncTest(const std::string& test_name, |
| std::vector<base::Value> test_arguments); |
| |
| // Sends message through |preload_frame| to preload javascript libraries and |
| // sets the |libraries_preloaded| flag to prevent re-loading at next |
| // javascript invocation. |
| void PreLoadJavascriptLibraries(const std::string& preload_test_fixture, |
| const std::string& preload_test_name, |
| content::RenderFrameHost* preload_frame); |
| |
| // Called by javascript-generated test bodies to browse to a page and preload |
| // the javascript for the given |preload_test_fixture| and |
| // |preload_test_name|. chrome.send will be overridden to allow javascript |
| // handler mocking. |
| virtual void BrowsePreload(const GURL& browse_to); |
| |
| protected: |
| // URL to dummy WebUI page for testing framework. |
| static const std::string kDummyURL; |
| |
| BaseWebUIBrowserTest(); |
| |
| // Accessors for preload test fixture and name. |
| void set_preload_test_fixture(const std::string& preload_test_fixture); |
| void set_preload_test_name(const std::string& preload_test_name); |
| |
| void set_webui_host(const std::string& webui_host); |
| |
| // Enable command line flags for test. |
| void SetUpCommandLine(base::CommandLine* command_line) override; |
| |
| // Set up & tear down console error catching. |
| void SetUpOnMainThread() override; |
| void TearDownOnMainThread() override; |
| |
| // Set a WebUI instance to run tests on. |
| void SetWebUIInstance(content::WebUI* web_ui); |
| |
| // Returns a mock WebUI object under test (if any). |
| virtual content::WebUIMessageHandler* GetMockMessageHandler(); |
| |
| content::WebUI* override_selected_web_ui() { |
| return override_selected_web_ui_; |
| } |
| |
| // Returns a file:// GURL constructed from |path| inside the test data dir for |
| // webui tests. |
| static GURL WebUITestDataPathToURL(const base::FilePath::StringType& path); |
| |
| // Attaches mock and test handlers. |
| virtual void SetupHandlers() = 0; |
| |
| WebUITestHandler* test_handler() { return test_handler_.get(); } |
| void set_test_handler(std::unique_ptr<WebUITestHandler> test_handler) { |
| test_handler_ = std::move(test_handler); |
| } |
| |
| // Handles collection of code coverage. |
| std::unique_ptr<WebUICoverageObserver> coverage_handler_; |
| |
| private: |
| // Loads all libraries added with AddLibrary(), and calls |function_name| with |
| // |function_arguments|. When |is_test| is true, the framework wraps |
| // |function_name| with a test helper function, which waits for completion, |
| // logging an error message on failure, otherwise |function_name| is called |
| // asynchronously. When |preload_frame| is non-NULL, sends the javascript to |
| // the renderer frame for evaluation at the appropriate time before the onload |
| // call is made. Passes |is_async| along to runTest wrapper. |
| bool RunJavascriptUsingHandler(const std::string& function_name, |
| std::vector<base::Value> function_arguments, |
| bool is_test, |
| bool is_async, |
| content::RenderFrameHost* preload_frame); |
| |
| // Handles test framework messages. |
| std::unique_ptr<WebUITestHandler> test_handler_; |
| |
| // Tracks the frames for which we've preloaded libraries. |
| // |
| // We use `GlobalRenderFrameHostId` because in certain cases, e.g. COOP/COEP, |
| // the frame gets swapped during the navigation and we get two calls to |
| // `WebContentsObserver::RenderFrameCreated()` (where we preload libraries). |
| // |
| // In the COOP/COEP case, `RenderFrameCreated()` is called for a speculative |
| // RFH when the navigation starts, then at response time, after parsing the |
| // headers, we realize that we need a new COOP/COEP-enabled SiteInstance, so |
| // we'll create a different RFH for that SiteInstance and dispatch |
| // `RenderFrameCreated()` for that RFH (and throw away the old speculative |
| // RFH). |
| std::set<content::GlobalRenderFrameHostId> libraries_preloaded_for_frames_; |
| |
| // Saves the states of |test_fixture| and |test_name| for calling |
| // PreloadJavascriptLibraries(). |
| std::string preload_test_fixture_; |
| std::string preload_test_name_; |
| |
| // When this is non-NULL, this is The WebUI instance used for testing. |
| // Otherwise the selected tab's web_ui is used. |
| raw_ptr<content::WebUI> override_selected_web_ui_ = nullptr; |
| |
| std::unique_ptr<TestChromeWebUIControllerFactory> test_factory_; |
| std::unique_ptr<content::ScopedWebUIControllerFactoryRegistration> |
| factory_registration_; |
| }; |
| |
| class WebUIBrowserTest : public BaseWebUIBrowserTest { |
| public: |
| WebUIBrowserTest(); |
| ~WebUIBrowserTest() override; |
| |
| void SetupHandlers() override; |
| |
| void CollectCoverage(const std::string& test_name); |
| |
| private: |
| // Owned by |test_handler_| in BaseWebUIBrowserTest. |
| const raw_ptr<WebUITestMessageHandler> test_message_handler_; |
| }; |
| |
| #endif // CHROME_TEST_BASE_WEB_UI_BROWSER_TEST_H_ |