Bug 1570631 - Part 5: test cases; r=k88hudson
authorLiang-Heng Chen <xeonchen@gmail.com>
Wed, 11 Sep 2019 09:16:11 +0000
changeset 492662 26009ef5fd47591cfa37b25cb7b01b739d564729
parent 492661 94c10676584a38959649712aeb7a0dbe29b8febf
child 492663 ec9772477adaf65f4516b3e9f1e8486e9b11170b
push id95056
push userxeonchen@gmail.com
push dateWed, 11 Sep 2019 12:15:45 +0000
treeherderautoland@26009ef5fd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersk88hudson
bugs1570631
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1570631 - Part 5: test cases; r=k88hudson Differential Revision: https://phabricator.services.mozilla.com/D43753
browser/components/newtab/test/browser/browser_asrouter_cfr.js
browser/components/newtab/test/browser/browser_asrouter_trigger_listeners.js
browser/components/newtab/test/unit/asrouter/ASRouter.test.js
browser/components/newtab/test/unit/asrouter/CFRMessageProvider.test.js
browser/components/newtab/test/unit/asrouter/constants.js
--- a/browser/components/newtab/test/browser/browser_asrouter_cfr.js
+++ b/browser/components/newtab/test/browser/browser_asrouter_cfr.js
@@ -8,26 +8,32 @@ const { ASRouter } = ChromeUtils.import(
   "resource://activity-stream/lib/ASRouter.jsm"
 );
 
 const createDummyRecommendation = ({
   action,
   category,
   heading_text,
   layout,
+  skip_address_bar_notifier,
 }) => ({
   content: {
     layout: layout || "addon_recommendation",
     category,
+    anchor_id: "page-action-buttons",
+    skip_address_bar_notifier,
     notification_text: "Mochitest",
     heading_text: heading_text || "Mochitest",
     info_icon: {
       label: { attributes: { tooltiptext: "Why am I seeing this" } },
       sumo_path: "extensionrecommendations",
     },
+    icon: "foo",
+    icon_dark_theme: "bar",
+    learn_more: "extensionrecommendations",
     addon: {
       id: "addon-id",
       title: "Addon name",
       icon: "foo",
       author: "Author name",
       amo_url: "https://example.com",
     },
     descriptionDetails: { steps: [] },
@@ -102,16 +108,29 @@ function checkCFRAddonsElements(notifica
     "Panel should have addon rating info"
   );
   Assert.ok(
     notification.querySelector("#cfr-notification-author"),
     "Panel should have author info"
   );
 }
 
+function checkCFRSocialTrackingProtection(notification) {
+  Assert.ok(notification.hidden === false, "Panel should be visible");
+  Assert.ok(
+    notification.getAttribute("data-notification-category") ===
+      "icon_and_message",
+    "Panel have corret data attribute"
+  );
+  Assert.ok(
+    notification.querySelector("#cfr-notification-footer-learn-more-link"),
+    "Panel should have learn more link"
+  );
+}
+
 function clearNotifications() {
   for (let notification of PopupNotifications._currentNotifications) {
     notification.remove();
   }
 
   // Clicking the primary action also removes the notification
   Assert.equal(
     PopupNotifications._currentNotifications.length,
@@ -123,28 +142,36 @@ function clearNotifications() {
 function trigger_cfr_panel(
   browser,
   trigger,
   {
     action = { type: "FOO" },
     heading_text,
     category = "cfrAddons",
     layout,
+    skip_address_bar_notifier = false,
+    use_single_secondary_button = false,
   } = {}
 ) {
   // a fake action type will result in the action being ignored
   const recommendation = createDummyRecommendation({
     action,
     category,
     heading_text,
     layout,
+    skip_address_bar_notifier,
   });
   if (category !== "cfrAddons") {
     delete recommendation.content.addon;
   }
+  if (use_single_secondary_button) {
+    recommendation.content.buttons.secondary = [
+      recommendation.content.buttons.secondary[0],
+    ];
+  }
 
   clearNotifications();
 
   return CFRPageActions.addRecommendation(
     browser,
     trigger,
     recommendation,
     // Use the real AS dispatch method to trigger real notifications
@@ -395,16 +422,59 @@ add_task(async function test_cfr_pin_tab
   // Clicking the primary action also removes the notification
   Assert.equal(
     PopupNotifications._currentNotifications.length,
     0,
     "Should have removed the notification"
   );
 });
 
+add_task(
+  async function test_cfr_social_tracking_protection_notification_show() {
+    // addRecommendation checks that scheme starts with http and host matches
+    let browser = gBrowser.selectedBrowser;
+    await BrowserTestUtils.loadURI(browser, "http://example.com/");
+    await BrowserTestUtils.browserLoaded(browser, false, "http://example.com/");
+
+    const showPanel = BrowserTestUtils.waitForEvent(
+      PopupNotifications.panel,
+      "popupshown"
+    );
+
+    const response = await trigger_cfr_panel(browser, "example.com", {
+      action: { type: "OPEN_PROTECTION_PANEL" },
+      category: "cfrFeatures",
+      layout: "icon_and_message",
+      skip_address_bar_notifier: true,
+      use_single_secondary_button: true,
+    });
+    Assert.ok(
+      response,
+      "Should return true if addRecommendation checks were successful"
+    );
+    await showPanel;
+
+    const notification = document.getElementById(
+      "contextual-feature-recommendation-notification"
+    );
+    checkCFRSocialTrackingProtection(notification);
+
+    // Check there is a primary button and click it. It will trigger the callback.
+    Assert.ok(notification.button);
+    let hidePanel = BrowserTestUtils.waitForEvent(
+      PopupNotifications.panel,
+      "popuphidden"
+    );
+    document
+      .getElementById("contextual-feature-recommendation-notification")
+      .button.click();
+    await hidePanel;
+  }
+);
+
 add_task(async function test_cfr_features_and_addon_show() {
   // addRecommendation checks that scheme starts with http and host matches
   let browser = gBrowser.selectedBrowser;
   await BrowserTestUtils.loadURI(browser, "http://example.com/");
   await BrowserTestUtils.browserLoaded(browser, false, "http://example.com/");
 
   // Trigger Feature CFR
   let response = await trigger_cfr_panel(browser, "example.com", {
--- a/browser/components/newtab/test/browser/browser_asrouter_trigger_listeners.js
+++ b/browser/components/newtab/test/browser/browser_asrouter_trigger_listeners.js
@@ -136,8 +136,102 @@ add_task(async function check_newSavedLo
     TEST_URL,
     async function triggerNewSavedPasswordAfterUninit(browser) {
       Services.obs.notifyObservers(browser, "LoginStats:NewSavedPassword");
       await new Promise(resolve => executeSoon(resolve));
       is(loginsSaved, 1, "shouldn't receive obs. notification after uninit");
     }
   );
 });
+
+add_task(async function check_trackingProtection_listener() {
+  const TEST_URL =
+    "https://example.com/browser/browser/components/newtab/test/browser/red_page.html";
+
+  const contentBlockingEvent = 1234;
+  let observerEvent = 0;
+  let pageLoadSum = 0;
+  const triggerHandler = (target, trigger) => {
+    const {
+      id,
+      param: { host },
+      context: { pageLoad },
+    } = trigger;
+    is(id, "trackingProtection", "should match event name");
+    is(host, TEST_URL, "should match test URL");
+
+    observerEvent += 1;
+    pageLoadSum += pageLoad;
+  };
+  const trackingProtectionListener = ASRouterTriggerListeners.get(
+    "trackingProtection"
+  );
+
+  // Previously initialized by the Router
+  trackingProtectionListener.uninit();
+
+  // Initialise listener
+  await trackingProtectionListener.init(triggerHandler, [contentBlockingEvent]);
+
+  await BrowserTestUtils.withNewTab(
+    TEST_URL,
+    async function triggerTrackingProtection(browser) {
+      Services.obs.notifyObservers(
+        {
+          wrappedJSObject: {
+            browser,
+            host: TEST_URL,
+            event: contentBlockingEvent + 1,
+          },
+        },
+        "SiteProtection:ContentBlockingEvent"
+      );
+    }
+  );
+
+  is(observerEvent, 0, "shouldn't receive unrelated observer notification");
+  is(pageLoadSum, 0, "shouldn't receive unrelated observer notification");
+
+  await BrowserTestUtils.withNewTab(
+    TEST_URL,
+    async function triggerTrackingProtection(browser) {
+      Services.obs.notifyObservers(
+        {
+          wrappedJSObject: {
+            browser,
+            host: TEST_URL,
+            event: contentBlockingEvent,
+          },
+        },
+        "SiteProtection:ContentBlockingEvent"
+      );
+
+      await BrowserTestUtils.waitForCondition(
+        () => observerEvent !== 0,
+        "Wait for the observer notification to run"
+      );
+      is(observerEvent, 1, "should receive observer notification");
+      is(pageLoadSum, 2, "should receive observer notification");
+    }
+  );
+
+  // Uninitialise listener
+  trackingProtectionListener.uninit();
+
+  await BrowserTestUtils.withNewTab(
+    TEST_URL,
+    async function triggerTrackingProtectionAfterUninit(browser) {
+      Services.obs.notifyObservers(
+        {
+          wrappedJSObject: {
+            browser,
+            host: TEST_URL,
+            event: contentBlockingEvent,
+          },
+        },
+        "SiteProtection:ContentBlockingEvent"
+      );
+      await new Promise(resolve => executeSoon(resolve));
+      is(observerEvent, 1, "shouldn't receive obs. notification after uninit");
+      is(pageLoadSum, 2, "shouldn't receive obs. notification after uninit");
+    }
+  );
+});
--- a/browser/components/newtab/test/unit/asrouter/ASRouter.test.js
+++ b/browser/components/newtab/test/unit/asrouter/ASRouter.test.js
@@ -1966,16 +1966,28 @@ describe("ASRouter", () => {
           ConfirmationHint.show,
           gBrowser.selectedTab,
           "pinTab",
           { showDescription: true }
         );
       });
     });
 
+    describe("#onMessage: OPEN_PROTECTION_PANEL", () => {
+      it("should open protection panel", async () => {
+        const msg = fakeExecuteUserAction({ type: "OPEN_PROTECTION_PANEL" });
+        let { gProtectionsHandler } = msg.target.browser.ownerGlobal;
+
+        await Router.onMessage(msg);
+
+        assert.calledOnce(gProtectionsHandler.showProtectionsPopup);
+        assert.calledWithExactly(gProtectionsHandler.showProtectionsPopup, {});
+      });
+    });
+
     describe("#dispatch(action, target)", () => {
       it("should an action and target to onMessage", async () => {
         // use the IMPRESSION action to make sure actions are actually getting processed
         sandbox.stub(Router, "addImpression");
         sandbox.spy(Router, "onMessage");
         const target = {};
         const action = { type: "IMPRESSION" };
 
--- a/browser/components/newtab/test/unit/asrouter/CFRMessageProvider.test.js
+++ b/browser/components/newtab/test/unit/asrouter/CFRMessageProvider.test.js
@@ -6,18 +6,18 @@ const REGULAR_IDS = [
   "GOOGLE_TRANSLATE",
   "YOUTUBE_ENHANCE",
   // These are excluded for now.
   // "WIKIPEDIA_CONTEXT_MENU_SEARCH",
   // "REDDIT_ENHANCEMENT",
 ];
 
 describe("CFRMessageProvider", () => {
-  it("should have a total of 5 messages", () => {
-    assert.lengthOf(messages, 5);
+  it("should have a total of 8 messages", () => {
+    assert.lengthOf(messages, 8);
   });
   it("should have one message each for the three regular addons", () => {
     for (const id of REGULAR_IDS) {
       const cohort3 = messages.find(msg => msg.id === `${id}_3`);
       assert.ok(cohort3, `contains three day cohort for ${id}`);
       assert.deepEqual(
         cohort3.frequency,
         { lifetime: 3 },
--- a/browser/components/newtab/test/unit/asrouter/constants.js
+++ b/browser/components/newtab/test/unit/asrouter/constants.js
@@ -144,13 +144,16 @@ export class FakeRemotePageManager {
         openPreferences: sinon.stub(),
         gBrowser: {
           pinTab: sinon.stub(),
           selectedTab: {},
         },
         ConfirmationHint: {
           show: sinon.stub(),
         },
+        gProtectionsHandler: {
+          showProtectionsPopup: sinon.stub(),
+        },
       },
     };
     this.portID = "6000:2";
   }
 }