forked from mirrors/gecko-dev
196 lines
5.4 KiB
JavaScript
196 lines
5.4 KiB
JavaScript
"use strict";
|
|
|
|
const { _ExperimentManager } = ChromeUtils.import(
|
|
"resource://messaging-system/experiments/ExperimentManager.jsm"
|
|
);
|
|
const { ExperimentStore } = ChromeUtils.import(
|
|
"resource://messaging-system/experiments/ExperimentStore.jsm"
|
|
);
|
|
const { ExperimentFakes } = ChromeUtils.import(
|
|
"resource://testing-common/MSTestUtils.jsm"
|
|
);
|
|
|
|
/**
|
|
* onStartup()
|
|
* - should set call setExperimentActive for each active experiment
|
|
*/
|
|
add_task(async function test_onStartup_setExperimentActive_called() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
const experiments = [];
|
|
sandbox.stub(manager, "setExperimentActive");
|
|
sandbox.stub(manager.store, "init").resolves();
|
|
sandbox.stub(manager.store, "getAll").returns(experiments);
|
|
|
|
const active = ["foo", "bar"].map(ExperimentFakes.experiment);
|
|
|
|
const inactive = ["baz", "qux"].map(slug =>
|
|
ExperimentFakes.experiment(slug, { active: false })
|
|
);
|
|
|
|
[...active, ...inactive].forEach(exp => experiments.push(exp));
|
|
|
|
await manager.onStartup();
|
|
|
|
active.forEach(exp =>
|
|
Assert.equal(
|
|
manager.setExperimentActive.calledWith(exp),
|
|
true,
|
|
`should call setExperimentActive for active experiment: ${exp.slug}`
|
|
)
|
|
);
|
|
|
|
inactive.forEach(exp =>
|
|
Assert.equal(
|
|
manager.setExperimentActive.calledWith(exp),
|
|
false,
|
|
`should not call setExperimentActive for inactive experiment: ${exp.slug}`
|
|
)
|
|
);
|
|
});
|
|
|
|
/**
|
|
* onRecipe()
|
|
* - should add recipe slug to .session[source]
|
|
* - should call .enroll() if the recipe hasn't been seen before;
|
|
* - should call .update() if the Enrollment already exists in the store;
|
|
* - should skip enrollment if recipe.isEnrollmentPaused is true
|
|
*/
|
|
add_task(async function test_onRecipe_track_slug() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
sandbox.spy(manager, "enroll");
|
|
sandbox.spy(manager, "updateEnrollment");
|
|
|
|
const fooRecipe = ExperimentFakes.recipe("foo");
|
|
|
|
await manager.onStartup();
|
|
// The first time a recipe has seen;
|
|
await manager.onRecipe(fooRecipe, "test");
|
|
|
|
Assert.equal(
|
|
manager.sessions.get("test").has("foo"),
|
|
true,
|
|
"should add slug to sessions[test]"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_onRecipe_enroll() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
sandbox.spy(manager, "enroll");
|
|
sandbox.spy(manager, "updateEnrollment");
|
|
|
|
const fooRecipe = ExperimentFakes.recipe("foo");
|
|
|
|
await manager.onStartup();
|
|
await manager.onRecipe(fooRecipe, "test");
|
|
|
|
Assert.equal(
|
|
manager.enroll.calledWith(fooRecipe),
|
|
true,
|
|
"should call .enroll() the first time a recipe is seen"
|
|
);
|
|
Assert.equal(
|
|
manager.store.has("foo"),
|
|
true,
|
|
"should add recipe to the store"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_onRecipe_update() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
sandbox.spy(manager, "enroll");
|
|
sandbox.spy(manager, "updateEnrollment");
|
|
|
|
const fooRecipe = ExperimentFakes.recipe("foo");
|
|
|
|
await manager.onStartup();
|
|
await manager.onRecipe(fooRecipe, "test");
|
|
// Call again after recipe has already been enrolled
|
|
await manager.onRecipe(fooRecipe, "test");
|
|
|
|
Assert.equal(
|
|
manager.updateEnrollment.calledWith(fooRecipe),
|
|
true,
|
|
"should call .updateEnrollment() if the recipe has already been enrolled"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_onRecipe_isEnrollmentPaused() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
sandbox.spy(manager, "enroll");
|
|
sandbox.spy(manager, "updateEnrollment");
|
|
|
|
await manager.onStartup();
|
|
|
|
const pausedRecipe = ExperimentFakes.recipe("xyz", {
|
|
isEnrollmentPaused: true,
|
|
});
|
|
await manager.onRecipe(pausedRecipe, "test");
|
|
Assert.equal(
|
|
manager.enroll.calledWith(pausedRecipe),
|
|
false,
|
|
"should skip enrollment for recipes that are paused"
|
|
);
|
|
Assert.equal(
|
|
manager.store.has("xyz"),
|
|
false,
|
|
"should not add recipe to the store"
|
|
);
|
|
|
|
const fooRecipe = ExperimentFakes.recipe("foo");
|
|
const updatedRecipe = ExperimentFakes.recipe("foo", {
|
|
isEnrollmentPaused: true,
|
|
});
|
|
await manager.enroll(fooRecipe);
|
|
await manager.onRecipe(updatedRecipe, "test");
|
|
Assert.equal(
|
|
manager.updateEnrollment.calledWith(updatedRecipe),
|
|
true,
|
|
"should still update existing recipes, even if enrollment is paused"
|
|
);
|
|
});
|
|
|
|
/**
|
|
* onFinalize()
|
|
* - should unenroll experiments that weren't seen in the current session
|
|
*/
|
|
|
|
add_task(async function test_onFinalize_unenroll() {
|
|
const manager = ExperimentFakes.manager();
|
|
const sandbox = sinon.createSandbox();
|
|
sandbox.spy(manager, "unenroll");
|
|
|
|
await manager.onStartup();
|
|
|
|
// Add an experiment to the store without calling .onRecipe
|
|
// This simulates an enrollment having happened in the past.
|
|
manager.store.addExperiment(ExperimentFakes.experiment("foo"));
|
|
|
|
// Simulate adding some other recipes
|
|
await manager.onStartup();
|
|
await manager.onRecipe(ExperimentFakes.recipe("bar"), "test");
|
|
await manager.onRecipe(ExperimentFakes.recipe("baz"), "test");
|
|
|
|
// Finalize
|
|
manager.onFinalize("test");
|
|
|
|
Assert.equal(
|
|
manager.unenroll.callCount,
|
|
1,
|
|
"should only call unenroll for the unseen recipe"
|
|
);
|
|
Assert.equal(
|
|
manager.unenroll.calledWith("foo", "recipe-not-seen"),
|
|
true,
|
|
"should unenroll a experiment whose recipe wasn't seen in the current session"
|
|
);
|
|
Assert.equal(
|
|
manager.sessions.has("test"),
|
|
false,
|
|
"should clear sessions[test]"
|
|
);
|
|
});
|