fune/toolkit/components/messaging-system/test/unit/test_ExperimentManager_enroll.js

138 lines
3.7 KiB
JavaScript

"use strict";
const { ExperimentFakes } = ChromeUtils.import(
"resource://testing-common/MSTestUtils.jsm"
);
const { NormandyTestUtils } = ChromeUtils.import(
"resource://testing-common/NormandyTestUtils.jsm"
);
/**
* The normal case: Enrollment of a new experiment
*/
add_task(async function test_add_to_store() {
const manager = ExperimentFakes.manager();
const recipe = ExperimentFakes.recipe("foo");
await manager.onStartup();
await manager.enroll(recipe);
const experiment = manager.store.get("foo");
Assert.ok(experiment, "should add an experiment with slug foo");
Assert.ok(
recipe.branches.includes(experiment.branch),
"should choose a branch from the recipe.branches"
);
Assert.equal(experiment.active, true, "should set .active = true");
Assert.ok(
NormandyTestUtils.isUuid(experiment.enrollmentId),
"should add a valid enrollmentId"
);
});
add_task(
async function test_setExperimentActive_sendEnrollmentTelemetry_called() {
const manager = ExperimentFakes.manager();
const sandbox = sinon.createSandbox();
sandbox.spy(manager, "setExperimentActive");
sandbox.spy(manager, "sendEnrollmentTelemetry");
await manager.onStartup();
await manager.onStartup();
await manager.enroll(ExperimentFakes.recipe("foo"));
const experiment = manager.store.get("foo");
Assert.equal(
manager.setExperimentActive.calledWith(experiment),
true,
"should call setExperimentActive after an enrollment"
);
Assert.equal(
manager.sendEnrollmentTelemetry.calledWith(experiment),
true,
"should call sendEnrollmentTelemetry after an enrollment"
);
}
);
/**
* Failure cases:
* - slug conflict
* - group conflict
*/
add_task(async function test_failure_name_conflict() {
const manager = ExperimentFakes.manager();
const sandbox = sinon.createSandbox();
sandbox.spy(manager, "sendFailureTelemetry");
await manager.onStartup();
// simulate adding a previouly enrolled experiment
manager.store.addExperiment(ExperimentFakes.experiment("foo"));
await Assert.rejects(
manager.enroll(ExperimentFakes.recipe("foo")),
/An experiment with the slug "foo" already exists/,
"should throw if a conflicting experiment exists"
);
Assert.equal(
manager.sendFailureTelemetry.calledWith(
"enrollFailed",
"foo",
"name-conflict"
),
true,
"should send failure telemetry if a conflicting experiment exists"
);
});
add_task(async function test_failure_group_conflict() {
const manager = ExperimentFakes.manager();
const sandbox = sinon.createSandbox();
sandbox.spy(manager, "sendFailureTelemetry");
await manager.onStartup();
// Two conflicting branches that both have the group "pink"
// These should not be allowed to exist simultaneously.
const existingBranch = {
slug: "treatment",
groups: ["red", "pink"],
value: { title: "hello" },
};
const newBranch = {
slug: "treatment",
groups: ["pink"],
value: { title: "hi" },
};
// simulate adding an experiment with a conflicting group "pink"
manager.store.addExperiment(
ExperimentFakes.experiment("foo", {
branch: existingBranch,
})
);
// ensure .enroll chooses the special branch with the conflict
sandbox.stub(manager, "chooseBranch").returns(newBranch);
await Assert.rejects(
manager.enroll(ExperimentFakes.recipe("bar", { branches: [newBranch] })),
/An experiment with a conflicting group already exists/,
"should throw if there is a group conflict"
);
Assert.equal(
manager.sendFailureTelemetry.calledWith(
"enrollFailed",
"bar",
"group-conflict"
),
true,
"should send failure telemetry if a group conflict exists"
);
});