| // Copyright 2018 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. |
| |
| #include "base/bind.h" |
| #include "base/memory/ref_counted.h" |
| #include "components/autofill_assistant/browser/service.pb.h" |
| #include "components/autofill_assistant/browser/web_controller.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| |
| namespace autofill_assistant { |
| |
| const char* kTargetWebsitePath = "/autofill_assistant_target_website.html"; |
| |
| class WebControllerBrowserTest : public content::ContentBrowserTest, |
| public content::WebContentsObserver { |
| public: |
| WebControllerBrowserTest() {} |
| ~WebControllerBrowserTest() override {} |
| |
| void SetUpOnMainThread() override { |
| ContentBrowserTest::SetUpOnMainThread(); |
| http_server_ = std::make_unique<net::EmbeddedTestServer>( |
| net::EmbeddedTestServer::TYPE_HTTP); |
| http_server_->ServeFilesFromSourceDirectory( |
| "components/test/data/autofill_assistant"); |
| ASSERT_TRUE(http_server_->Start()); |
| ASSERT_TRUE( |
| NavigateToURL(shell(), http_server_->GetURL(kTargetWebsitePath))); |
| web_controller_ = |
| WebController::CreateForWebContents(shell()->web_contents()); |
| Observe(shell()->web_contents()); |
| } |
| |
| void DidCommitAndDrawCompositorFrame() override { |
| paint_occurred_during_last_loop_ = true; |
| } |
| |
| void WaitTillPageIsIdle(base::TimeDelta continuous_paint_timeout) { |
| base::TimeTicks finished_load_time = base::TimeTicks::Now(); |
| bool page_is_loading = false; |
| do { |
| paint_occurred_during_last_loop_ = false; |
| base::RunLoop heart_beat; |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, heart_beat.QuitClosure(), base::TimeDelta::FromSeconds(3)); |
| heart_beat.Run(); |
| page_is_loading = |
| web_contents()->IsWaitingForResponse() || web_contents()->IsLoading(); |
| if (page_is_loading) { |
| finished_load_time = base::TimeTicks::Now(); |
| } else if ((base::TimeTicks::Now() - finished_load_time) > |
| continuous_paint_timeout) { |
| // |continuous_paint_timeout| has expired since Chrome loaded the page. |
| // During this period of time, Chrome has been continuously painting |
| // the page. In this case, the page is probably idle, but a bug, a |
| // blinking caret or a persistent animation is making Chrome paint at |
| // regular intervals. Exit. |
| break; |
| } |
| } while (page_is_loading || paint_occurred_during_last_loop_); |
| } |
| |
| void RunElementChecks(ElementCheckType check_type, |
| const std::vector<Selector>& selectors, |
| const std::vector<bool> results) { |
| base::RunLoop run_loop; |
| ASSERT_EQ(selectors.size(), results.size()); |
| size_t pending_number_of_checks = selectors.size(); |
| for (size_t i = 0; i < selectors.size(); i++) { |
| web_controller_->ElementCheck( |
| check_type, selectors[i], |
| base::BindOnce(&WebControllerBrowserTest::CheckElementVisibleCallback, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &pending_number_of_checks, results[i])); |
| } |
| run_loop.Run(); |
| } |
| |
| void CheckElementVisibleCallback(const base::Closure& done_callback, |
| size_t* pending_number_of_checks_output, |
| bool expected_result, |
| bool result) { |
| ASSERT_EQ(expected_result, result); |
| *pending_number_of_checks_output -= 1; |
| if (*pending_number_of_checks_output == 0) { |
| done_callback.Run(); |
| } |
| } |
| |
| void ClickElement(const Selector& selector) { |
| base::RunLoop run_loop; |
| web_controller_->ClickElement( |
| selector, |
| base::BindOnce(&WebControllerBrowserTest::ClickElementCallback, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| void ClickElementCallback(const base::Closure& done_callback, |
| bool result) { |
| ASSERT_TRUE(result); |
| done_callback.Run(); |
| } |
| |
| void TapElement(const Selector& selector) { |
| base::RunLoop run_loop; |
| web_controller_->TapElement( |
| selector, |
| base::BindOnce(&WebControllerBrowserTest::ClickElementCallback, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| void TapElementCallback(const base::Closure& done_callback, bool result) { |
| ASSERT_TRUE(result); |
| done_callback.Run(); |
| } |
| |
| void WaitForElementRemove(const Selector& selector) { |
| base::RunLoop run_loop; |
| web_controller_->ElementCheck( |
| kExistenceCheck, selector, |
| base::BindOnce(&WebControllerBrowserTest::OnWaitForElementRemove, |
| base::Unretained(this), run_loop.QuitClosure(), |
| selector)); |
| run_loop.Run(); |
| } |
| |
| void OnWaitForElementRemove(const base::Closure& done_callback, |
| const Selector& selector, |
| bool result) { |
| done_callback.Run(); |
| if (result) { |
| WaitForElementRemove(selector); |
| } |
| } |
| |
| void FocusElement(const Selector& selector) { |
| base::RunLoop run_loop; |
| web_controller_->FocusElement( |
| selector, |
| base::BindOnce(&WebControllerBrowserTest::OnFocusElement, |
| base::Unretained(this), run_loop.QuitClosure())); |
| run_loop.Run(); |
| } |
| |
| void OnFocusElement(base::Closure done_callback, bool result) { |
| ASSERT_TRUE(result); |
| std::move(done_callback).Run(); |
| } |
| |
| bool SelectOption(const Selector& selector, const std::string& option) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->SelectOption( |
| selector, option, |
| base::BindOnce(&WebControllerBrowserTest::OnSelectOption, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnSelectOption(base::Closure done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| bool HighlightElement(const Selector& selector) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->HighlightElement( |
| selector, base::BindOnce(&WebControllerBrowserTest::OnHighlightElement, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnHighlightElement(base::Closure done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| bool GetOuterHtml(const Selector& selector, std::string* html_output) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->GetOuterHtml( |
| selector, base::BindOnce(&WebControllerBrowserTest::OnGetOuterHtml, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result, html_output)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnGetOuterHtml(const base::Closure& done_callback, |
| bool* successful_output, |
| std::string* html_output, |
| bool successful, |
| const std::string& html) { |
| *successful_output = successful; |
| *html_output = html; |
| done_callback.Run(); |
| } |
| |
| void FindElement(const Selector& selector, |
| size_t expected_index, |
| bool is_main_frame) { |
| base::RunLoop run_loop; |
| web_controller_->FindElement( |
| selector, |
| /* strict_mode= */ true, |
| base::BindOnce(&WebControllerBrowserTest::OnFindElement, |
| base::Unretained(this), run_loop.QuitClosure(), |
| expected_index, is_main_frame)); |
| run_loop.Run(); |
| } |
| |
| void OnFindElement(const base::Closure& done_callback, |
| size_t expected_index, |
| bool is_main_frame, |
| std::unique_ptr<WebController::FindElementResult> result) { |
| done_callback.Run(); |
| if (is_main_frame) { |
| ASSERT_EQ(shell()->web_contents()->GetMainFrame(), |
| result->container_frame_host); |
| } else { |
| ASSERT_NE(shell()->web_contents()->GetMainFrame(), |
| result->container_frame_host); |
| } |
| ASSERT_EQ(result->container_frame_selector_index, expected_index); |
| ASSERT_FALSE(result->object_id.empty()); |
| } |
| |
| void GetFieldsValue(const std::vector<Selector>& selectors, |
| const std::vector<std::string>& expected_values) { |
| base::RunLoop run_loop; |
| ASSERT_EQ(selectors.size(), expected_values.size()); |
| size_t pending_number_of_checks = selectors.size(); |
| for (size_t i = 0; i < selectors.size(); i++) { |
| web_controller_->GetFieldValue( |
| selectors[i], |
| base::BindOnce(&WebControllerBrowserTest::OnGetFieldValue, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &pending_number_of_checks, expected_values[i])); |
| } |
| run_loop.Run(); |
| } |
| |
| void OnGetFieldValue(const base::Closure& done_callback, |
| size_t* pending_number_of_checks_output, |
| const std::string& expected_value, |
| bool exists, |
| const std::string& value) { |
| // Don't use ASSERT_EQ here: if the check fails, this would result in |
| // an endless loop without meaningful test results. |
| EXPECT_EQ(expected_value, value); |
| *pending_number_of_checks_output -= 1; |
| if (*pending_number_of_checks_output == 0) { |
| std::move(done_callback).Run(); |
| } |
| } |
| |
| bool SetFieldValue(const Selector& selector, |
| const std::string& value, |
| bool simulate_key_presses) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->SetFieldValue( |
| selector, value, simulate_key_presses, |
| base::BindOnce(&WebControllerBrowserTest::OnSetFieldValue, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnSetFieldValue(const base::Closure& done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| bool SendKeyboardInput(const Selector& selector, |
| const std::vector<std::string>& text_parts) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->SendKeyboardInput( |
| selector, text_parts, |
| base::BindOnce(&WebControllerBrowserTest::OnSendKeyboardInput, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnSendKeyboardInput(const base::Closure& done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| bool SetAttribute(const Selector& selector, |
| const std::vector<std::string>& attribute, |
| const std::string& value) { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->SetAttribute( |
| selector, attribute, value, |
| base::BindOnce(&WebControllerBrowserTest::OnSetAttribute, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnSetAttribute(const base::Closure& done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| bool HasCookie() { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->HasCookie(base::BindOnce( |
| &WebControllerBrowserTest::OnCookieResult, base::Unretained(this), |
| run_loop.QuitClosure(), &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| bool SetCookie() { |
| base::RunLoop run_loop; |
| bool result; |
| web_controller_->SetCookie( |
| "http://example.com", |
| base::BindOnce(&WebControllerBrowserTest::OnCookieResult, |
| base::Unretained(this), run_loop.QuitClosure(), |
| &result)); |
| run_loop.Run(); |
| return result; |
| } |
| |
| void OnCookieResult(const base::Closure& done_callback, |
| bool* result_output, |
| bool result) { |
| *result_output = result; |
| std::move(done_callback).Run(); |
| } |
| |
| protected: |
| std::unique_ptr<WebController> web_controller_; |
| |
| private: |
| std::unique_ptr<net::EmbeddedTestServer> http_server_; |
| bool paint_occurred_during_last_loop_ = false; |
| |
| DISALLOW_COPY_AND_ASSIGN(WebControllerBrowserTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ConcurrentElementsVisible) { |
| std::vector<Selector> selectors; |
| std::vector<bool> results; |
| |
| Selector a_selector; |
| a_selector.selectors.emplace_back("#button"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| a_selector.selectors.emplace_back("#whatever"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| // IFrame. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#iframe"); |
| a_selector.selectors.emplace_back("#button"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| a_selector.selectors.emplace_back("#whatever"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#iframe"); |
| a_selector.selectors.emplace_back("[name=name]"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| // Shadow DOM. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#iframe"); |
| a_selector.selectors.emplace_back("#shadowsection"); |
| a_selector.selectors.emplace_back("#shadowbutton"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| a_selector.selectors.emplace_back("#whatever"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| // IFrame inside IFrame. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#iframe"); |
| a_selector.selectors.emplace_back("#iframe"); |
| a_selector.selectors.emplace_back("#button"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| a_selector.selectors.emplace_back("#whatever"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| // Hidden element. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#hidden"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| RunElementChecks(kVisibilityCheck, selectors, results); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ElementExists) { |
| std::vector<Selector> selectors; |
| std::vector<bool> results; |
| |
| Selector a_selector; |
| |
| // A visible element |
| a_selector.selectors.emplace_back("#button"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| // A hidden element. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#hidden"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(true); |
| |
| // A nonexistent element. |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#doesnotexist"); |
| selectors.emplace_back(a_selector); |
| results.emplace_back(false); |
| |
| RunElementChecks(kExistenceCheck, selectors, results); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickElement) { |
| Selector selector; |
| selector.selectors.emplace_back("#button"); |
| ClickElement(selector); |
| |
| WaitForElementRemove(selector); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, |
| ClickElementInIFrame) { |
| Selector selector; |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#shadowsection"); |
| selector.selectors.emplace_back("#shadowbutton"); |
| ClickElement(selector); |
| |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#button"); |
| WaitForElementRemove(selector); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, TapElement) { |
| Selector selector; |
| selector.selectors.emplace_back("#touch_area_two"); |
| TapElement(selector); |
| WaitForElementRemove(selector); |
| |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#touch_area_one"); |
| TapElement(selector); |
| WaitForElementRemove(selector); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, TapElementMovingOutOfView) { |
| Selector selector; |
| selector.selectors.emplace_back("#touch_area_three"); |
| TapElement(selector); |
| WaitForElementRemove(selector); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, TapElementAfterPageIsIdle) { |
| // Set a very long timeout to make sure either the page is idle or the test |
| // timeout. |
| WaitTillPageIsIdle(base::TimeDelta::FromHours(1)); |
| |
| Selector selector; |
| selector.selectors.emplace_back("#touch_area_one"); |
| TapElement(selector); |
| |
| WaitForElementRemove(selector); |
| } |
| |
| // TODO(crbug.com/920948) Disabled for strong flakiness. |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, DISABLED_TapElementInIFrame) { |
| Selector selector; |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#touch_area"); |
| TapElement(selector); |
| |
| WaitForElementRemove(selector); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickPseudoElement) { |
| const std::string javascript = R"( |
| document.querySelector("#terms-and-conditions").checked; |
| )"; |
| EXPECT_FALSE(content::EvalJs(shell(), javascript).ExtractBool()); |
| Selector selector({R"(label[for="terms-and-conditions"])"}, |
| PseudoType::BEFORE); |
| ClickElement(selector); |
| EXPECT_TRUE(content::EvalJs(shell(), javascript).ExtractBool()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, FindElement) { |
| Selector selector; |
| selector.selectors.emplace_back("#button"); |
| FindElement(selector, 0, true); |
| |
| // IFrame. |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#button"); |
| FindElement(selector, 0, false); |
| |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("[name=name]"); |
| FindElement(selector, 0, false); |
| |
| // IFrame inside IFrame. |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#button"); |
| FindElement(selector, 1, false); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, FocusElement) { |
| Selector selector; |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("#focus"); |
| |
| // The element is not visible initially. |
| const std::string checkNotVisibleScript = R"( |
| let iframe = document.querySelector("#iframe"); |
| let div = iframe.contentDocument.querySelector("#focus"); |
| let iframeRect = iframe.getBoundingClientRect(); |
| let divRect = div.getBoundingClientRect(); |
| iframeRect.y + divRect.y > window.innerHeight; |
| )"; |
| EXPECT_EQ(true, content::EvalJs(shell(), checkNotVisibleScript)); |
| FocusElement(selector); |
| |
| // Verify that the scroll moved the div in the iframe into view. |
| const std::string checkVisibleScript = R"( |
| const scrollTimeoutMs = 500; |
| var timer = null; |
| |
| function check() { |
| let iframe = document.querySelector("#iframe"); |
| let div = iframe.contentDocument.querySelector("#focus"); |
| let iframeRect = iframe.getBoundingClientRect(); |
| let divRect = div.getBoundingClientRect(); |
| return iframeRect.y + divRect.y < window.innerHeight; |
| } |
| function onScrollDone() { |
| window.removeEventListener("scroll", onScroll); |
| domAutomationController.send(check()); |
| } |
| function onScroll(e) { |
| if (timer != null) { |
| clearTimeout(timer); |
| } |
| timer = setTimeout(onScrollDone, scrollTimeoutMs); |
| } |
| if (check()) { |
| // Scrolling finished before this script started. Just return the result. |
| domAutomationController.send(true); |
| } else { |
| window.addEventListener("scroll", onScroll); |
| } |
| )"; |
| EXPECT_EQ(true, content::EvalJsWithManualReply(shell(), checkVisibleScript)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOption) { |
| Selector selector; |
| selector.selectors.emplace_back("#select"); |
| EXPECT_FALSE(SelectOption(selector, "incorrect_label")); |
| ASSERT_TRUE(SelectOption(selector, "two")); |
| |
| const std::string javascript = R"( |
| let select = document.querySelector("#select"); |
| select.options[select.selectedIndex].label; |
| )"; |
| EXPECT_EQ("Two", content::EvalJs(shell(), javascript)); |
| |
| ASSERT_TRUE(SelectOption(selector, "one")); |
| EXPECT_EQ("One", content::EvalJs(shell(), javascript)); |
| |
| selector.selectors.clear(); |
| selector.selectors.emplace_back("#incorrect_selector"); |
| EXPECT_FALSE(SelectOption(selector, "two")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOptionInIframe) { |
| Selector selector; |
| selector.selectors.emplace_back("#iframe"); |
| selector.selectors.emplace_back("select[name=state]"); |
| ASSERT_TRUE(SelectOption(selector, "NY")); |
| |
| const std::string javascript = R"( |
| let iframe = document.querySelector("iframe").contentDocument; |
| let select = iframe.querySelector("select[name=state]"); |
| select.options[select.selectedIndex].label; |
| )"; |
| EXPECT_EQ("NY", content::EvalJs(shell(), javascript)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetOuterHtml) { |
| Selector selector; |
| selector.selectors.emplace_back("#testOuterHtml"); |
| std::string html; |
| ASSERT_TRUE(GetOuterHtml(selector, &html)); |
| EXPECT_EQ( |
| R"(<div id="testOuterHtml"><span>Span</span><p>Paragraph</p></div>)", |
| html); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetAndSetFieldValue) { |
| std::vector<Selector> selectors; |
| std::vector<std::string> expected_values; |
| |
| Selector a_selector; |
| a_selector.selectors.emplace_back("#input1"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld1"); |
| GetFieldsValue(selectors, expected_values); |
| |
| EXPECT_TRUE( |
| SetFieldValue(a_selector, "foo", /* simulate_key_presses= */ false)); |
| expected_values.clear(); |
| expected_values.emplace_back("foo"); |
| GetFieldsValue(selectors, expected_values); |
| |
| selectors.clear(); |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#uppercase_input"); |
| selectors.emplace_back(a_selector); |
| EXPECT_TRUE(SetFieldValue(a_selector, /* Zürich */ "Z\xc3\xbcrich", |
| /* simulate_key_presses= */ true)); |
| expected_values.clear(); |
| expected_values.emplace_back(/* ZÜRICH */ "Z\xc3\x9cRICH"); |
| GetFieldsValue(selectors, expected_values); |
| |
| selectors.clear(); |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#invalid_selector"); |
| selectors.emplace_back(a_selector); |
| expected_values.clear(); |
| expected_values.emplace_back(""); |
| GetFieldsValue(selectors, expected_values); |
| |
| EXPECT_FALSE( |
| SetFieldValue(a_selector, "foobar", /* simulate_key_presses= */ false)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SendKeyboardInput) { |
| std::vector<std::string> text_parts = { |
| "Z", /* ü */ "\xc3\xbc", "r", "i", "c", "h", "\r"}; |
| std::vector<std::string> expected_values = {"Z\xc3\xbcrich"}; |
| |
| std::vector<Selector> selectors; |
| Selector a_selector; |
| a_selector.selectors.emplace_back("#input6"); |
| selectors.emplace_back(a_selector); |
| EXPECT_TRUE(SendKeyboardInput(a_selector, text_parts)); |
| GetFieldsValue(selectors, expected_values); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SetAttribute) { |
| Selector selector; |
| std::vector<std::string> attribute; |
| |
| selector.selectors.emplace_back("#full_height_section"); |
| attribute.emplace_back("style"); |
| attribute.emplace_back("backgroundColor"); |
| std::string value = "red"; |
| |
| EXPECT_TRUE(SetAttribute(selector, attribute, value)); |
| const std::string javascript = R"( |
| document.querySelector("#full_height_section").style.backgroundColor; |
| )"; |
| EXPECT_EQ(value, content::EvalJs(shell(), javascript)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ConcurrentGetFieldsValue) { |
| std::vector<Selector> selectors; |
| std::vector<std::string> expected_values; |
| |
| Selector a_selector; |
| a_selector.selectors.emplace_back("#input1"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld1"); |
| |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#input2"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld2"); |
| |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#input3"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld3"); |
| |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#input4"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld4"); |
| |
| a_selector.selectors.clear(); |
| a_selector.selectors.emplace_back("#input5"); |
| selectors.emplace_back(a_selector); |
| expected_values.emplace_back("helloworld5"); |
| |
| GetFieldsValue(selectors, expected_values); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, NavigateToUrl) { |
| EXPECT_EQ(kTargetWebsitePath, |
| shell()->web_contents()->GetLastCommittedURL().path()); |
| web_controller_->LoadURL(GURL(url::kAboutBlankURL)); |
| WaitForLoadStop(shell()->web_contents()); |
| EXPECT_EQ(url::kAboutBlankURL, |
| shell()->web_contents()->GetLastCommittedURL().spec()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, HighlightElement) { |
| Selector selector; |
| selector.selectors.emplace_back("#select"); |
| |
| const std::string javascript = R"( |
| let select = document.querySelector("#select"); |
| select.style.boxShadow; |
| )"; |
| EXPECT_EQ("", content::EvalJs(shell(), javascript)); |
| ASSERT_TRUE(HighlightElement(selector)); |
| // We only make sure that the element has a non-empty boxShadow style without |
| // requiring an exact string match. |
| EXPECT_NE("", content::EvalJs(shell(), javascript)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetAndSetCookie) { |
| EXPECT_FALSE(HasCookie()); |
| EXPECT_TRUE(SetCookie()); |
| } |
| |
| } // namespace |