tor-browser

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

test_ASRouterTelemetry.js (20017B)


      1 /* Any copyright is dedicated to the Public Domain.
      2  http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { MESSAGE_TYPE_HASH: msg } = ChromeUtils.importESModule(
      7  "resource:///modules/asrouter/ActorConstants.mjs"
      8 );
      9 
     10 const { ASRouterTelemetry } = ChromeUtils.importESModule(
     11  "resource:///modules/asrouter/ASRouterTelemetry.sys.mjs"
     12 );
     13 
     14 ChromeUtils.defineESModuleGetters(this, {
     15  AboutWelcomeTelemetry:
     16    "resource:///modules/aboutwelcome/AboutWelcomeTelemetry.sys.mjs",
     17  NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
     18  JsonSchemaValidator:
     19    "resource://gre/modules/components-utils/JsonSchemaValidator.sys.mjs",
     20  TelemetryController: "resource://gre/modules/TelemetryController.sys.mjs",
     21  UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
     22 });
     23 
     24 const FAKE_UUID = "{foo-123-foo}";
     25 const PREF_TELEMETRY = "browser.newtabpage.activity-stream.telemetry";
     26 
     27 let ASRouterEventPingSchemaPromise;
     28 
     29 function assertPingMatchesSchema(pingKind, ping, schema) {
     30  // Unlike the validator from JsonSchema.sys.mjs, JsonSchemaValidator
     31  // lets us opt-in to having "undefined" properties, which are then
     32  // ignored. This is fine because the ping is sent as a JSON string
     33  // over an XHR, and undefined properties are culled as part of the
     34  // JSON encoding process.
     35  let result = JsonSchemaValidator.validate(ping, schema, {
     36    allowExplicitUndefinedProperties: true,
     37  });
     38 
     39  if (!result.valid) {
     40    info(`${pingKind} failed to validate against the schema: ${result.error}`);
     41  }
     42 
     43  Assert.ok(result.valid, `${pingKind} is valid against the schema.`);
     44 }
     45 
     46 async function assertASRouterEventPingValid(ping) {
     47  let schema = await ASRouterEventPingSchemaPromise;
     48  assertPingMatchesSchema("ASRouterEventPing", ping, schema);
     49 }
     50 
     51 add_setup(async function setup() {
     52  ASRouterEventPingSchemaPromise = IOUtils.readJSON(
     53    do_get_file("../schemas/asrouter_event_ping.schema.json").path
     54  );
     55 
     56  do_get_profile();
     57 
     58  await TelemetryController.testReset();
     59 });
     60 
     61 add_task(async function test_applyCFRPolicy_prerelease() {
     62  info(
     63    "ASRouterTelemetry.applyCFRPolicy should use client_id and message_id " +
     64      "in prerelease"
     65  );
     66  let sandbox = sinon.createSandbox();
     67  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("nightly");
     68 
     69  let instance = new ASRouterTelemetry();
     70 
     71  let data = {
     72    action: "cfr_user_event",
     73    event: "IMPRESSION",
     74    message_id: "cfr_message_01",
     75    bucket_id: "cfr_bucket_01",
     76  };
     77  let { ping, pingType } = await instance.applyCFRPolicy(data);
     78 
     79  Assert.equal(pingType, "cfr");
     80  Assert.equal(ping.impression_id, undefined);
     81  Assert.equal(
     82    ping.client_id,
     83    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
     84  );
     85  Assert.equal(ping.bucket_id, "cfr_bucket_01");
     86  Assert.equal(ping.message_id, "cfr_message_01");
     87 
     88  sandbox.restore();
     89 });
     90 
     91 add_task(async function test_applyCFRPolicy_release() {
     92  info(
     93    "ASRouterTelemetry.applyCFRPolicy should use impression_id and bucket_id " +
     94      "in release"
     95  );
     96  let sandbox = sinon.createSandbox();
     97  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
     98  sandbox
     99    .stub(ASRouterTelemetry.prototype, "getOrCreateImpressionId")
    100    .returns(FAKE_UUID);
    101 
    102  let instance = new ASRouterTelemetry();
    103 
    104  let data = {
    105    action: "cfr_user_event",
    106    event: "IMPRESSION",
    107    message_id: "cfr_message_01",
    108    bucket_id: "cfr_bucket_01",
    109  };
    110  let { ping, pingType } = await instance.applyCFRPolicy(data);
    111 
    112  Assert.equal(pingType, "cfr");
    113  Assert.equal(ping.impression_id, FAKE_UUID);
    114  Assert.equal(ping.client_id, undefined);
    115  Assert.equal(ping.bucket_id, "cfr_bucket_01");
    116  Assert.equal(ping.message_id, "n/a");
    117 
    118  sandbox.restore();
    119 });
    120 
    121 add_task(async function test_applyCFRPolicy_experiment_release() {
    122  info(
    123    "ASRouterTelemetry.applyCFRPolicy should use impression_id and bucket_id " +
    124      "in release"
    125  );
    126  let sandbox = sinon.createSandbox();
    127  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
    128  sandbox.stub(NimbusFeatures.cfr, "getEnrollmentMetadata").returns({
    129    slug: "SOME-CFR-EXP",
    130    branch: "branch-slug",
    131    isRollout: false,
    132  });
    133 
    134  let instance = new ASRouterTelemetry();
    135 
    136  let data = {
    137    action: "cfr_user_event",
    138    event: "IMPRESSION",
    139    message_id: "cfr_message_01",
    140    bucket_id: "cfr_bucket_01",
    141  };
    142  let { ping, pingType } = await instance.applyCFRPolicy(data);
    143 
    144  Assert.equal(pingType, "cfr");
    145  Assert.equal(ping.impression_id, undefined);
    146  Assert.equal(
    147    ping.client_id,
    148    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    149  );
    150  Assert.equal(ping.bucket_id, "cfr_bucket_01");
    151  Assert.equal(ping.message_id, "cfr_message_01");
    152 
    153  sandbox.restore();
    154 });
    155 
    156 add_task(async function test_applyCFRPolicy_release_private_browsing() {
    157  info(
    158    "ASRouterTelemetry.applyCFRPolicy should use impression_id and bucket_id " +
    159      "in Private Browsing in release"
    160  );
    161  let sandbox = sinon.createSandbox();
    162  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
    163  sandbox
    164    .stub(ASRouterTelemetry.prototype, "getOrCreateImpressionId")
    165    .returns(FAKE_UUID);
    166 
    167  let instance = new ASRouterTelemetry();
    168 
    169  let data = {
    170    action: "cfr_user_event",
    171    event: "IMPRESSION",
    172    is_private: true,
    173    message_id: "cfr_message_01",
    174    bucket_id: "cfr_bucket_01",
    175  };
    176  let { ping, pingType } = await instance.applyCFRPolicy(data);
    177 
    178  Assert.equal(pingType, "cfr");
    179  Assert.equal(ping.impression_id, FAKE_UUID);
    180  Assert.equal(ping.client_id, undefined);
    181  Assert.equal(ping.bucket_id, "cfr_bucket_01");
    182  Assert.equal(ping.message_id, "n/a");
    183 
    184  sandbox.restore();
    185 });
    186 
    187 add_task(
    188  async function test_applyCFRPolicy_release_experiment_private_browsing() {
    189    info(
    190      "ASRouterTelemetry.applyCFRPolicy should use client_id and message_id in the " +
    191        "experiment cohort in Private Browsing in release"
    192    );
    193    let sandbox = sinon.createSandbox();
    194    sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
    195    sandbox.stub(NimbusFeatures.cfr, "getEnrollmentMetadata").returns({
    196      slug: "SOME-CFR-EXP",
    197      branch: "branch-slug",
    198      isRollout: false,
    199    });
    200 
    201    let instance = new ASRouterTelemetry();
    202 
    203    let data = {
    204      action: "cfr_user_event",
    205      event: "IMPRESSION",
    206      is_private: true,
    207      message_id: "cfr_message_01",
    208      bucket_id: "cfr_bucket_01",
    209    };
    210    let { ping, pingType } = await instance.applyCFRPolicy(data);
    211 
    212    Assert.equal(pingType, "cfr");
    213    Assert.equal(ping.impression_id, undefined);
    214    Assert.equal(
    215      ping.client_id,
    216      Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    217    );
    218    Assert.equal(ping.bucket_id, "cfr_bucket_01");
    219    Assert.equal(ping.message_id, "cfr_message_01");
    220 
    221    sandbox.restore();
    222  }
    223 );
    224 
    225 add_task(async function test_applyToolbarBadgePolicy() {
    226  info(
    227    "ASRouterTelemetry.applyToolbarBadgePolicy should set client_id and set pingType"
    228  );
    229  let instance = new ASRouterTelemetry();
    230  let { ping, pingType } = await instance.applyToolbarBadgePolicy({});
    231 
    232  Assert.equal(
    233    ping.client_id,
    234    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    235  );
    236  Assert.equal(pingType, "toolbar-badge");
    237 });
    238 
    239 add_task(async function test_applyInfoBarPolicy() {
    240  info(
    241    "ASRouterTelemetry.applyInfoBarPolicy should set client_id and set pingType"
    242  );
    243  let instance = new ASRouterTelemetry();
    244  let { ping, pingType } = await instance.applyInfoBarPolicy({});
    245 
    246  Assert.equal(
    247    ping.client_id,
    248    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    249  );
    250  Assert.equal(pingType, "infobar");
    251 });
    252 
    253 add_task(async function test_applyToastNotificationPolicy() {
    254  info(
    255    "ASRouterTelemetry.applyToastNotificationPolicy should set client_id " +
    256      "and set pingType"
    257  );
    258  let instance = new ASRouterTelemetry();
    259  let { ping, pingType } = await instance.applyToastNotificationPolicy({});
    260 
    261  Assert.equal(
    262    ping.client_id,
    263    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    264  );
    265  Assert.equal(pingType, "toast_notification");
    266 });
    267 
    268 add_task(async function test_applySpotlightPolicy() {
    269  info(
    270    "ASRouterTelemetry.applySpotlightPolicy should set client_id " +
    271      "and set pingType"
    272  );
    273  let instance = new ASRouterTelemetry();
    274  let { ping, pingType } = await instance.applySpotlightPolicy({
    275    action: "foo",
    276  });
    277 
    278  Assert.equal(
    279    ping.client_id,
    280    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    281  );
    282  Assert.equal(pingType, "spotlight");
    283  Assert.equal(ping.action, undefined);
    284 });
    285 
    286 add_task(async function test_applyMomentsPolicy_prerelease() {
    287  info(
    288    "ASRouterTelemetry.applyMomentsPolicy should use client_id and " +
    289      "message_id in prerelease"
    290  );
    291  let sandbox = sinon.createSandbox();
    292  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("nightly");
    293 
    294  let instance = new ASRouterTelemetry();
    295  let data = {
    296    action: "moments_user_event",
    297    event: "IMPRESSION",
    298    message_id: "moments_message_01",
    299    bucket_id: "moments_bucket_01",
    300  };
    301  let { ping, pingType } = await instance.applyMomentsPolicy(data);
    302 
    303  Assert.equal(pingType, "moments");
    304  Assert.equal(ping.impression_id, undefined);
    305  Assert.equal(
    306    ping.client_id,
    307    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    308  );
    309  Assert.equal(ping.bucket_id, "moments_bucket_01");
    310  Assert.equal(ping.message_id, "moments_message_01");
    311 
    312  sandbox.restore();
    313 });
    314 
    315 add_task(async function test_applyMomentsPolicy_release() {
    316  info(
    317    "ASRouterTelemetry.applyMomentsPolicy should use impression_id and " +
    318      "bucket_id in release"
    319  );
    320  let sandbox = sinon.createSandbox();
    321  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
    322  sandbox
    323    .stub(ASRouterTelemetry.prototype, "getOrCreateImpressionId")
    324    .returns(FAKE_UUID);
    325 
    326  let instance = new ASRouterTelemetry();
    327  let data = {
    328    action: "moments_user_event",
    329    event: "IMPRESSION",
    330    message_id: "moments_message_01",
    331    bucket_id: "moments_bucket_01",
    332  };
    333  let { ping, pingType } = await instance.applyMomentsPolicy(data);
    334 
    335  Assert.equal(pingType, "moments");
    336  Assert.equal(ping.impression_id, FAKE_UUID);
    337  Assert.equal(ping.client_id, undefined);
    338  Assert.equal(ping.bucket_id, "moments_bucket_01");
    339  Assert.equal(ping.message_id, "n/a");
    340 
    341  sandbox.restore();
    342 });
    343 
    344 add_task(async function test_applyMomentsPolicy_experiment_release() {
    345  info(
    346    "ASRouterTelemetry.applyMomentsPolicy client_id and message_id in " +
    347      "the experiment cohort in release"
    348  );
    349  let sandbox = sinon.createSandbox();
    350  sandbox.stub(UpdateUtils, "getUpdateChannel").returns("release");
    351  sandbox.stub(NimbusFeatures.cfr, "getEnrollmentMetadata").returns({
    352    slug: "SOME-CFR-EXP",
    353    branch: "branch-slug",
    354    isRollout: false,
    355  });
    356 
    357  let instance = new ASRouterTelemetry();
    358  let data = {
    359    action: "moments_user_event",
    360    event: "IMPRESSION",
    361    message_id: "moments_message_01",
    362    bucket_id: "moments_bucket_01",
    363  };
    364  let { ping, pingType } = await instance.applyMomentsPolicy(data);
    365 
    366  Assert.equal(pingType, "moments");
    367  Assert.equal(ping.impression_id, undefined);
    368  Assert.equal(
    369    ping.client_id,
    370    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    371  );
    372  Assert.equal(ping.bucket_id, "moments_bucket_01");
    373  Assert.equal(ping.message_id, "moments_message_01");
    374 
    375  sandbox.restore();
    376 });
    377 
    378 add_task(async function test_applyMenuMessagePolicy() {
    379  info(
    380    "ASRouterTelemetry.applyMenuMessagePolicy should set client_id and set pingType"
    381  );
    382  let instance = new ASRouterTelemetry();
    383  let { ping, pingType } = await instance.applyMenuMessagePolicy({});
    384 
    385  Assert.equal(
    386    ping.client_id,
    387    Services.prefs.getCharPref("toolkit.telemetry.cachedClientID")
    388  );
    389  Assert.equal(pingType, "menu");
    390 });
    391 
    392 add_task(async function test_applyUndesiredEventPolicy() {
    393  info(
    394    "ASRouterTelemetry.applyUndesiredEventPolicy should exclude client_id " +
    395      "and use impression_id"
    396  );
    397  let sandbox = sinon.createSandbox();
    398  sandbox
    399    .stub(ASRouterTelemetry.prototype, "getOrCreateImpressionId")
    400    .returns(FAKE_UUID);
    401 
    402  let instance = new ASRouterTelemetry();
    403  let data = {
    404    action: "asrouter_undesired_event",
    405    event: "RS_MISSING_DATA",
    406  };
    407  let { ping, pingType } = await instance.applyUndesiredEventPolicy(data);
    408 
    409  Assert.equal(pingType, "undesired-events");
    410  Assert.equal(ping.client_id, undefined);
    411  Assert.equal(ping.impression_id, FAKE_UUID);
    412 
    413  sandbox.restore();
    414 });
    415 
    416 add_task(async function test_createASRouterEvent_valid_ping() {
    417  info(
    418    "ASRouterTelemetry.createASRouterEvent should create a valid " +
    419      "ASRouterEventPing ping"
    420  );
    421  let instance = new ASRouterTelemetry();
    422  let action = {
    423    type: msg.AS_ROUTER_TELEMETRY_USER_EVENT,
    424    data: {
    425      action: "cfr_user_event",
    426      event: "CLICK",
    427      message_id: "cfr_message_01",
    428    },
    429  };
    430  let { ping } = await instance.createASRouterEvent(action);
    431 
    432  await assertASRouterEventPingValid(ping);
    433  Assert.equal(ping.event, "CLICK");
    434 });
    435 
    436 add_task(async function test_createASRouterEvent_call_correctPolicy() {
    437  let testCallCorrectPolicy = async (expectedPolicyFnName, data) => {
    438    info(
    439      `ASRouterTelemetry.createASRouterEvent should call ${expectedPolicyFnName} ` +
    440        `on action ${data.action} and event ${data.event}`
    441    );
    442    let sandbox = sinon.createSandbox();
    443    let instance = new ASRouterTelemetry();
    444    sandbox.stub(instance, expectedPolicyFnName);
    445 
    446    let action = { type: msg.AS_ROUTER_TELEMETRY_USER_EVENT, data };
    447    await instance.createASRouterEvent(action);
    448    Assert.ok(
    449      instance[expectedPolicyFnName].calledOnce,
    450      `ASRouterTelemetry.${expectedPolicyFnName} called`
    451    );
    452 
    453    sandbox.restore();
    454  };
    455 
    456  testCallCorrectPolicy("applyCFRPolicy", {
    457    action: "cfr_user_event",
    458    event: "IMPRESSION",
    459    message_id: "cfr_message_01",
    460  });
    461 
    462  testCallCorrectPolicy("applyToolbarBadgePolicy", {
    463    action: "badge_user_event",
    464    event: "IMPRESSION",
    465    message_id: "badge_message_01",
    466  });
    467 
    468  testCallCorrectPolicy("applyMomentsPolicy", {
    469    action: "moments_user_event",
    470    event: "CLICK_BUTTON",
    471    message_id: "moments_message_01",
    472  });
    473 
    474  testCallCorrectPolicy("applySpotlightPolicy", {
    475    action: "spotlight_user_event",
    476    event: "CLICK",
    477    message_id: "SPOTLIGHT_MESSAGE_93",
    478  });
    479 
    480  testCallCorrectPolicy("applyToastNotificationPolicy", {
    481    action: "toast_notification_user_event",
    482    event: "IMPRESSION",
    483    message_id: "TEST_TOAST_NOTIFICATION1",
    484  });
    485 
    486  testCallCorrectPolicy("applyUndesiredEventPolicy", {
    487    action: "asrouter_undesired_event",
    488    event: "UNDESIRED_EVENT",
    489  });
    490 });
    491 
    492 add_task(async function test_createASRouterEvent_stringify_event_context() {
    493  info(
    494    "ASRouterTelemetry.createASRouterEvent should stringify event_context if " +
    495      "it is an Object"
    496  );
    497  let instance = new ASRouterTelemetry();
    498  let action = {
    499    type: msg.AS_ROUTER_TELEMETRY_USER_EVENT,
    500    data: {
    501      action: "asrouter_undesired_event",
    502      event: "UNDESIRED_EVENT",
    503      event_context: { foo: "bar" },
    504    },
    505  };
    506  let { ping } = await instance.createASRouterEvent(action);
    507 
    508  Assert.equal(ping.event_context, JSON.stringify({ foo: "bar" }));
    509 });
    510 
    511 add_task(async function test_createASRouterEvent_not_stringify_event_context() {
    512  info(
    513    "ASRouterTelemetry.createASRouterEvent should not stringify event_context " +
    514      "if it is a String"
    515  );
    516  let instance = new ASRouterTelemetry();
    517  let action = {
    518    type: msg.AS_ROUTER_TELEMETRY_USER_EVENT,
    519    data: {
    520      action: "asrouter_undesired_event",
    521      event: "UNDESIRED_EVENT",
    522      event_context: "foo",
    523    },
    524  };
    525  let { ping } = await instance.createASRouterEvent(action);
    526 
    527  Assert.equal(ping.event_context, "foo");
    528 });
    529 
    530 add_task(async function test_onAction_calls_handleASRouterUserEvent() {
    531  let actions = [
    532    msg.AS_ROUTER_TELEMETRY_USER_EVENT,
    533    msg.TOOLBAR_BADGE_TELEMETRY,
    534    msg.TOOLBAR_PANEL_TELEMETRY,
    535    msg.MOMENTS_PAGE_TELEMETRY,
    536    msg.DOORHANGER_TELEMETRY,
    537  ];
    538 
    539  Services.prefs.setBoolPref(PREF_TELEMETRY, true);
    540  actions.forEach(type => {
    541    info(`Testing ${type} action`);
    542    let sandbox = sinon.createSandbox();
    543    let instance = new ASRouterTelemetry();
    544 
    545    const eventHandler = sandbox.spy(instance, "handleASRouterUserEvent");
    546    const action = {
    547      type,
    548      data: { event: "CLICK" },
    549    };
    550 
    551    instance.onAction(action);
    552 
    553    Assert.ok(eventHandler.calledWith(action));
    554    sandbox.restore();
    555  });
    556 
    557  Services.prefs.clearUserPref(PREF_TELEMETRY);
    558 });
    559 
    560 add_task(
    561  async function test_SendASRouterUndesiredEvent_calls_handleASRouterUserEvent() {
    562    info(
    563      "ASRouterTelemetry.SendASRouterUndesiredEvent should call " +
    564        "handleASRouterUserEvent"
    565    );
    566    let sandbox = sinon.createSandbox();
    567    let instance = new ASRouterTelemetry();
    568 
    569    sandbox.stub(instance, "handleASRouterUserEvent");
    570 
    571    instance.SendASRouterUndesiredEvent({ foo: "bar" });
    572 
    573    Assert.ok(
    574      instance.handleASRouterUserEvent.calledOnce,
    575      "ASRouterTelemetry.handleASRouterUserEvent was called once"
    576    );
    577    let [payload] = instance.handleASRouterUserEvent.firstCall.args;
    578    Assert.equal(payload.data.action, "asrouter_undesired_event");
    579    Assert.equal(payload.data.foo, "bar");
    580 
    581    sandbox.restore();
    582  }
    583 );
    584 
    585 add_task(
    586  async function test_handleASRouterUserEvent_calls_submitGleanPingForPing() {
    587    info(
    588      "ASRouterTelemetry.handleASRouterUserEvent should call " +
    589        "submitGleanPingForPing on known pingTypes when telemetry is enabled"
    590    );
    591 
    592    let data = {
    593      action: "spotlight_user_event",
    594      event: "IMPRESSION",
    595      message_id: "12345",
    596    };
    597    let sandbox = sinon.createSandbox();
    598    let instance = new ASRouterTelemetry();
    599    Services.fog.testResetFOG();
    600 
    601    Services.prefs.setBoolPref(PREF_TELEMETRY, true);
    602 
    603    sandbox.spy(AboutWelcomeTelemetry.prototype, "submitGleanPingForPing");
    604 
    605    await instance.handleASRouterUserEvent({ data });
    606 
    607    Assert.ok(
    608      AboutWelcomeTelemetry.prototype.submitGleanPingForPing.calledOnce,
    609      "AboutWelcomeTelemetry.submitGleanPingForPing called once"
    610    );
    611 
    612    Services.prefs.clearUserPref(PREF_TELEMETRY);
    613    sandbox.restore();
    614  }
    615 );
    616 
    617 add_task(
    618  async function test_handleASRouterUserEvent_no_submit_unknown_pingTypes() {
    619    info(
    620      "ASRouterTelemetry.handleASRouterUserEvent not submit pings on unknown pingTypes"
    621    );
    622 
    623    let data = {
    624      action: "unknown_event",
    625      event: "IMPRESSION",
    626      message_id: "12345",
    627    };
    628    let sandbox = sinon.createSandbox();
    629    let instance = new ASRouterTelemetry();
    630    Services.fog.testResetFOG();
    631 
    632    Services.prefs.setBoolPref(PREF_TELEMETRY, true);
    633 
    634    sandbox.spy(AboutWelcomeTelemetry.prototype, "submitGleanPingForPing");
    635 
    636    await instance.handleASRouterUserEvent({ data });
    637 
    638    Assert.ok(
    639      AboutWelcomeTelemetry.prototype.submitGleanPingForPing.notCalled,
    640      "AboutWelcomeTelemetry.submitGleanPingForPing not called"
    641    );
    642 
    643    Services.prefs.clearUserPref(PREF_TELEMETRY);
    644    sandbox.restore();
    645  }
    646 );
    647 
    648 add_task(
    649  async function test_isInCFRCohort_return_false_for_no_CFR_experiment() {
    650    info(
    651      "ASRouterTelemetry.isInCFRCohort should return false if there " +
    652        "is no CFR experiment registered"
    653    );
    654    let instance = new ASRouterTelemetry();
    655    Assert.ok(
    656      !instance.isInCFRCohort,
    657      "Should not be in CFR cohort by default"
    658    );
    659  }
    660 );
    661 
    662 add_task(
    663  async function test_isInCFRCohort_return_true_for_registered_CFR_experiment() {
    664    info(
    665      "ASRouterTelemetry.isInCFRCohort should return true if there " +
    666        "is a CFR experiment registered"
    667    );
    668    let sandbox = sinon.createSandbox();
    669    let instance = new ASRouterTelemetry();
    670 
    671    sandbox.stub(NimbusFeatures.cfr, "getEnrollmentMetadata").returns({
    672      slug: "SOME-CFR-EXP",
    673      branch: "branch-slug",
    674      isRollout: false,
    675    });
    676 
    677    Assert.ok(instance.isInCFRCohort, "Should be in a CFR cohort");
    678 
    679    sandbox.restore();
    680  }
    681 );