summaryrefslogtreecommitdiff
path: root/chromium/content/browser/conversions/conversion_internals_browsertest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/conversions/conversion_internals_browsertest.cc')
-rw-r--r--chromium/content/browser/conversions/conversion_internals_browsertest.cc284
1 files changed, 284 insertions, 0 deletions
diff --git a/chromium/content/browser/conversions/conversion_internals_browsertest.cc b/chromium/content/browser/conversions/conversion_internals_browsertest.cc
new file mode 100644
index 00000000000..9f88538a1de
--- /dev/null
+++ b/chromium/content/browser/conversions/conversion_internals_browsertest.cc
@@ -0,0 +1,284 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/conversions/conversion_internals_ui.h"
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "content/browser/conversions/conversion_manager.h"
+#include "content/browser/conversions/conversion_report.h"
+#include "content/browser/conversions/conversion_test_utils.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+
+namespace content {
+
+namespace {
+
+const char kConversionInternalsUrl[] = "chrome://conversion-internals/";
+
+const base::string16 kCompleteTitle = base::ASCIIToUTF16("Complete");
+
+} // namespace
+
+class ConversionInternalsWebUiBrowserTest : public ContentBrowserTest {
+ public:
+ ConversionInternalsWebUiBrowserTest() = default;
+
+ void ClickRefreshButton() {
+ EXPECT_TRUE(ExecJsInWebUI("document.getElementById('refresh').click();"));
+ }
+
+ // Executing javascript in the WebUI requires using an isolated world in which
+ // to execute the script because WebUI has a default CSP policy denying
+ // "eval()", which is what EvalJs uses under the hood.
+ bool ExecJsInWebUI(std::string script) {
+ return ExecJs(shell()->web_contents()->GetMainFrame(), script,
+ EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */);
+ }
+
+ void OverrideWebUIConversionManager(ConversionManager* manager) {
+ content::WebUI* web_ui = shell()->web_contents()->GetWebUI();
+
+ // Performs a safe downcast to the concrete ConversionInternalsUI subclass.
+ ConversionInternalsUI* conversion_internals_ui =
+ web_ui ? web_ui->GetController()->GetAs<ConversionInternalsUI>()
+ : nullptr;
+ EXPECT_TRUE(conversion_internals_ui);
+ conversion_internals_ui->SetConversionManagerProviderForTesting(
+ std::make_unique<TestManagerProvider>(manager));
+ }
+
+ // Registers a mutation observer that sets the window title to |title| when
+ // the report table is empty.
+ void SetTitleOnReportsTableEmpty(const base::string16& title) {
+ const std::string kObserveEmptyReportsTableScript = R"(
+ let table = document.getElementById("report-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 1 &&
+ table.children[0].children[0].innerText === "No pending reports.") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(
+ ExecJsInWebUI(JsReplace(kObserveEmptyReportsTableScript, title)));
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ NavigationUrl_ResolvedToWebUI) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ // Execute script to ensure the page has loaded correctly, executing similarly
+ // to ExecJsInWebUI().
+ EXPECT_EQ(
+ true,
+ EvalJs(shell()->web_contents()->GetMainFrame(),
+ "document.body.innerHTML.search('Conversion Internals') >= 0;",
+ EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUIShownWithManager_MeasurementConsideredEnabled) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ OverrideWebUIConversionManager(&manager);
+
+ // Create a mutation observer to wait for the content to render to the dom.
+ // Waiting on calls to TestConversionManager is not sufficient because the
+ // results are returned in promises.
+ std::string wait_script = R"(
+ let status = document.getElementById("feature-status-content");
+ let obs = new MutationObserver(() => {
+ if (status.innerText.trim() === "enabled") {
+ document.title = $1;
+ }
+ });
+ obs.observe(status, {'childList': true, 'characterData': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(
+ ConversionInternalsWebUiBrowserTest,
+ WebUIShownWithNoActiveImpression_NoImpressionsDisplayed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ OverrideWebUIConversionManager(&manager);
+
+ std::string wait_script = R"(
+ let table = document.getElementById("impression-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 1 &&
+ table.children[0].children[0].innerText ===
+ "No active impressions.") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUIShownWithActiveImpression_ImpressionsDisplayed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ manager.SetActiveImpressionsForWebUI(
+ {ImpressionBuilder(base::Time::Now()).SetData("100").Build(),
+ ImpressionBuilder(base::Time::Now()).Build()});
+ OverrideWebUIConversionManager(&manager);
+
+ std::string wait_script = R"(
+ let table = document.getElementById("impression-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 2 &&
+ table.children[0].children[0].innerText === "0x100") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUIShownWithNoReports_NoReportsDisplayed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ OverrideWebUIConversionManager(&manager);
+
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ SetTitleOnReportsTableEmpty(kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUIShownWithPendingReports_ReportsDisplayed) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ ConversionReport report(
+ ImpressionBuilder(base::Time::Now()).SetData("100").Build(),
+ "7" /* conversion_data */, base::Time::Now() /* report_time */,
+ 1 /* conversion_id */);
+ manager.SetReportsForWebUI({report});
+ OverrideWebUIConversionManager(&manager);
+
+ std::string wait_script = R"(
+ let table = document.getElementById("report-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 1 &&
+ table.children[0].children[1].innerText === "0x7") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUIWithPendingReportsClearStorage_ReportsRemoved) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ ConversionReport report(
+ ImpressionBuilder(base::Time::Now()).SetData("100").Build(),
+ "7" /* conversion_data */, base::Time::Now() /* report_time */,
+ 1 /* conversion_id */);
+ manager.SetReportsForWebUI({report});
+ OverrideWebUIConversionManager(&manager);
+
+ std::string wait_script = R"(
+ let table = document.getElementById("report-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 1 &&
+ table.children[0].children[1].innerText === "0x7") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ // Wait for the table to rendered.
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+
+ // Click the clear storage button and expect that the report table is emptied.
+ const base::string16 kDeleteTitle = base::ASCIIToUTF16("Delete");
+ TitleWatcher delete_title_watcher(shell()->web_contents(), kDeleteTitle);
+ SetTitleOnReportsTableEmpty(kDeleteTitle);
+
+ // Click the button.
+ EXPECT_TRUE(ExecJsInWebUI("document.getElementById('clear-data').click();"));
+ EXPECT_EQ(kDeleteTitle, delete_title_watcher.WaitAndGetTitle());
+}
+
+// TODO(johnidel): Use a real ConversionManager here and verify that the reports
+// are actually sent.
+IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest,
+ WebUISendReports_ReportsRemoved) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl)));
+
+ TestConversionManager manager;
+ ConversionReport report(
+ ImpressionBuilder(base::Time::Now()).SetData("100").Build(),
+ "7" /* conversion_data */, base::Time::Now() /* report_time */,
+ 1 /* conversion_id */);
+ manager.SetReportsForWebUI({report});
+ OverrideWebUIConversionManager(&manager);
+
+ std::string wait_script = R"(
+ let table = document.getElementById("report-table-body");
+ let obs = new MutationObserver(() => {
+ if (table.children.length === 1 &&
+ table.children[0].children[1].innerText === "0x7") {
+ document.title = $1;
+ }
+ });
+ obs.observe(table, {'childList': true});)";
+ EXPECT_TRUE(ExecJsInWebUI(JsReplace(wait_script, kCompleteTitle)));
+
+ // Wait for the table to rendered.
+ TitleWatcher title_watcher(shell()->web_contents(), kCompleteTitle);
+ ClickRefreshButton();
+ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle());
+
+ // Click the send reports button and expect that the report table is emptied.
+ const base::string16 kSentTitle = base::ASCIIToUTF16("Sent");
+ TitleWatcher sent_title_watcher(shell()->web_contents(), kSentTitle);
+ SetTitleOnReportsTableEmpty(kSentTitle);
+
+ EXPECT_TRUE(
+ ExecJsInWebUI("document.getElementById('send-reports').click();"));
+ EXPECT_EQ(kSentTitle, sent_title_watcher.WaitAndGetTitle());
+}
+
+} // namespace content