827 lines
20 KiB
JavaScript
827 lines
20 KiB
JavaScript
"use strict";
|
|
|
|
const { NimbusTelemetry } = ChromeUtils.importESModule(
|
|
"resource://nimbus/lib/Telemetry.sys.mjs"
|
|
);
|
|
const { TestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/TestUtils.sys.mjs"
|
|
);
|
|
const COLLECTION_ID_PREF = "messaging-system.rsexperimentloader.collection_id";
|
|
|
|
add_setup(function () {
|
|
Services.fog.initializeFOG();
|
|
});
|
|
|
|
/**
|
|
* #getRecipe
|
|
*/
|
|
add_task(async function test_getRecipe() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
const RECIPE = NimbusTestUtils.factories.recipe("foo");
|
|
const collectionName = Services.prefs.getStringPref(COLLECTION_ID_PREF);
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").resolves([RECIPE]);
|
|
|
|
const recipe = await ExperimentAPI.getRecipe("foo");
|
|
Assert.deepEqual(
|
|
recipe,
|
|
RECIPE,
|
|
"should return an experiment recipe if found"
|
|
);
|
|
Assert.equal(
|
|
ExperimentAPI._remoteSettingsClient.collectionName,
|
|
collectionName,
|
|
"Loaded the expected collection"
|
|
);
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function test_getRecipe_Failure() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").throws();
|
|
|
|
const recipe = await ExperimentAPI.getRecipe("foo");
|
|
Assert.equal(recipe, undefined, "should return undefined if RS throws");
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
/**
|
|
* #getAllBranches
|
|
*/
|
|
add_task(async function test_getAllBranches() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
const RECIPE = NimbusTestUtils.factories.recipe("foo");
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").resolves([RECIPE]);
|
|
|
|
const branches = await ExperimentAPI.getAllBranches("foo");
|
|
Assert.deepEqual(
|
|
branches,
|
|
RECIPE.branches,
|
|
"should return all branches if found a recipe"
|
|
);
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
// API used by Messaging System
|
|
add_task(async function test_getAllBranches_featureIdAccessor() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const RECIPE = NimbusTestUtils.factories.recipe("foo");
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").resolves([RECIPE]);
|
|
|
|
const branches = await ExperimentAPI.getAllBranches("foo");
|
|
Assert.deepEqual(
|
|
branches,
|
|
RECIPE.branches,
|
|
"should return all branches if found a recipe"
|
|
);
|
|
branches.forEach(branch => {
|
|
Assert.equal(
|
|
branch.testFeature.featureId,
|
|
"testFeature",
|
|
"Should use the experimentBranchAccessor proxy getter"
|
|
);
|
|
});
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
// For schema version before 1.6.2 branch.feature was accessed
|
|
// instead of branch.features
|
|
add_task(async function test_getAllBranches_backwardsCompat() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const RECIPE = NimbusTestUtils.factories.recipe("foo");
|
|
delete RECIPE.branches[0].features;
|
|
delete RECIPE.branches[1].features;
|
|
let feature = {
|
|
featureId: "backwardsCompat",
|
|
value: {
|
|
enabled: true,
|
|
},
|
|
};
|
|
RECIPE.branches[0].feature = feature;
|
|
RECIPE.branches[1].feature = feature;
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").resolves([RECIPE]);
|
|
|
|
const branches = await ExperimentAPI.getAllBranches("foo");
|
|
Assert.deepEqual(
|
|
branches,
|
|
RECIPE.branches,
|
|
"should return all branches if found a recipe"
|
|
);
|
|
branches.forEach(branch => {
|
|
Assert.equal(
|
|
branch.backwardsCompat.featureId,
|
|
"backwardsCompat",
|
|
"Should use the experimentBranchAccessor proxy getter"
|
|
);
|
|
});
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function test_getAllBranches_Failure() {
|
|
const { sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
sandbox.stub(ExperimentAPI._remoteSettingsClient, "get").throws();
|
|
|
|
const branches = await ExperimentAPI.getAllBranches("foo");
|
|
Assert.equal(branches, undefined, "should return undefined if RS throws");
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
/**
|
|
* Store events
|
|
*/
|
|
add_task(async function test_addEnrollment_eventEmit_add() {
|
|
const { sandbox, manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
const store = manager.store;
|
|
|
|
const featureStub = sandbox.stub();
|
|
const experiment = NimbusTestUtils.factories.experiment("foo", {
|
|
branch: {
|
|
slug: "variant",
|
|
ratio: 1,
|
|
features: [{ featureId: "purple", value: {} }],
|
|
},
|
|
});
|
|
|
|
await ExperimentAPI.ready();
|
|
|
|
store.on("featureUpdate:purple", featureStub);
|
|
|
|
store.addEnrollment(experiment);
|
|
|
|
Assert.equal(
|
|
featureStub.callCount,
|
|
1,
|
|
"should call 'featureUpdate' callback for featureId when an experiment is added"
|
|
);
|
|
Assert.equal(featureStub.firstCall.args[0], "featureUpdate:purple");
|
|
Assert.equal(featureStub.firstCall.args[1], "experiment-updated");
|
|
|
|
store.off("featureUpdate:purple", featureStub);
|
|
|
|
await manager.unenroll(experiment.slug);
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function test_updateExperiment_eventEmit_add_and_update() {
|
|
const { sandbox, manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
const store = manager.store;
|
|
|
|
const featureStub = sandbox.stub();
|
|
const experiment = NimbusTestUtils.factories.experiment("foo", {
|
|
branch: {
|
|
slug: "variant",
|
|
ratio: 1,
|
|
features: [{ featureId: "purple", value: {} }],
|
|
},
|
|
});
|
|
|
|
store.addEnrollment(experiment);
|
|
|
|
store._onFeatureUpdate("purple", featureStub);
|
|
|
|
store.updateExperiment(experiment.slug, experiment);
|
|
|
|
await TestUtils.waitForCondition(
|
|
() => featureStub.callCount == 2,
|
|
"Wait for `on` method to notify callback about the `add` event."
|
|
);
|
|
// Called twice, once when attaching the event listener (because there is an
|
|
// existing experiment with that name) and 2nd time for the update event
|
|
Assert.equal(featureStub.callCount, 2, "Called twice for feature");
|
|
Assert.equal(featureStub.firstCall.args[0], "featureUpdate:purple");
|
|
Assert.equal(featureStub.firstCall.args[1], "experiment-updated");
|
|
|
|
store._offFeatureUpdate("featureUpdate:purple", featureStub);
|
|
|
|
await manager.unenroll(experiment.slug);
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function test_updateExperiment_eventEmit_off() {
|
|
const { manager, sandbox, cleanup } = await NimbusTestUtils.setupTest();
|
|
const store = manager.store;
|
|
|
|
const featureStub = sandbox.stub();
|
|
const experiment = NimbusTestUtils.factories.experiment("foo", {
|
|
branch: {
|
|
slug: "variant",
|
|
ratio: 1,
|
|
features: [{ featureId: "purple", value: {} }],
|
|
},
|
|
});
|
|
|
|
store.on("featureUpdate:purple", featureStub);
|
|
|
|
store.addEnrollment(experiment);
|
|
|
|
store.off("featureUpdate:purple", featureStub);
|
|
|
|
store.updateExperiment(experiment.slug, experiment);
|
|
|
|
Assert.equal(featureStub.callCount, 1, "Called only once before `off`");
|
|
|
|
await manager.unenroll(experiment.slug);
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetEnrollments() {
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const fallbackPref = "nimbus.test-only.feature.baz";
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(
|
|
new ExperimentFeature("foo", {
|
|
variables: {
|
|
foo: { type: "int" },
|
|
bar: { type: "boolean" },
|
|
baz: {
|
|
type: "string",
|
|
fallbackPref,
|
|
},
|
|
},
|
|
})
|
|
);
|
|
|
|
Services.prefs.setStringPref(fallbackPref, "pref-value");
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment", {
|
|
branchSlug: "treatment",
|
|
featureId: "foo",
|
|
value: { foo: 1, baz: "qux" },
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout",
|
|
{ featureId: "foo", value: { foo: 2, bar: false } },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
const enrollments = NimbusFeatures.foo
|
|
.getAllEnrollments()
|
|
.sort((a, b) => a.meta.slug.localeCompare(b.meta.slug));
|
|
|
|
Assert.deepEqual(
|
|
enrollments,
|
|
[
|
|
{
|
|
meta: {
|
|
slug: "experiment",
|
|
branch: "treatment",
|
|
isRollout: false,
|
|
},
|
|
value: {
|
|
foo: 1,
|
|
baz: "qux",
|
|
},
|
|
},
|
|
{
|
|
meta: {
|
|
slug: "rollout",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
value: {
|
|
foo: 2,
|
|
bar: false,
|
|
baz: "pref-value",
|
|
},
|
|
},
|
|
],
|
|
"Should have two enrollments"
|
|
);
|
|
|
|
await NimbusTestUtils.cleanupManager(["experiment", "rollout"], { manager });
|
|
Services.prefs.clearUserPref(fallbackPref);
|
|
cleanupFeature();
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetEnrollmentsCoenrolling() {
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const fallbackPref = "nimbus.test-only.feature.baz";
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(
|
|
new ExperimentFeature("foo", {
|
|
allowCoenrollment: true,
|
|
variables: {
|
|
foo: { type: "int" },
|
|
bar: { type: "boolean" },
|
|
baz: {
|
|
type: "string",
|
|
fallbackPref,
|
|
},
|
|
},
|
|
})
|
|
);
|
|
|
|
Services.prefs.setStringPref(fallbackPref, "pref-value");
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-1", {
|
|
branchSlug: "treatment-a",
|
|
featureId: "foo",
|
|
value: { foo: 1, baz: "qux" },
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-2", {
|
|
branchSlug: "treatment-b",
|
|
featureId: "foo",
|
|
value: { foo: 2 },
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-1",
|
|
{ featureId: "foo", value: { foo: 3, bar: true } },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-2",
|
|
{ featureId: "foo", value: { bar: false, baz: "quux" } },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
const enrollments = NimbusFeatures.foo
|
|
.getAllEnrollments()
|
|
.sort((a, b) => a.meta.slug.localeCompare(b.meta.slug));
|
|
|
|
Assert.deepEqual(
|
|
enrollments,
|
|
[
|
|
{
|
|
meta: {
|
|
slug: "experiment-1",
|
|
branch: "treatment-a",
|
|
isRollout: false,
|
|
},
|
|
value: {
|
|
foo: 1,
|
|
baz: "qux",
|
|
},
|
|
},
|
|
{
|
|
meta: {
|
|
slug: "experiment-2",
|
|
branch: "treatment-b",
|
|
isRollout: false,
|
|
},
|
|
value: {
|
|
foo: 2,
|
|
baz: "pref-value",
|
|
},
|
|
},
|
|
{
|
|
meta: {
|
|
slug: "rollout-1",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
value: {
|
|
foo: 3,
|
|
bar: true,
|
|
baz: "pref-value",
|
|
},
|
|
},
|
|
{
|
|
meta: {
|
|
slug: "rollout-2",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
value: {
|
|
bar: false,
|
|
baz: "quux",
|
|
},
|
|
},
|
|
],
|
|
"Should have four enrollments"
|
|
);
|
|
|
|
await NimbusTestUtils.cleanupManager(
|
|
["experiment-1", "experiment-2", "rollout-1", "rollout-2"],
|
|
{ manager }
|
|
);
|
|
Services.prefs.clearUserPref(fallbackPref);
|
|
cleanupFeature();
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetEnrollmentMetadata() {
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(
|
|
new ExperimentFeature("foo", {
|
|
variables: {},
|
|
})
|
|
);
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment", {
|
|
branchSlug: "treatment",
|
|
featureId: "foo",
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout",
|
|
{ featureId: "foo" },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
const enrollments = NimbusFeatures.foo
|
|
.getAllEnrollmentMetadata()
|
|
.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
|
|
Assert.deepEqual(
|
|
enrollments,
|
|
[
|
|
{
|
|
slug: "experiment",
|
|
branch: "treatment",
|
|
isRollout: false,
|
|
},
|
|
{
|
|
slug: "rollout",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
],
|
|
"Should have two enrollments"
|
|
);
|
|
|
|
await NimbusTestUtils.cleanupManager(["experiment", "rollout"], { manager });
|
|
|
|
cleanupFeature();
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetEnrollmentMetadataCoenrolling() {
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(
|
|
new ExperimentFeature("foo", {
|
|
allowCoenrollment: true,
|
|
variables: {},
|
|
})
|
|
);
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-1", {
|
|
branchSlug: "treatment-a",
|
|
featureId: "foo",
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-2", {
|
|
branchSlug: "treatment-b",
|
|
featureId: "foo",
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-1",
|
|
{ featureId: "foo" },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-2",
|
|
{ featureId: "foo" },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
const enrollments = NimbusFeatures.foo
|
|
.getAllEnrollmentMetadata()
|
|
.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
|
|
Assert.deepEqual(
|
|
enrollments,
|
|
[
|
|
{
|
|
slug: "experiment-1",
|
|
branch: "treatment-a",
|
|
isRollout: false,
|
|
},
|
|
{
|
|
slug: "experiment-2",
|
|
branch: "treatment-b",
|
|
isRollout: false,
|
|
},
|
|
{
|
|
slug: "rollout-1",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
{
|
|
slug: "rollout-2",
|
|
branch: "control",
|
|
isRollout: true,
|
|
},
|
|
],
|
|
"Should have four enrollments"
|
|
);
|
|
|
|
await NimbusTestUtils.cleanupManager(
|
|
["experiment-1", "experiment-2", "rollout-1", "rollout-2"],
|
|
{ manager }
|
|
);
|
|
|
|
cleanupFeature();
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testCoenrollingTraditionalApis() {
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(
|
|
new ExperimentFeature("foo", {
|
|
allowCoenrollment: true,
|
|
variables: {},
|
|
})
|
|
);
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-1", {
|
|
branchSlug: "treatment-a",
|
|
featureId: "foo",
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-2", {
|
|
branchSlug: "treatment-b",
|
|
featureId: "foo",
|
|
}),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-1",
|
|
{ featureId: "foo" },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-2",
|
|
{ featureId: "foo" },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
Assert.throws(
|
|
() => NimbusFeatures.foo.getAllVariables(),
|
|
/Co-enrolling features must use the getAllEnrollments API/
|
|
);
|
|
|
|
Assert.throws(
|
|
() => NimbusFeatures.foo.getVariable("bar"),
|
|
/Co-enrolling features must use the getAllEnrollments API/
|
|
);
|
|
Assert.throws(
|
|
() => NimbusFeatures.foo.recordExposureEvent(),
|
|
/Co-enrolling features must provide slug/
|
|
);
|
|
|
|
Assert.throws(
|
|
() => NimbusFeatures.foo.getEnrollmentMetadata(),
|
|
/Co-enrolling features must use the getAllEnrollments or getAllEnrollmentMetadata APIs/
|
|
);
|
|
|
|
NimbusFeatures.foo.recordExposureEvent({ slug: "experiment-1" });
|
|
NimbusFeatures.foo.recordExposureEvent({ slug: "rollout-2" });
|
|
|
|
Assert.deepEqual(
|
|
Glean.nimbusEvents.exposure.testGetValue("events")?.map(ev => ev.extra),
|
|
[
|
|
{
|
|
experiment: "experiment-1",
|
|
branch: "treatment-a",
|
|
feature_id: "foo",
|
|
},
|
|
{
|
|
experiment: "rollout-2",
|
|
branch: "control",
|
|
feature_id: "foo",
|
|
},
|
|
]
|
|
);
|
|
|
|
await NimbusTestUtils.cleanupManager(
|
|
["experiment-1", "experiment-2", "rollout-1", "rollout-2"],
|
|
{ manager }
|
|
);
|
|
|
|
cleanupFeature();
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetEnrollmentMetadata() {
|
|
const feature = new ExperimentFeature("test-feature", {
|
|
variables: {},
|
|
});
|
|
const featureId = feature.featureId;
|
|
const cleanupFeature = NimbusTestUtils.addTestFeatures(feature);
|
|
|
|
const { manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
const experimentMeta = {
|
|
slug: "experiment-slug",
|
|
branch: "treatment",
|
|
isRollout: false,
|
|
};
|
|
|
|
const rolloutMeta = {
|
|
slug: "rollout-slug",
|
|
branch: "control",
|
|
isRollout: true,
|
|
};
|
|
|
|
// There are no active enrollments.
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("experiment"),
|
|
null
|
|
);
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("rollout"),
|
|
null
|
|
);
|
|
Assert.equal(NimbusFeatures[featureId].getEnrollmentMetadata(), null);
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig(
|
|
"rollout-slug",
|
|
{ featureId },
|
|
{ isRollout: true }
|
|
),
|
|
"test"
|
|
);
|
|
|
|
// Thre are no active experiments, but there is an active rollout.
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("experiment"),
|
|
null
|
|
);
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("rollout"),
|
|
rolloutMeta
|
|
);
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata(),
|
|
rolloutMeta
|
|
);
|
|
|
|
await manager.enroll(
|
|
NimbusTestUtils.factories.recipe.withFeatureConfig("experiment-slug", {
|
|
featureId,
|
|
branchSlug: "treatment",
|
|
}),
|
|
"test"
|
|
);
|
|
|
|
// There is an active experiment and rollout, so we should get the experiment metadata by default.
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("experiment"),
|
|
experimentMeta
|
|
);
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("rollout"),
|
|
rolloutMeta
|
|
);
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata(),
|
|
experimentMeta
|
|
);
|
|
|
|
await manager.unenroll("rollout-slug");
|
|
|
|
// There is only an active experiment.
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("experiment"),
|
|
experimentMeta
|
|
);
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("rollout"),
|
|
null
|
|
);
|
|
Assert.deepEqual(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata(),
|
|
experimentMeta
|
|
);
|
|
|
|
await manager.unenroll("experiment-slug");
|
|
|
|
// There are no active enrollments.
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("experiment"),
|
|
null
|
|
);
|
|
Assert.equal(
|
|
NimbusFeatures[featureId].getEnrollmentMetadata("rollout"),
|
|
null
|
|
);
|
|
Assert.equal(NimbusFeatures[featureId].getEnrollmentMetadata(), null);
|
|
|
|
await cleanup();
|
|
cleanupFeature();
|
|
});
|
|
|
|
add_task(async function testGetEnrollmentMetadataSafe() {
|
|
const { sandbox, manager, cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
sandbox.stub(NimbusTelemetry, "recordExposure");
|
|
sandbox.stub(manager.store, "getExperimentForFeature").throws();
|
|
sandbox.stub(manager.store, "getRolloutForFeature").throws();
|
|
|
|
Assert.equal(
|
|
NimbusFeatures.testFeature.getEnrollmentMetadata(),
|
|
null,
|
|
"Should not throw"
|
|
);
|
|
Assert.equal(
|
|
NimbusFeatures.testFeature.getEnrollmentMetadata("experiment"),
|
|
null,
|
|
"Should not throw"
|
|
);
|
|
Assert.equal(
|
|
NimbusFeatures.testFeature.getEnrollmentMetadata("rollout"),
|
|
null,
|
|
"Should not throw"
|
|
);
|
|
|
|
Assert.equal(
|
|
manager.store.getExperimentForFeature.callCount,
|
|
2,
|
|
"getExperimentForFeature called"
|
|
);
|
|
Assert.equal(
|
|
manager.store.getRolloutForFeature.callCount,
|
|
1,
|
|
"getRolloutForFeature called"
|
|
);
|
|
|
|
NimbusFeatures.testFeature.recordExposureEvent();
|
|
Assert.ok(
|
|
NimbusTelemetry.recordExposure.notCalled,
|
|
"Should not record exposure"
|
|
);
|
|
Assert.equal(
|
|
manager.store.getExperimentForFeature.callCount,
|
|
3,
|
|
"getExperimentForFeature called"
|
|
);
|
|
|
|
await cleanup();
|
|
});
|
|
|
|
add_task(async function testGetProfileId() {
|
|
const { cleanup } = await NimbusTestUtils.setupTest();
|
|
|
|
Assert.ok(
|
|
Services.prefs.prefHasUserValue("nimbus.profileId"),
|
|
"nimbus.profileId set on user branch"
|
|
);
|
|
Assert.ok(
|
|
!!Services.prefs.getStringPref("nimbus.profileId"),
|
|
"can get profile ID pref"
|
|
);
|
|
|
|
Assert.equal(
|
|
ExperimentAPI.profileId,
|
|
Services.prefs.getStringPref("nimbus.profileId"),
|
|
"ExperimentAPI.profileId matches pref value"
|
|
);
|
|
|
|
await cleanup();
|
|
});
|