From ab07e63e8a4e95d718afc3e955b941c09524d1c3 Mon Sep 17 00:00:00 2001 From: Jon Honeycutt Date: Mon, 18 Nov 2019 23:12:23 -0600 Subject: [PATCH 1/2] Replace delay / polling for DOM elements with a MutationObserver. Resolves https://github.com/brave/brave-browser/issues/7060 --- .../browser/rewards_service_browsertest.cc | 420 ++++-------------- .../rewards_service_browsertest_utils.cc | 204 +++++++++ .../rewards_service_browsertest_utils.h | 33 ++ test/BUILD.gn | 2 + 4 files changed, 317 insertions(+), 342 deletions(-) create mode 100644 components/brave_rewards/browser/rewards_service_browsertest_utils.cc create mode 100644 components/brave_rewards/browser/rewards_service_browsertest_utils.h 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", From 9110375e6934fcfd93bfb1b93673f9558b68d755 Mon Sep 17 00:00:00 2001 From: NejcZdovc Date: Tue, 3 Dec 2019 10:39:45 +0100 Subject: [PATCH 2/2] Fixed TODOs and added some more helpers --- .../browser/rewards_service_browsertest.cc | 644 +++++++----------- .../rewards_service_browsertest_utils.cc | 221 +++++- .../rewards_service_browsertest_utils.h | 53 +- .../resources/page/components/tipsBox.tsx | 3 +- .../internal/contribution/contribution.cc | 11 +- 5 files changed, 512 insertions(+), 420 deletions(-) diff --git a/components/brave_rewards/browser/rewards_service_browsertest.cc b/components/brave_rewards/browser/rewards_service_browsertest.cc index a635018d3d79..300f99827952 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest.cc +++ b/components/brave_rewards/browser/rewards_service_browsertest.cc @@ -50,8 +50,6 @@ using braveledger_request_util::ServerTypes; -using namespace rewards_service_browsertest_utils; - using RewardsNotificationType = brave_rewards::RewardsNotificationService::RewardsNotificationType; @@ -271,7 +269,9 @@ class BraveRewardsBrowserTest std::vector GetSiteBannerTipOptions( content::WebContents* site_banner) { - WaitForSelector(site_banner, "[data-test-id=amount-wrapper] div span"); + rewards_service_browsertest_utils::WaitForElementToAppear( + site_banner, + "[data-test-id=amount-wrapper] div span"); auto options = content::EvalJs( site_banner, R"( @@ -293,6 +293,9 @@ class BraveRewardsBrowserTest static std::vector GetRewardsPopupTipOptions( content::WebContents* popup) { + rewards_service_browsertest_utils::WaitForElementToAppear( + popup, + "option:not(:disabled)"); auto options = content::EvalJs( popup, R"_( @@ -517,76 +520,6 @@ class BraveRewardsBrowserTest wait_for_recurring_tip_saved_loop_->Run(); } - void DragAndDrop( - content::WebContents* contents, - const std::string& drag_selector, - const std::string& drop_selector) { - const std::string js_code = base::StringPrintf( - R"( - var triggerDragAndDrop = function (selectorDrag, selectorDrop) { - - // function for triggering mouse events - var fireMouseEvent = function (type, elem, centerX, centerY) { - var evt = document.createEvent('MouseEvents'); - evt.initMouseEvent(type, true, true, window, 1, 1, 1, centerX, - centerY, false, false, false, false, 0, elem); - elem.dispatchEvent(evt); - }; - - // fetch target elements - var elemDrag = document.querySelector(selectorDrag); - var elemDrop = document.querySelector(selectorDrop); - if (!elemDrag || !elemDrop) return false; - - // calculate positions - var pos = elemDrag.getBoundingClientRect(); - var center1X = Math.floor((pos.left + pos.right) / 2); - var center1Y = Math.floor((pos.top + pos.bottom) / 2); - pos = elemDrop.getBoundingClientRect(); - var center2X = Math.floor((pos.left + pos.right) / 2); - var center2Y = Math.floor((pos.top + pos.bottom) / 2); - - // mouse over dragged element and mousedown - fireMouseEvent('mousemove', elemDrag, center1X, center1Y); - fireMouseEvent('mouseenter', elemDrag, center1X, center1Y); - fireMouseEvent('mouseover', elemDrag, center1X, center1Y); - fireMouseEvent('mousedown', elemDrag, center1X, center1Y); - - // start dragging process over to drop target - fireMouseEvent('dragstart', elemDrag, center1X, center1Y); - fireMouseEvent('drag', elemDrag, center1X, center1Y); - fireMouseEvent('mousemove', elemDrag, center1X, center1Y); - fireMouseEvent('drag', elemDrag, center2X, center2Y); - fireMouseEvent('mousemove', elemDrop, center2X, center2Y); - - // trigger dragging process on top of drop target - fireMouseEvent('mouseenter', elemDrop, center2X, center2Y); - fireMouseEvent('dragenter', elemDrop, center2X, center2Y); - fireMouseEvent('mouseover', elemDrop, center2X, center2Y); - fireMouseEvent('dragover', elemDrop, center2X, center2Y); - - // release dragged element on top of drop target - fireMouseEvent('drop', elemDrop, center2X, center2Y); - fireMouseEvent('dragend', elemDrag, center2X, center2Y); - fireMouseEvent('mouseup', elemDrag, center2X, center2Y); - - return true; - }; - - triggerDragAndDrop( - '%s', - '%s') - )", - drag_selector.c_str(), - drop_selector.c_str()); - content::EvalJsResult jsResult = EvalJs( - contents, - js_code, - content::EXECUTE_SCRIPT_NO_RESOLVE_PROMISES, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(jsResult.ExtractBool()); - } - void AddNotificationServiceObserver() { rewards_service_->GetNotificationService()->AddObserver(this); } @@ -679,7 +612,9 @@ class BraveRewardsBrowserTest // Wait for the popup to load popup_observer.Wait(); - WaitForSelector(popup_contents, "[data-test-id='rewards-panel']"); + rewards_service_browsertest_utils::WaitForElementToAppear( + popup_contents, + "[data-test-id='rewards-panel']"); return popup_contents; } @@ -814,8 +749,12 @@ class BraveRewardsBrowserTest ui_test_utils::NavigateToURL(browser(), page_url); WaitForLoadStop(contents()); // Opt in and create wallet to enable rewards - WaitForElementThenClick(contents(), "[data-test-id='optInAction']"); - WaitForElementToAppear(contents(), "[data-test-id2='enableMain']"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id='optInAction']"); + rewards_service_browsertest_utils::WaitForElementToAppear( + contents(), + "[data-test-id2='enableMain']"); } void EnableRewardsViaCode() { @@ -849,15 +788,21 @@ class BraveRewardsBrowserTest // Claim promotion via settings page or panel, as instructed if (use_panel) { - WaitForElementThenClick(contents, "button"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents, + "button"); } else { - WaitForElementThenClick(contents, "[data-test-id='claimGrant']"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents, + "[data-test-id='claimGrant']"); } // Wait for CAPTCHA - WaitForElementToAppear(contents, "[data-test-id='captcha']"); + rewards_service_browsertest_utils::WaitForElementToAppear( + contents, + "[data-test-id='captcha']"); - DragAndDrop( + rewards_service_browsertest_utils::DragAndDrop( contents, "[data-test-id=\"captcha-triangle\"]", "[data-test-id=\"captcha-drop\"]"); @@ -875,12 +820,20 @@ class BraveRewardsBrowserTest // Check that promotion notification shows the appropriate amount const std::string selector = use_panel ? "[id='root']" : "[data-test-id='newTokenGrant']"; - WaitForElementToContain(contents, selector, "Free Token Grant"); - WaitForElementToContain(contents, selector, "30.0 BAT"); + rewards_service_browsertest_utils::WaitForElementToContain( + contents, + selector, + "Free Token Grant"); + rewards_service_browsertest_utils::WaitForElementToContain( + contents, + selector, + "30.0 BAT"); // Dismiss the promotion notification if (use_panel) { - WaitForElementThenClick(contents, "#grant-completed-ok"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents, "#" + "grant-completed-ok"); } } @@ -903,8 +856,10 @@ class BraveRewardsBrowserTest WaitForPublisherListNormalized(); // Make sure site appears in auto-contribute table - WaitForElementToEqual(contents(), - "[data-test-id='ac_link_" + publisher + "']", publisher); + rewards_service_browsertest_utils::WaitForElementToEqual( + contents(), + "[data-test-id='ac_link_" + publisher + "']", + publisher); if (verified) { // A verified site has two images associated with it, the site's @@ -934,19 +889,13 @@ class BraveRewardsBrowserTest } std::string RewardsPageTipSummaryAmount() const { - std::string amount = ElementInnerText( + const std::string amount = + rewards_service_browsertest_utils::WaitForElementThenGetContent( + contents(), "[data-test-id=summary-tips] [color=contribute] span span"); return amount + " BAT"; } - std::string ExpectedPendingBalanceString() const { - return GetPendingBalance() + " BAT"; - } - - std::string ExpectedBalanceString() const { - return GetBalance() + " BAT"; - } - 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; @@ -960,7 +909,7 @@ class BraveRewardsBrowserTest } void RefreshPublisherListUsingRewardsPopup() const { - WaitForElementThenClick( + rewards_service_browsertest_utils::WaitForElementThenClick( OpenRewardsPopup(), "[data-test-id='unverified-check-button']"); } @@ -979,7 +928,9 @@ class BraveRewardsBrowserTest : "[type='tip']"; // Click button to initiate sending a tip. - WaitForElementThenClick(popup_contents, buttonSelector); + rewards_service_browsertest_utils::WaitForElementThenClick( + popup_contents, + buttonSelector); // Wait for the site banner to load site_banner_observer.Wait(); @@ -1026,10 +977,13 @@ class BraveRewardsBrowserTest std::string amount_selector = base::StringPrintf( "div:nth-of-type(%u)>[data-test-id=amount-wrapper]", selection + 1); - WaitForElementThenClick(site_banner_contents, amount_selector); + rewards_service_browsertest_utils::WaitForElementThenClick( + site_banner_contents, + amount_selector); // Send the tip - WaitForElementThenClick(site_banner_contents, + rewards_service_browsertest_utils::WaitForElementThenClick( + site_banner_contents, "[data-test-id='send-tip-button']"); // Signal that direct tip was made and update wallet with new @@ -1074,21 +1028,22 @@ class BraveRewardsBrowserTest // Make sure that thank you banner shows correct publisher data // (domain and amount) { - content::EvalJsResult js_result = EvalJs( + rewards_service_browsertest_utils::WaitForElementToContain( + site_banner_contents, + "body", + confirmationText); + rewards_service_browsertest_utils::WaitForElementToContain( + site_banner_contents, + "body", + amount_str + " BAT"); + rewards_service_browsertest_utils::WaitForElementToContain( site_banner_contents, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(1000).then(() => " - " document.documentElement.innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result.ExtractString().find( - confirmationText), std::string::npos); - EXPECT_NE(js_result.ExtractString().find( - "" + amount_str + " BAT"), std::string::npos); - EXPECT_NE(js_result.ExtractString().find( - "Share the good news:"), std::string::npos); - EXPECT_NE(js_result.ExtractString().find( - "" + GetBalance() + " BAT"), std::string::npos); + "body", + "Share the good news:"); + rewards_service_browsertest_utils::WaitForElementToContain( + site_banner_contents, + "body", + "" + GetBalance() + " BAT"); } VerifyTip(amount, should_contribute, type == ContributionType::MonthlyTip); @@ -1108,69 +1063,47 @@ class BraveRewardsBrowserTest if (should_contribute) { // Make sure that balance is updated correctly - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); + IsBalanceCorrect(); // Check that tip table shows the appropriate tip amount const std::string selector = monthly ? "[data-test-id='summary-monthly']" : "[data-test-id='summary-tips']"; - WaitForElementToContain(contents(), selector, - "-" + BalanceDoubleToString(amount) + "BAT"); - } else { - // Make sure that balance did not change - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); - - // Make sure that pending contribution box shows the correct - // amount - WaitForElementToContain( + rewards_service_browsertest_utils::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(), - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelectorAll(\"[type='donation']\")[1]" - " .parentElement.parentElement.innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE( - js_result.ExtractString().find("Total tips this month\n0.0BAT"), - std::string::npos); - } + selector, + "-" + BalanceDoubleToString(amount) + "BAT"); + return; } + + // Make sure that balance did not change + IsBalanceCorrect(); + + // Make sure that pending contribution box shows the correct + // amount + IsPendingBalanceCorrect(); + + rewards_service_browsertest_utils::WaitForElementToEqual( + contents(), + "#tip-box-total", + "0.0BAT0.00 USD"); } - bool IsMediaTipsInjected() { - content::EvalJsResult js_result = - EvalJs(contents(), - "new Promise((resolve) => {" - "let count = 10;" - "var interval = setInterval(function() {" - " if (count === 0) {" - " clearInterval(interval);" - " resolve(false);" - " } else {" - " count -= 1;" - " }" - " const braveTipActions" - " = document.querySelectorAll(\".action-brave-tip\");" - " if (braveTipActions && braveTipActions.length === 1) {" - " clearInterval(interval);" - " resolve(true);" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - return js_result.ExtractBool(); + void IsBalanceCorrect() { + const std::string balance = GetBalance() + " BAT"; + rewards_service_browsertest_utils::WaitForElementToEqual( + contents(), + "[data-test-id='balance']", + balance); + } + + void IsPendingBalanceCorrect() { + const std::string balance = GetPendingBalance() + " BAT"; + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[data-test-id='pending-contribution-box']", + balance); } void OnWalletInitialized(brave_rewards::RewardsService* rewards_service, @@ -1356,6 +1289,7 @@ class BraveRewardsBrowserTest const ledger::Result result = ledger::Result::LEDGER_OK) { tip_reconcile_completed_ = false; pending_tip_saved_ = false; + auto site = std::make_unique(); site->id = publisher_key; site->name = publisher_key; @@ -1477,48 +1411,25 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ToggleRewards) { EnableRewards(); // Toggle rewards off - content::EvalJsResult toggleOffResult = EvalJs(contents(), - "document.querySelector(\"[data-test-id2='enableMain']\").click();" - "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(document.querySelector(\"[data-test-id2='enableMain']\")" - " .getAttribute(\"data-toggled\") === 'false');" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(toggleOffResult.ExtractBool()); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id2='enableMain']"); + std::string value = + rewards_service_browsertest_utils::WaitForElementThenGetAttribute( + contents(), + "[data-test-id2='enableMain']", + "data-toggled"); + ASSERT_STREQ(value.c_str(), "false"); // Toggle rewards back on - content::EvalJsResult toggleOnResult = EvalJs(contents(), - "document.querySelector(\"[data-test-id2='enableMain']\").click();" - "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(document.querySelector(\"[data-test-id2='enableMain']\")" - " .getAttribute(\"data-toggled\") === 'true');" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(toggleOnResult.ExtractBool()); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id2='enableMain']"); + value = rewards_service_browsertest_utils::WaitForElementThenGetAttribute( + contents(), + "[data-test-id2='enableMain']", + "data-toggled"); + ASSERT_STREQ(value.c_str(), "true"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ToggleAutoContribute) { @@ -1529,64 +1440,36 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ToggleAutoContribute) { EXPECT_TRUE(WaitForLoadStop(contents())); // toggle auto contribute off - content::EvalJsResult toggleOffResult = EvalJs(contents(), - "let toggleClicked = false;" - "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='autoContribution']\")) {" - " if (!toggleClicked) {" - " toggleClicked = true;" - " document.querySelector(" - " \"[data-test-id2='autoContribution']\").click();" - " } else {" - " clearInterval(interval);" - " resolve(document.querySelector(" - " \"[data-test-id2='autoContribution']\")" - " .getAttribute(\"data-toggled\") === 'false');" - " }" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(toggleOffResult.ExtractBool()); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id2='autoContribution']"); + std::string value = + rewards_service_browsertest_utils::WaitForElementThenGetAttribute( + contents(), + "[data-test-id2='autoContribution']", + "data-toggled"); + ASSERT_STREQ(value.c_str(), "false"); // toggle auto contribute back on - content::EvalJsResult toggleOnResult = EvalJs( + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id2='autoContribution']"); + value = rewards_service_browsertest_utils::WaitForElementThenGetAttribute( contents(), - "document.querySelector(\"[data-test-id2='autoContribution']\").click();" - "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='autoContribution']\")) {" - " clearInterval(interval);" - " " - "resolve(document.querySelector(\"[data-test-id2='autoContribution']\")" - " .getAttribute(\"data-toggled\") === 'true');" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(toggleOnResult.ExtractBool()); + "[data-test-id2='autoContribution']", + "data-toggled"); + ASSERT_STREQ(value.c_str(), "true"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ActivateSettingsModal) { EnableRewards(); - WaitForElementThenClick(contents(), "[data-test-id='settingsButton']"); - WaitForElementToAppear(contents(), "#modal"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id='settingsButton']"); + rewards_service_browsertest_utils::WaitForElementToAppear( + contents(), + "#modal"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, HandleFlagsSingleArg) { @@ -1821,24 +1704,24 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, // Retrieve the inner text of the wallet panel and verify that it // looks as expected - WaitForElementToContain(popup_contents, "[id='wallet-panel']", + rewards_service_browsertest_utils::WaitForElementToContain( + popup_contents, + "[id='wallet-panel']", "Brave Verified Creator"); - WaitForElementToContain(popup_contents, "[id='wallet-panel']", publisher); + rewards_service_browsertest_utils::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, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector(\"[id='wallet-panel']\").innerHTML);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); const std::string favicon = "chrome://favicon/size/48@2x/https://" + publisher; - EXPECT_NE(js_result.ExtractString().find(favicon), std::string::npos); + rewards_service_browsertest_utils::WaitForElementToContainHTML( + popup_contents, + "#wallet-panel", + favicon); } } @@ -1883,11 +1766,13 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, AutoContribution) { ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); + IsBalanceCorrect(); // Check that summary table shows the appropriate contribution - WaitForElementToContain(contents(), "[color=contribute]", "-20.0BAT"); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[color=contribute]", + "-20.0BAT"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, AutoContributeWhenACOff) { @@ -1902,33 +1787,15 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, AutoContributeWhenACOff) { VisitPublisher("duckduckgo.com", verified); // toggle auto contribute off - content::EvalJsResult toggleOffResult = EvalJs(contents(), - "let toggleClicked = false;" - "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='autoContribution']\")) {" - " if (!toggleClicked) {" - " toggleClicked = true;" - " document.querySelector(" - " \"[data-test-id2='autoContribution']\").click();" - " } else {" - " clearInterval(interval);" - " resolve(document.querySelector(" - " \"[data-test-id2='autoContribution']\")" - " .getAttribute(\"data-toggled\") === 'false');" - " }" - " }" - "}, 500);});", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_TRUE(toggleOffResult.ExtractBool()); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id2='autoContribution']"); + std::string value = + rewards_service_browsertest_utils::WaitForElementThenGetAttribute( + contents(), + "[data-test-id2='autoContribution']", + "data-toggled"); + ASSERT_STREQ(value.c_str(), "false"); // Trigger contribution process rewards_service()->StartMonthlyContributionForTest(); @@ -2000,7 +1867,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, TwitterTipsInjectedOnTwitter) { ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media tips injection is active - EXPECT_TRUE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), true); } // Brave tip icon is not injected when visiting Twitter while Brave @@ -2014,7 +1881,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is injected when visiting old Twitter @@ -2030,7 +1897,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media tips injection is active - EXPECT_TRUE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), true); } // Brave tip icon is not injected when visiting old Twitter while @@ -2044,7 +1911,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is not injected into non-Twitter sites @@ -2060,7 +1927,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is injected when visiting Reddit @@ -2075,7 +1942,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, RedditTipsInjectedOnReddit) { ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is active - EXPECT_TRUE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), true); } // Brave tip icon is not injected when visiting Reddit @@ -2088,7 +1955,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is not injected when visiting Reddit @@ -2104,7 +1971,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is injected when visiting GitHub @@ -2119,7 +1986,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, GitHubTipsInjectedOnGitHub) { ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is active - EXPECT_TRUE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), true); } // Brave tip icon is not injected when visiting GitHub while Brave @@ -2133,7 +2000,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Brave tip icon is not injected when not visiting GitHub @@ -2149,7 +2016,7 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); // Ensure that Media Tips injection is not active - EXPECT_FALSE(IsMediaTipsInjected()); + rewards_service_browsertest_utils::IsMediaTipsInjected(contents(), false); } // Check pending contributions @@ -2167,28 +2034,15 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, // Tip unverified publisher 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(), - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector(\"[data-test-id='reservedAllLink']\")" - " .parentElement.parentElement.innerText);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE( - js_result.ExtractString().find("Show all pending contributions"), - std::string::npos); - } - - // Open modal - WaitForElementThenClick(contents(), "[data-test-id='reservedAllLink']"); + // Check that link for pending is shown and open modal + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id='reservedAllLink']"); // Make sure that table is populated - WaitForElementToContain(contents(), "[id='pendingContributionTable'] a", + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[id='pendingContributionTable'] a", publisher); } @@ -2329,9 +2183,9 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, PrefsTestInPrivateWindow) { brave_rewards::prefs::kBraveRewardsEnabled)); } -IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, - ProcessPendingContributions) { +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ProcessPendingContributions) { AddNotificationServiceObserver(); + alter_publisher_list_ = true; EnableRewards(); @@ -2371,34 +2225,38 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, UpdateContributionBalance(-25.0, false); // update pending balance // Make sure that balance is updated correctly - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); + IsBalanceCorrect(); // Check that wallet summary shows the appropriate tip amount - WaitForElementToEqual( + rewards_service_browsertest_utils::WaitForElementToEqual( contents(), - "[data-test-id=summary-tips] [color=donation] span span", + "[data-test-id=summary-tips] [color=contribute] span span", ExpectedTipSummaryAmountString()); // Make sure that pending contribution box shows the correct // amount - WaitForElementToContain( - contents(), - "[data-test-id='pending-contribution-box']", - ExpectedPendingBalanceString()); + IsPendingBalanceCorrect(); // Open the Rewards popup content::WebContents* popup_contents = OpenRewardsPopup(); ASSERT_TRUE(popup_contents); // Check if verified notification is shown - WaitForElementToContain(popup_contents, "#root", "3zsistemi.si"); + rewards_service_browsertest_utils::WaitForElementToContain( + popup_contents, + "#root", + "3zsistemi.si"); // Close notification - WaitForElementThenClick(popup_contents, "[data-test-id=notification-close]"); + rewards_service_browsertest_utils::WaitForElementThenClick( + popup_contents, + "[data-test-id=notification-close]"); // Check if insufficient funds notification is shown - WaitForElementToContain(popup_contents, "#root", "Insufficient Funds"); + rewards_service_browsertest_utils::WaitForElementToContain( + popup_contents, + "#root", + "Insufficient Funds"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, RewardsPanelDefaultTipChoices) { @@ -2462,15 +2320,18 @@ IN_PROC_BROWSER_TEST_F( ASSERT_EQ(tip_options, std::vector({ 5, 10, 20 })); } -IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, - NotVerifedWallet) { +IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, NotVerifiedWallet) { EnableRewards(); // Click on verify button - WaitForElementThenClick(contents(), "#verify-wallet-button"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "#verify-wallet-button"); // Click on verify button in on boarding - WaitForElementThenClick(contents(), "#on-boarding-verify-button"); + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "#on-boarding-verify-button"); // Check if we are redirected to uphold { @@ -2511,9 +2372,6 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ledger::PublisherStatus::VERIFIED, should_contribute); VerifyTip(amount, should_contribute, false, true); - - // Stop observing the Rewards service - rewards_service()->RemoveObserver(this); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, @@ -2552,9 +2410,6 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, for (auto const& value : transfer_fees) { ASSERT_EQ(value.second->amount, tip_fee); } - - // Stop observing the Rewards service - rewards_service()->RemoveObserver(this); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, TipConnectedPublisherAnon) { @@ -2611,7 +2466,7 @@ IN_PROC_BROWSER_TEST_F( // Tip connected publisher const double amount = 5.0; - const bool should_contribute = true; + const bool should_contribute = false; TipViaCode( "bumpsmack.com", amount, @@ -2620,7 +2475,13 @@ IN_PROC_BROWSER_TEST_F( false, ledger::Result::LEDGER_ERROR); - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + IsBalanceCorrect(); + + // Make sure that tips table is empty + rewards_service_browsertest_utils::WaitForElementToEqual( + contents(), + "#tips-table > div > div", + "Have you tipped your favorite content creator today?"); } IN_PROC_BROWSER_TEST_F( @@ -2633,9 +2494,9 @@ IN_PROC_BROWSER_TEST_F( contents()->GetController().Reload(content::ReloadType::NORMAL, true); EXPECT_TRUE(WaitForLoadStop(contents())); - // Tip verified publisher + // Tip connected publisher const double amount = 5.0; - const bool should_contribute = true; + const bool should_contribute = false; TipViaCode( "bumpsmack.com", amount, @@ -2644,7 +2505,13 @@ IN_PROC_BROWSER_TEST_F( false, ledger::Result::LEDGER_ERROR); - ASSERT_EQ(RewardsPageBalance(), ExpectedBalanceString()); + IsBalanceCorrect(); + + // Make sure that tips table is empty + rewards_service_browsertest_utils::WaitForElementToEqual( + contents(), + "#tips-table > div > div", + "Have you tipped your favorite content creator today?"); } // Ensure that we can make a one-time tip of a non-integral amount. @@ -2715,11 +2582,13 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); + IsBalanceCorrect(); // Check that summary table shows the appropriate contribution - WaitForElementToContain(contents(), "[color='contribute']", "-5.0BAT"); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[color='contribute']", + "-5.0BAT"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, @@ -2775,13 +2644,15 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ASSERT_EQ(ac_reconcile_status_, ledger::Result::LEDGER_OK); // Make sure that balance is updated correctly - WaitForElementToEqual(contents(), "[data-test-id='balance']", - ExpectedBalanceString()); + IsBalanceCorrect(); // Check that summary table shows the appropriate contribution // Check that summary table shows the appropriate contribution - WaitForElementToContain(contents(), "[color='contribute']", "-5.0BAT"); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[color='contribute']", + "-5.0BAT"); } IN_PROC_BROWSER_TEST_F( @@ -2812,7 +2683,9 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ShowMonthlyIfACOff) { content::WebContents *popup_contents = OpenRewardsPopup(); ASSERT_TRUE(popup_contents); - WaitForSelector(popup_contents, "#panel-donate-monthly"); + rewards_service_browsertest_utils::WaitForElementToAppear( + popup_contents, + "#panel-donate-monthly"); } IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ShowACPercentInThePanel) { @@ -2829,17 +2702,11 @@ IN_PROC_BROWSER_TEST_F(BraveRewardsBrowserTest, ShowACPercentInThePanel) { content::WebContents *popup_contents = OpenRewardsPopup(); ASSERT_TRUE(popup_contents); - { - content::EvalJsResult js_result = EvalJs( - popup_contents, - "const delay = t => new Promise(resolve => setTimeout(resolve, t));" - "delay(0).then(() => " - " document.querySelector(\"[data-test-id='attention-score']\")" - " .innerHTML);", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END); - EXPECT_NE(js_result.ExtractString().find("100%"), std::string::npos); - } + const std::string score = + rewards_service_browsertest_utils::WaitForElementThenGetContent( + popup_contents, + "[data-test-id='attention-score']"); + EXPECT_NE(score.find("100%"), std::string::npos); } IN_PROC_BROWSER_TEST_F( @@ -2866,22 +2733,27 @@ IN_PROC_BROWSER_TEST_F( ASSERT_EQ(multiple_ac_reconcile_status_[0], ledger::Result::LEDGER_OK); ASSERT_EQ(multiple_ac_reconcile_status_[1], ledger::Result::LEDGER_OK); - // Check monthly report - ASSERT_TRUE(ExecJs(contents(), - "document.querySelector(\"[data-test-id='showMonthlyReport']\").click();", - content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, - content::ISOLATED_WORLD_ID_CONTENT_END)); - + rewards_service_browsertest_utils::WaitForElementThenClick( + contents(), + "[data-test-id='showMonthlyReport']"); - WaitForSelector(contents(), "#transactionTable"); + rewards_service_browsertest_utils::WaitForElementToAppear( + contents(), + "#transactionTable"); - ASSERT_NE(ElementInnerText("#transactionTable").find("-30.0BAT"), - std::string::npos); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "#transactionTable", + "-30.0BAT"); - ASSERT_NE(ElementInnerText("#transactionTable").find("-20.0BAT"), - std::string::npos); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "#transactionTable", + "-20.0BAT"); // Check that summary table shows the appropriate contribution - ASSERT_NE(ElementInnerText("[color=contribute]").find("-50.0BAT"), - std::string::npos); + rewards_service_browsertest_utils::WaitForElementToContain( + contents(), + "[color=contribute]", + "-50.0BAT"); } diff --git a/components/brave_rewards/browser/rewards_service_browsertest_utils.cc b/components/brave_rewards/browser/rewards_service_browsertest_utils.cc index 915c97bf8912..323575ee3e27 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest_utils.cc +++ b/components/brave_rewards/browser/rewards_service_browsertest_utils.cc @@ -3,13 +3,13 @@ * 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 "brave/components/brave_rewards/browser/rewards_service_browsertest_utils.h" #include "content/public/test/browser_test_utils.h" namespace rewards_service_browsertest_utils { -static const std::string kWaitForElementToAppearScript = R"( +static const char kWaitForElementToAppearScript[] = R"( const waitForElementToAppear = (selector) => { const TIMEOUT_SECONDS = 5; @@ -39,8 +39,10 @@ static const std::string kWaitForElementToAppearScript = R"( }; )"; -void WaitForElementToAppear(content::WebContents* context, - const std::string& selector) { +void WaitForElementToAppear( + content::WebContents* context, + const std::string& selector, + bool should_appear) { auto script = kWaitForElementToAppearScript + content::JsReplace(R"( new Promise(async (resolve, reject) => { @@ -48,10 +50,9 @@ void WaitForElementToAppear(content::WebContents* context, const selector = $1; const element = await waitForElementToAppear(selector); - console.log("XXXX", element); resolve(true); } catch (error) { - reject(error); + resolve(false); } }) )", @@ -63,11 +64,13 @@ void WaitForElementToAppear(content::WebContents* context, content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, content::ISOLATED_WORLD_ID_CONTENT_END); - ASSERT_EQ(true, result); + ASSERT_EQ(should_appear, result); } -void WaitForElementToEqual(content::WebContents* context, - const std::string& selector, const std::string& expectedValue) { +void WaitForElementToEqual( + content::WebContents* context, + const std::string& selector, + const std::string& expectedValue) { auto script = kWaitForElementToAppearScript + content::JsReplace(R"( new Promise(async (resolve, reject) => { @@ -120,8 +123,10 @@ void WaitForElementToEqual(content::WebContents* context, ASSERT_EQ(true, result); } -void WaitForElementToContain(content::WebContents* context, - const std::string& selector, const std::string& substring) { +void WaitForElementToContain( + content::WebContents* context, + const std::string& selector, + const std::string& substring) { auto script = kWaitForElementToAppearScript + content::JsReplace(R"( new Promise(async (resolve, reject) => { @@ -174,9 +179,66 @@ void WaitForElementToContain(content::WebContents* context, ASSERT_EQ(true, result); } -void WaitForElementThenClick(content::WebContents* context, +void WaitForElementToContainHTML( + content::WebContents* context, + const std::string& selector, + const std::string& html) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + const TIMEOUT_SECONDS = 5; + const selector = $1; + const html = $2; + + try { + let element = await waitForElementToAppear(selector); + + if (element.innerHTML.indexOf(html) !== -1) { + resolve(true); + return; + } + + const timerID = window.setTimeout(() => { + observer.disconnect(); + reject(new Error("Timed out waiting for '" + selector + "' " + + "to contain '" + html + "'")); + }, TIMEOUT_SECONDS * 1000); + + const observer = new MutationObserver(({}, observer) => { + let element = document.querySelector(selector); + if (!element) { + return; + } + + if (element.innerHTML.indexOf(html) !== -1) { + clearTimeout(timerID); + observer.disconnect(); + resolve(true); + } + }); + observer.observe(document.documentElement, + { characterData: true, childList: true, subtree: true }); + } catch(error) { + reject(error); + } + }); + )", + selector, + html); + + 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 + + auto script = kWaitForElementToAppearScript + content::JsReplace(R"( new Promise(async (resolve, reject) => { try { @@ -201,4 +263,135 @@ void WaitForElementThenClick(content::WebContents* context, ASSERT_EQ(true, result); } -} // namespace rewards_service_browsertest_utils +std::string WaitForElementThenGetAttribute( + content::WebContents* context, + const std::string& selector, + const std::string& attribute_name) { + auto script = kWaitForElementToAppearScript + + content::JsReplace(R"( + new Promise(async (resolve, reject) => { + try { + const selector = $1; + const attributeName = $2; + + const element = await waitForElementToAppear(selector); + resolve(element.getAttribute(attributeName)); + } catch (error) { + reject(error); + } + }) + )", + selector, + attribute_name); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + return result.ExtractString(); +} + +std::string WaitForElementThenGetContent( + 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); + resolve(element.innerText); + } catch (error) { + reject(error); + } + }) + )", + selector); + + auto result = EvalJs( + context, + script, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + content::ISOLATED_WORLD_ID_CONTENT_END); + + return result.ExtractString(); +} + +void DragAndDrop( + content::WebContents* context, + const std::string& drag_selector, + const std::string& drop_selector) { + const std::string js_code = base::StringPrintf( + R"( + var triggerDragAndDrop = function (selectorDrag, selectorDrop) { + + // function for triggering mouse events + var fireMouseEvent = function (type, elem, centerX, centerY) { + var evt = document.createEvent('MouseEvents'); + evt.initMouseEvent(type, true, true, window, 1, 1, 1, centerX, + centerY, false, false, false, false, 0, elem); + elem.dispatchEvent(evt); + }; + + // fetch target elements + var elemDrag = document.querySelector(selectorDrag); + var elemDrop = document.querySelector(selectorDrop); + if (!elemDrag || !elemDrop) return false; + + // calculate positions + var pos = elemDrag.getBoundingClientRect(); + var center1X = Math.floor((pos.left + pos.right) / 2); + var center1Y = Math.floor((pos.top + pos.bottom) / 2); + pos = elemDrop.getBoundingClientRect(); + var center2X = Math.floor((pos.left + pos.right) / 2); + var center2Y = Math.floor((pos.top + pos.bottom) / 2); + + // mouse over dragged element and mousedown + fireMouseEvent('mousemove', elemDrag, center1X, center1Y); + fireMouseEvent('mouseenter', elemDrag, center1X, center1Y); + fireMouseEvent('mouseover', elemDrag, center1X, center1Y); + fireMouseEvent('mousedown', elemDrag, center1X, center1Y); + + // start dragging process over to drop target + fireMouseEvent('dragstart', elemDrag, center1X, center1Y); + fireMouseEvent('drag', elemDrag, center1X, center1Y); + fireMouseEvent('mousemove', elemDrag, center1X, center1Y); + fireMouseEvent('drag', elemDrag, center2X, center2Y); + fireMouseEvent('mousemove', elemDrop, center2X, center2Y); + + // trigger dragging process on top of drop target + fireMouseEvent('mouseenter', elemDrop, center2X, center2Y); + fireMouseEvent('dragenter', elemDrop, center2X, center2Y); + fireMouseEvent('mouseover', elemDrop, center2X, center2Y); + fireMouseEvent('dragover', elemDrop, center2X, center2Y); + + // release dragged element on top of drop target + fireMouseEvent('drop', elemDrop, center2X, center2Y); + fireMouseEvent('dragend', elemDrag, center2X, center2Y); + fireMouseEvent('mouseup', elemDrag, center2X, center2Y); + + return true; + }; + + triggerDragAndDrop( + '%s', + '%s') + )", + drag_selector.c_str(), + drop_selector.c_str()); + content::EvalJsResult jsResult = EvalJs( + context, + js_code, + content::EXECUTE_SCRIPT_NO_RESOLVE_PROMISES, + content::ISOLATED_WORLD_ID_CONTENT_END); + ASSERT_TRUE(jsResult.ExtractBool()); +} + +void IsMediaTipsInjected(content::WebContents* context, bool should_appear) { + WaitForElementToAppear(context, ".action-brave-tip", should_appear); +} + +} // 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 index cc1b795ec7dd..e9cf9952c897 100644 --- a/components/brave_rewards/browser/rewards_service_browsertest_utils.h +++ b/components/brave_rewards/browser/rewards_service_browsertest_utils.h @@ -3,31 +3,58 @@ * 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_ +#ifndef BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_REWARDS_SERVICE_BROWSERTEST_UTILS_H_ +#define BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_REWARDS_SERVICE_BROWSERTEST_UTILS_H_ #include #include "build/build_config.h" - namespace content { class WebContents; -} // namespace content +} // namespace content namespace rewards_service_browsertest_utils { -void WaitForElementToAppear(content::WebContents*, - const std::string& selector); +void WaitForElementToAppear( + content::WebContents* context, + const std::string& selector, + bool should_appear = true); + +void WaitForElementToEqual( + content::WebContents*, + const std::string& selector, + const std::string& expectedValue); + +void WaitForElementToContain( + content::WebContents* context, + const std::string& selector, + const std::string& substring); -void WaitForElementToEqual(content::WebContents*, - const std::string& selector, const std::string& expectedValue); +void WaitForElementToContainHTML( + content::WebContents* context, + const std::string& selector, + const std::string& html); -void WaitForElementToContain(content::WebContents*, - const std::string& selector, const std::string& substring); +void WaitForElementThenClick( + content::WebContents* context, + const std::string& selector); + +std::string WaitForElementThenGetAttribute( + content::WebContents* context, + const std::string& selector, + const std::string& attribute_name); -void WaitForElementThenClick(content::WebContents*, +std::string WaitForElementThenGetContent( + content::WebContents* context, const std::string& selector); -} // namespace rewards_service_browsertest_utils +void DragAndDrop( + content::WebContents* context, + const std::string& drag_selector, + const std::string& drop_selector); + +void IsMediaTipsInjected(content::WebContents* contents, bool should_appear); + +} // namespace rewards_service_browsertest_utils -#endif // REWARDS_SERVICE_BROWSERTEST_UTILS_H_ +#endif // BRAVE_COMPONENTS_BRAVE_REWARDS_BROWSER_REWARDS_SERVICE_BROWSERTEST_UTILS_H_ diff --git a/components/brave_rewards/resources/page/components/tipsBox.tsx b/components/brave_rewards/resources/page/components/tipsBox.tsx index f345f1810d62..0106ba475253 100644 --- a/components/brave_rewards/resources/page/components/tipsBox.tsx +++ b/components/brave_rewards/resources/page/components/tipsBox.tsx @@ -195,9 +195,10 @@ class TipBox extends React.Component { : null } - + status != ledger::PublisherStatus::VERIFIED) { BLOG(ledger_, ledger::LogLevel::LOG_ERROR) << "Publisher not verified"; - // we don't need callback as there is nothing to report back - SavePendingContribution( - info->publisher_key, - amount, - type, - [](const ledger::Result){}); + auto save_callback = std::bind(&Contribution::OnSavePendingContribution, + this, + _1); + + SavePendingContribution(info->publisher_key, amount, type, save_callback); ledger_->ContributionCompleted( ledger::Result::LEDGER_ERROR,