diff --git a/components/brave_rewards/browser/rewards_service_browsertest.cc b/components/brave_rewards/browser/rewards_service_browsertest.cc index 51316189fb1b..a635018d3d79 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest.cc +++ b/components/brave_rewards/browser/rewards_service_browsertest.cc @@ -22,6 +22,7 @@ #include "brave/browser/extensions/api/brave_action_api.h" #include "brave/common/brave_paths.h" #include "brave/common/extensions/extension_constants.h" +#include "brave/components/brave_rewards/browser/rewards_service_browsertest_utils.h" #include "brave/components/brave_rewards/browser/rewards_service_factory.h" #include "brave/components/brave_rewards/browser/rewards_service_impl.h" #include "brave/components/brave_rewards/browser/rewards_service_observer.h" @@ -49,6 +50,8 @@ using braveledger_request_util::ServerTypes; +using namespace rewards_service_browsertest_utils; + using RewardsNotificationType = brave_rewards::RewardsNotificationService::RewardsNotificationType; @@ -514,34 +517,6 @@ class BraveRewardsBrowserTest wait_for_recurring_tip_saved_loop_->Run(); } - void WaitForSelector(content::WebContents* contents, - const std::string& selector) const { - auto script = content::JsReplace( - "new Promise((resolve) => {" - " let count = 20;" - " let interval = setInterval(function() {" - " if (count == 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " const element = document.querySelector($1);" - " if (element) {" - " clearInterval(interval);" - " resolve(true);" - " }" - " }, 500);" - "});", - selector); - auto js_result = EvalJs( - contents, - script, - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(js_result.ExtractBool()); - } - void DragAndDrop( content::WebContents* contents, const std::string& drag_selector, @@ -839,28 +814,8 @@ class BraveRewardsBrowserTest ui_test_utils::NavigateToURL(browser(), page_url); WaitForLoadStop(contents()); // Opt in and create wallet to enable rewards - ASSERT_TRUE(ExecJs(contents(), - "document.querySelector(\"[data-test-id='optInAction']\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); - content::EvalJsResult jsResult = EvalJs(contents(), - "new Promise((resolve) => {" - "var count = 10;" - "var interval = setInterval(function() {" - " if (count == 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " if (document.querySelector(\"[data-test-id2='enableMain']\")) {" - " clearInterval(interval);" - " resolve(true);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(jsResult.ExtractBool()); + WaitForElementThenClick(contents(), "[data-test-id='optInAction']"); + WaitForElementToAppear(contents(), "[data-test-id2='enableMain']"); } void EnableRewardsViaCode() { @@ -894,21 +849,13 @@ class BraveRewardsBrowserTest // Claim promotion via settings page or panel, as instructed if (use_panel) { - ASSERT_TRUE(ExecJs(contents, - "document.getElementsByTagName('button')[0].click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); + WaitForElementThenClick(contents, "button"); } else { - WaitForSelector(contents, "[data-test-id='claimGrant']"); - ASSERT_TRUE(ExecJs( - contents, - "document.querySelector(\"[data-test-id='claimGrant']\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); + WaitForElementThenClick(contents, "[data-test-id='claimGrant']"); } // Wait for CAPTCHA - WaitForSelector(contents, "[data-test-id='captcha']"); + WaitForElementToAppear(contents, "[data-test-id='captcha']"); DragAndDrop( contents, @@ -928,44 +875,12 @@ class BraveRewardsBrowserTest // Check that promotion notification shows the appropriate amount const std::string selector = use_panel ? "[id='root']" : "[data-test-id='newTokenGrant']"; - - WaitForSelector(contents, selector); - - content::EvalJsResult js_result = EvalJs( - contents, - content::JsReplace( - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector($1).innerText);", - selector), - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result.ExtractString().find("Free Token Grant"), - std::string::npos); - EXPECT_NE(js_result.ExtractString().find("30.0 BAT"), std::string::npos); + WaitForElementToContain(contents, selector, "Free Token Grant"); + WaitForElementToContain(contents, selector, "30.0 BAT"); // Dismiss the promotion notification if (use_panel) { - content::EvalJsResult jsResult = EvalJs(contents, - "new Promise((resolve) => {" - "let count = 10;" - "let interval = setInterval(function() {" - " if (count == 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " const button = document.getElementById(\"grant-completed-ok\");" - " if (button) {" - " clearInterval(interval);" - " button.click();" - " resolve(true);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(jsResult.ExtractBool()); + WaitForElementThenClick(contents, "#grant-completed-ok"); } } @@ -988,15 +903,8 @@ class BraveRewardsBrowserTest WaitForPublisherListNormalized(); // Make sure site appears in auto-contribute table - content::EvalJsResult js_result = EvalJs( - contents(), - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(1000).then(() => " - " document.querySelector(\"[data-test-id='ac_link_" + publisher + "']" - "\").innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_STREQ(js_result.ExtractString().c_str(), publisher.c_str()); + WaitForElementToEqual(contents(), + "[data-test-id='ac_link_" + publisher + "']", publisher); if (verified) { // A verified site has two images associated with it, the site's @@ -1025,43 +933,6 @@ class BraveRewardsBrowserTest } } - std::string ElementInnerText(const std::string& selector, - int delay_ms = 0) const { - auto script = content::JsReplace( - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay($1).then(() => document.querySelector($2).innerText);", - delay_ms, - selector); - - auto js_result = EvalJs( - contents(), - script, - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - - return js_result.ExtractString(); - } - - std::string RewardsPageBalance() const { - return ElementInnerText("[data-test-id='balance']", 1000); - } - - std::string RewardsPagePendingContributions() const { - std::string pending_text = ElementInnerText( - "[data-test-id='pending-contribution-box']", - 500); - - // The pending text is of the form "You’ve designated 1.0 BAT for..." - size_t start = pending_text.find("designated "); - assert(start != std::string::npos); - start += 11; - - size_t end = pending_text.find(" for"); - assert(start != std::string::npos); - - return pending_text.substr(start, end - start); - } - std::string RewardsPageTipSummaryAmount() const { std::string amount = ElementInnerText( "[data-test-id=summary-tips] [color=contribute] span span"); @@ -1079,7 +950,7 @@ class BraveRewardsBrowserTest std::string ExpectedTipSummaryAmountString() const { // The tip summary page formats 2.4999 as 2.4, so we do the same here. double truncated_amount = floor(reconciled_tip_total_ * 10) / 10; - return BalanceDoubleToString(-truncated_amount) + " BAT"; + return BalanceDoubleToString(-truncated_amount); } void ActivateTabAtIndex(int index) const { @@ -1089,28 +960,9 @@ class BraveRewardsBrowserTest } void RefreshPublisherListUsingRewardsPopup() const { - content::EvalJsResult js_result = EvalJs( + WaitForElementThenClick( OpenRewardsPopup(), - "new Promise((resolve) => {" - "let count = 10;" - "let interval = setInterval(function() {" - " if (count == 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " const button = " - "document.querySelector(\"[data-test-id='unverified-check-button']\");" - " if (button) {" - " clearInterval(interval);" - " button.click();" - " resolve(true);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(js_result.ExtractBool()); + "[data-test-id='unverified-check-button']"); } content::WebContents* OpenSiteBanner(ContributionType banner_type) const { @@ -1126,29 +978,8 @@ class BraveRewardsBrowserTest ? "[type='tip-monthly']" : "[type='tip']"; - // Click button to initiate sending a tip - content::EvalJsResult js_result = EvalJs( - popup_contents, - content::JsReplace( - "new Promise((resolve) => {" - "let count = 10;" - "var interval = setInterval(function() {" - " if (count === 0) {" - " clearInterval(interval);" - " resolve('');" - " } else {" - " count -= 1;" - " }" - " const tipButton = document.querySelector($1);" - " if (tipButton) {" - " clearInterval(interval);" - " tipButton.click();" - " resolve(true);" - " }" - "}, 500);});", - buttonSelector), - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); + // Click button to initiate sending a tip. + WaitForElementThenClick(popup_contents, buttonSelector); // Wait for the site banner to load site_banner_observer.Wait(); @@ -1192,26 +1023,14 @@ class BraveRewardsBrowserTest const std::string amount_str = base::StringPrintf("%2.1f", amount); // Select the tip amount (default is 1.0 BAT) - ASSERT_TRUE(ExecJs( - site_banner_contents, - content::JsReplace( - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelectorAll(\"[data-test-id='amount-wrapper']\")[$1]" - " .click());", - selection), - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); + std::string amount_selector = base::StringPrintf( + "div:nth-of-type(%u)>[data-test-id=amount-wrapper]", + selection + 1); + WaitForElementThenClick(site_banner_contents, amount_selector); // Send the tip - ASSERT_TRUE(ExecJs( - site_banner_contents, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector(\"[data-test-id='send-tip-button']\")" - " .click());", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); + WaitForElementThenClick(site_banner_contents, + "[data-test-id='send-tip-button']"); // Signal that direct tip was made and update wallet with new // balance @@ -1289,26 +1108,31 @@ class BraveRewardsBrowserTest if (should_contribute) { // Make sure that balance is updated correctly - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Check that tip table shows the appropriate tip amount const std::string selector = monthly ? "[data-test-id='summary-monthly']" : "[data-test-id='summary-tips']"; - std::string page_amount = ElementInnerText(selector); - ASSERT_NE(page_amount.find("-" + BalanceDoubleToString(amount) + "BAT"), - std::string::npos); + WaitForElementToContain(contents(), selector, + "-" + BalanceDoubleToString(amount) + "BAT"); } else { // Make sure that balance did not change - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Make sure that pending contribution box shows the correct // amount - ASSERT_EQ(RewardsPagePendingContributions(), + WaitForElementToContain( + contents(), + "[data-test-id='pending-contribution-box']", ExpectedPendingBalanceString()); // Check that tip table shows no tip + // TODO(jhoneycutt): There isn't a good selector for this element. Make it + // identifiable. { content::EvalJsResult js_result = EvalJs( contents(), @@ -1761,26 +1585,8 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ToggleAutoContribute) { IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ActivateSettingsModal) { EnableRewards(); - content::EvalJsResult modalResult = EvalJs( - contents(), - "document.querySelector(\"[data-test-id='settingsButton']\").click();" - "new Promise((resolve) => {" - "var count = 10;" - "var interval = setInterval(function() {" - " if (count == 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " if (document.getElementById('modal')) {" - " clearInterval(interval);" - " resolve(document.getElementById('modal') != null);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(modalResult.ExtractBool()); + WaitForElementThenClick(contents(), "[data-test-id='settingsButton']"); + WaitForElementToAppear(contents(), "#modal"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, HandleFlagsSingleArg) { @@ -2015,33 +1821,13 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, // Retrieve the inner text of the wallet panel and verify that it // looks as expected - { - content::EvalJsResult js_result = EvalJs( - popup_contents, - "new Promise((resolve) => {" - "let count = 10;" - "var interval = setInterval(function() {" - " if (count === 0) {" - " clearInterval(interval);" - " resolve('');" - " } else {" - " count -= 1;" - " }" - " const walletPanel = document.querySelector(\"[id='wallet-panel']\");" - " if (walletPanel) {" - " clearInterval(interval);" - " resolve(walletPanel.innerText);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result.ExtractString().find("Brave Verified Creator"), - std::string::npos); - EXPECT_NE(js_result.ExtractString().find(publisher), std::string::npos); - } + WaitForElementToContain(popup_contents, "[id='wallet-panel']", + "Brave Verified Creator"); + WaitForElementToContain(popup_contents, "[id='wallet-panel']", publisher); // Retrieve the inner HTML of the wallet panel and verify that it // contains the expected favicon + // TODO(jhoneycutt): WaitForElementHTMLToContain? Or WaitForScriptToSucceed? { content::EvalJsResult js_result = EvalJs( popup_contents, @@ -2097,11 +1883,11 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, AutoContribution) { ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Check that summary table shows the appropriate contribution - ASSERT_NE(ElementInnerText("[color=contribute]").find("-20.0BAT"), - std::string::npos); + WaitForElementToContain(contents(), "[color=contribute]", "-20.0BAT"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, AutoContributeWhenACOff) { @@ -2382,6 +2168,8 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, TipPublisher(publisher, ContributionType::OneTimeTip); // Check that link for pending is shown + // TODO(jhoneycutt): There isn't a good selector for this element. Make it + // identifiable. { content::EvalJsResult js_result = EvalJs( contents(), @@ -2397,30 +2185,11 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, } // Open modal - { - ASSERT_TRUE(ExecJs(contents(), - "if (document.querySelector(\"[data-test-id='reservedAllLink']\")) {" - " document.querySelector(" - " \"[data-test-id='reservedAllLink']\").click();" - "}", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); - } + WaitForElementThenClick(contents(), "[data-test-id='reservedAllLink']"); // Make sure that table is populated - { - content::EvalJsResult js_result = EvalJs( - contents(), - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector(\"[id='pendingContributionTable']\")" - " .getElementsByTagName('a')[0].innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE( - js_result.ExtractString().find(publisher), - std::string::npos); - } + WaitForElementToContain(contents(), "[id='pendingContributionTable'] a", + publisher); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, @@ -2548,7 +2317,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, EXPECT_TRUE(is_showing_notification); } -// Test whether rewards is diabled in private profile. +// Test whether rewards is disabled in private profile. IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, PrefsTestInPrivateWindow) { EnableRewards(); auto* profile = browser()->profile(); @@ -2602,49 +2371,34 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, UpdateContributionBalance(-25.0, false); // update pending balance // Make sure that balance is updated correctly - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Check that wallet summary shows the appropriate tip amount - ASSERT_EQ(RewardsPageTipSummaryAmount(), ExpectedTipSummaryAmountString()); + WaitForElementToEqual( + contents(), + "[data-test-id=summary-tips] [color=donation] span span", + ExpectedTipSummaryAmountString()); // Make sure that pending contribution box shows the correct // amount - ASSERT_EQ(RewardsPagePendingContributions(), ExpectedPendingBalanceString()); + WaitForElementToContain( + contents(), + "[data-test-id='pending-contribution-box']", + ExpectedPendingBalanceString()); // Open the Rewards popup - { - content::WebContents* popup_contents = OpenRewardsPopup(); - ASSERT_TRUE(popup_contents); + content::WebContents* popup_contents = OpenRewardsPopup(); + ASSERT_TRUE(popup_contents); - // Check if verified notification is shown - content::EvalJsResult js_result = EvalJs( - popup_contents, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(500).then(() => " - " document.querySelector(\"[id='root']\").innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result.ExtractString().find("3zsistemi.si"), - std::string::npos); + // Check if verified notification is shown + WaitForElementToContain(popup_contents, "#root", "3zsistemi.si"); - // Close notification - ASSERT_TRUE(ExecJs(popup_contents, - " document.querySelector(" - " \"[data-test-id='notification-close']\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); + // Close notification + WaitForElementThenClick(popup_contents, "[data-test-id=notification-close]"); - // Check if insufficient funds notification is shown - content::EvalJsResult js_result2 = EvalJs( - popup_contents, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(500).then(() => " - " document.querySelector(\"[id='root']\").innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result2.ExtractString().find("Insufficient Funds"), - std::string::npos); - } + // Check if insufficient funds notification is shown + WaitForElementToContain(popup_contents, "#root", "Insufficient Funds"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, RewardsPanelDefaultTipChoices) { @@ -2713,20 +2467,10 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, EnableRewards(); // Click on verify button - { - ASSERT_TRUE(ExecJs(contents(), - " document.getElementById(\"verify-wallet-button\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); - } + WaitForElementThenClick(contents(), "#verify-wallet-button"); // Click on verify button in on boarding - { - ASSERT_TRUE(ExecJs(contents(), - " document.getElementById(\"on-boarding-verify-button\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); - } + WaitForElementThenClick(contents(), "#on-boarding-verify-button"); // Check if we are redirected to uphold { @@ -2971,16 +2715,11 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - { - const std::string result = RewardsPageBalance(); - EXPECT_NE(result.find(ExpectedBalanceString()), std::string::npos); - } + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Check that summary table shows the appropriate contribution - { - const std::string result = ElementInnerText("[color='contribute']"); - EXPECT_NE(result.find("-5.0BAT"), std::string::npos); - } + WaitForElementToContain(contents(), "[color='contribute']", "-5.0BAT"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, @@ -3036,16 +2775,13 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - { - const std::string result = RewardsPageBalance(); - EXPECT_NE(result.find(ExpectedBalanceString()), std::string::npos); - } + WaitForElementToEqual(contents(), "[data-test-id='balance']", + ExpectedBalanceString()); // Check that summary table shows the appropriate contribution - { - const std::string result = ElementInnerText("[color='contribute']"); - EXPECT_NE(result.find("-5.0BAT"), std::string::npos); - } + + // Check that summary table shows the appropriate contribution + WaitForElementToContain(contents(), "[color='contribute']", "-5.0BAT"); } IN_PROC_BROWSER_TEST_F( diff --git a/components/brave_rewards/browser/rewards_service_browsertest_utils.cc b/components/brave_rewards/browser/rewards_service_browsertest_utils.cc new file mode 100644 index 000000000000..915c97bf8912 --- /dev/null +++ b/components/brave_rewards/browser/rewards_service_browsertest_utils.cc @@ -0,0 +1,204 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "rewards_service_browsertest_utils.h" + +#include "content/public/test/browser_test_utils.h" + +namespace rewards_service_browsertest_utils { + +static const std::string kWaitForElementToAppearScript = R"( + const waitForElementToAppear = (selector) => { + const TIMEOUT_SECONDS = 5; + + return new Promise((resolve, reject) => { + let element = document.querySelector(selector); + if (element) { + resolve(element); + return; + } + + const timerID = window.setTimeout(() => { + observer.disconnect(); + reject(new Error("Timed out waiting for '" + selector + "'.")); + }, TIMEOUT_SECONDS * 1000); + + const observer = new MutationObserver(({}, observer) => { + let element = document.querySelector(selector); + if (element) { + clearTimeout(timerID); + observer.disconnect(); + resolve(element); + } + }); + observer.observe(document.documentElement, + { childList: true, subtree: true }); + }); + }; +)"; + +void WaitForElementToAppear(content::WebContents* context, + const std::string& selector) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + try { + const selector = $1; + + const element = await waitForElementToAppear(selector); + console.log("XXXX", element); + resolve(true); + } catch (error) { + reject(error); + } + }) + )", + selector); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + ASSERT_EQ(true, result); +} + +void WaitForElementToEqual(content::WebContents* context, + const std::string& selector, const std::string& expectedValue) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + const TIMEOUT_SECONDS = 5; + const selector = $1; + const expectedValue = $2; + + try { + let element = await waitForElementToAppear(selector); + + if (element.innerText === expectedValue) { + resolve(true); + return; + } + + const timerID = window.setTimeout(() => { + observer.disconnect(); + reject(new Error("Timed out waiting for '" + selector + "' " + + "to equal '" + expectedValue + "'")); + }, TIMEOUT_SECONDS * 1000); + + const observer = new MutationObserver(({}, observer) => { + let element = document.querySelector(selector); + if (!element) { + return; + } + + if (element.innerText === expectedValue) { + clearTimeout(timerID); + observer.disconnect(); + resolve(true); + } + }); + observer.observe(document.documentElement, + { characterData: true, childList: true, subtree: true }); + } catch(error) { + reject(error); + } + }); + )", + selector, + expectedValue); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + ASSERT_EQ(true, result); +} + +void WaitForElementToContain(content::WebContents* context, + const std::string& selector, const std::string& substring) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + const TIMEOUT_SECONDS = 5; + const selector = $1; + const substring = $2; + + try { + let element = await waitForElementToAppear(selector); + + if (element.innerText.indexOf(substring) !== -1) { + resolve(true); + return; + } + + const timerID = window.setTimeout(() => { + observer.disconnect(); + reject(new Error("Timed out waiting for '" + selector + "' " + + "to contain '" + substring + "'")); + }, TIMEOUT_SECONDS * 1000); + + const observer = new MutationObserver(({}, observer) => { + let element = document.querySelector(selector); + if (!element) { + return; + } + + if (element.innerText.indexOf(substring) !== -1) { + clearTimeout(timerID); + observer.disconnect(); + resolve(true); + } + }); + observer.observe(document.documentElement, + { characterData: true, childList: true, subtree: true }); + } catch(error) { + reject(error); + } + }); + )", + selector, + substring); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + ASSERT_EQ(true, result); +} + +void WaitForElementThenClick(content::WebContents* context, + const std::string& selector) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + try { + const selector = $1; + + const element = await waitForElementToAppear(selector); + element.click(); + resolve(true); + } catch(error) { + reject(error); + } + }) + )", + selector); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + ASSERT_EQ(true, result); +} + +} // namespace rewards_service_browsertest_utils diff --git a/components/brave_rewards/browser/rewards_service_browsertest_utils.h b/components/brave_rewards/browser/rewards_service_browsertest_utils.h new file mode 100644 index 000000000000..cc1b795ec7dd --- /dev/null +++ b/components/brave_rewards/browser/rewards_service_browsertest_utils.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2019 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef REWARDS_SERVICE_BROWSERTEST_UTILS_H_ +#define REWARDS_SERVICE_BROWSERTEST_UTILS_H_ + +#include +#include "build/build_config.h" + + +namespace content { +class WebContents; +} // namespace content + +namespace rewards_service_browsertest_utils { + +void WaitForElementToAppear(content::WebContents*, + const std::string& selector); + +void WaitForElementToEqual(content::WebContents*, + const std::string& selector, const std::string& expectedValue); + +void WaitForElementToContain(content::WebContents*, + const std::string& selector, const std::string& substring); + +void WaitForElementThenClick(content::WebContents*, + const std::string& selector); + +} // namespace rewards_service_browsertest_utils + +#endif // REWARDS_SERVICE_BROWSERTEST_UTILS_H_ diff --git a/test/BUILD.gn b/test/BUILD.gn index 4d12610bb20e..db3d995c9625 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -664,6 +664,8 @@ test("brave_browser_tests") { "//brave/components/brave_rewards/browser/rewards_notification_service_browsertest.cc", "//brave/components/brave_rewards/browser/rewards_database_browsertest.cc", "//brave/components/brave_rewards/browser/rewards_service_browsertest.cc", + "//brave/components/brave_rewards/browser/rewards_service_browsertest_utils.cc", + "//brave/components/brave_rewards/browser/rewards_service_browsertest_utils.h", "//brave/components/brave_ads/browser/ads_service_browsertest.cc", "//brave/components/brave_ads/browser/locale_helper_mock.cc", "//brave/components/brave_ads/browser/locale_helper_mock.h",