tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_signed_out_avatar_variants.js (7122B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   https://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { NimbusTestUtils } = ChromeUtils.importESModule(
      7  "resource://testing-common/NimbusTestUtils.sys.mjs"
      8 );
      9 
     10 const { ToolbarBadgeHub } = ChromeUtils.importESModule(
     11  "resource:///modules/asrouter/ToolbarBadgeHub.sys.mjs"
     12 );
     13 
     14 const DEFAULT_ICON = "avatar-empty.svg";
     15 const HUMAN_CIRCLE_BADGED = "avatar-empty.svg";
     16 const HUMAN_CIRCLE = "avatar-empty-circle.svg";
     17 const FOX_CIRCLE_BADGED = "avatar-fox.svg";
     18 const FOX_CIRCLE = "avatar-fox-circle.svg";
     19 
     20 // No matter which branch we're in, we expect this icon to be used for the
     21 // signed-in state by default.
     22 const SIGNED_IN_ICON = "avatar.svg";
     23 
     24 /**
     25 * Checks that the current icon for the FxA avatar menu button matches
     26 * iconFilename.
     27 *
     28 * @param {DOMWindow} win
     29 *   The browser window to test the icon for.
     30 * @param {string} iconFilename
     31 *   The expected iconFilename. This is not the full path to the image.
     32 *   Example: "avatar-empty.svg".
     33 * @param {string} message
     34 *   The assertion message to display.
     35 */
     36 function assertCurrentIcon(win, iconFilename, message) {
     37  let image = win.document.querySelector("#fxa-avatar-image");
     38  let avatarURL = win.getComputedStyle(image).listStyleImage;
     39  let expectedURL = `url("chrome://browser/skin/fxa/${iconFilename}")`;
     40  Assert.equal(avatarURL, expectedURL, message);
     41 }
     42 
     43 /**
     44 * Asserts that we're in the signed-out state, and that the signed-out icon
     45 * in win matches our iconFilename.
     46 *
     47 * @param {DOMWindow} win
     48 *   The browser window to test the icon for.
     49 * @param {string} iconFilename
     50 *   The expected iconFilename. This is not the full path to the image.
     51 *   Example: "avatar-empty.svg".
     52 */
     53 function assertSignedOutIcon(win, iconFilename) {
     54  Assert.equal(
     55    UIState.get().status,
     56    UIState.STATUS_NOT_CONFIGURED,
     57    "Currently signed out."
     58  );
     59  assertCurrentIcon(
     60    win,
     61    iconFilename,
     62    `Signed-out avatar image is ${iconFilename}`
     63  );
     64 }
     65 
     66 /**
     67 * Fakes out a signed-in state and then asserts that the signed-in icon
     68 * is the generic signed-in icon that we always use. Then we revert the
     69 * faked signed-in state.
     70 *
     71 * @param {DOMWindow} win
     72 *   The browser window to test the icon for.
     73 */
     74 function assertSignedInIcon(win) {
     75  const oldUIState = UIState.get;
     76 
     77  UIState.get = () => ({
     78    status: UIState.STATUS_SIGNED_IN,
     79    lastSync: new Date(),
     80    email: "foo@bar.com",
     81  });
     82  Services.obs.notifyObservers(null, UIState.ON_UPDATE);
     83 
     84  assertCurrentIcon(
     85    win,
     86    SIGNED_IN_ICON,
     87    `Signed-in avatar image is ${SIGNED_IN_ICON}`
     88  );
     89 
     90  UIState.get = oldUIState;
     91  Services.obs.notifyObservers(null, UIState.ON_UPDATE);
     92 }
     93 
     94 /**
     95 * Asserts that we're in the signed-out state, and that when badged, we're
     96 * showing the iconFilename icon in the window. This reverts any badging state
     97 * on the window before returning.
     98 *
     99 * @param {DOMWindow} win
    100 *   The browser window to test the icon for.
    101 * @param {string} iconFilename
    102 *   The expected iconFilename. This is not the full path to the image.
    103 *   Example: "avatar-empty.svg".
    104 */
    105 function assertBadgedIcon(win, iconFilename) {
    106  Assert.equal(
    107    UIState.get().status,
    108    UIState.STATUS_NOT_CONFIGURED,
    109    "Currently signed out."
    110  );
    111 
    112  let button = win.document.querySelector("#fxa-toolbar-menu-button");
    113  let badge = button.querySelector(".toolbarbutton-badge");
    114  badge.classList.add("feature-callout");
    115  button.setAttribute("badged", true);
    116  button.toggleAttribute("showing-callout", true);
    117 
    118  assertCurrentIcon(
    119    win,
    120    iconFilename,
    121    `Badged avatar image is ${iconFilename}`
    122  );
    123 
    124  badge.classList.remove("feature-callout");
    125  button.removeAttribute("badged");
    126  button.toggleAttribute("showing-callout", false);
    127 }
    128 
    129 /**
    130 * Opens up a new browser window, makes sure its FxA state is initialized, and
    131 * then runs taskFn (passing it the opened window). When taskFn resolves, the
    132 * window is closed and an (optional) cleanup function is run.
    133 *
    134 * @param {Function|null} doCleanup
    135 *   An optional async cleanup function to call once the browser window has
    136 *   closed.
    137 * @param {Function} taskFn
    138 *   An async function to run once the browser window has opened and its FxA
    139 *   state has initialized. This is passed the opened window as its only
    140 *   argument.
    141 * @returns {Promise<undefined>}
    142 */
    143 async function testInNewWindow(doCleanup, taskFn) {
    144  let win = await BrowserTestUtils.openNewBrowserWindow();
    145  win.gSync.init();
    146 
    147  await taskFn(win);
    148  await BrowserTestUtils.closeWindow(win);
    149  if (doCleanup) {
    150    await doCleanup();
    151  }
    152 }
    153 
    154 /**
    155 * Tests that we can change the signed-out icon for the FxA avatar menu via
    156 * Experimenter. Also ensures that the signed-in icon is not affected by these
    157 * signed-out variants.
    158 */
    159 
    160 add_setup(async () => {
    161  UIState.get = () => ({
    162    status: UIState.STATUS_NOT_CONFIGURED,
    163  });
    164  Services.obs.notifyObservers(null, UIState.ON_UPDATE);
    165  gSync.init();
    166 });
    167 
    168 /**
    169 * Tests that we use the default icon when not enrolled in the experiment.
    170 */
    171 add_task(async function test_default() {
    172  Assert.equal(
    173    NimbusFeatures.fxaButtonVisibility.getVariable("avatarIconVariant"),
    174    undefined,
    175    "Should not start with a NimbusFeature set for the signed-out icon."
    176  );
    177 
    178  await testInNewWindow(null /* no cleanup */, async win => {
    179    assertSignedOutIcon(win, DEFAULT_ICON);
    180    assertSignedInIcon(win);
    181  });
    182 });
    183 
    184 /**
    185 * Tests that we use the default icon when enrolled in the control branch.
    186 */
    187 add_task(async function test_control() {
    188  let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig(
    189    {
    190      featureId: NimbusFeatures.fxaButtonVisibility.featureId,
    191      value: {
    192        avatarIconVariant: "control",
    193      },
    194    },
    195    { isRollout: true }
    196  );
    197 
    198  await testInNewWindow(doCleanup, async win => {
    199    assertSignedOutIcon(win, DEFAULT_ICON);
    200    assertSignedInIcon(win);
    201  });
    202 });
    203 
    204 /**
    205 * Tests that we use the human-circle icon when enrolled in the human-circle
    206 * branch, and that we hide the circle when in the badged state.
    207 */
    208 add_task(async function test_human_circle() {
    209  let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig(
    210    {
    211      featureId: NimbusFeatures.fxaButtonVisibility.featureId,
    212      value: {
    213        avatarIconVariant: "human-circle",
    214      },
    215    },
    216    { isRollout: true }
    217  );
    218 
    219  await testInNewWindow(doCleanup, async win => {
    220    assertSignedOutIcon(win, HUMAN_CIRCLE);
    221    assertBadgedIcon(win, HUMAN_CIRCLE_BADGED);
    222    assertSignedInIcon(win);
    223  });
    224 });
    225 
    226 /**
    227 * Tests that we use the fox-circle icon when enrolled in the fox-circle
    228 * branch, and that we hide the circle when in the badged state.
    229 */
    230 add_task(async function test_fox_circle() {
    231  let doCleanup = await NimbusTestUtils.enrollWithFeatureConfig(
    232    {
    233      featureId: NimbusFeatures.fxaButtonVisibility.featureId,
    234      value: {
    235        avatarIconVariant: "fox-circle",
    236      },
    237    },
    238    { isRollout: true }
    239  );
    240 
    241  await testInNewWindow(doCleanup, async win => {
    242    assertSignedOutIcon(win, FOX_CIRCLE);
    243    assertBadgedIcon(win, FOX_CIRCLE_BADGED);
    244    assertSignedInIcon(win);
    245  });
    246 });