forked from mirrors/gecko-dev
MozReview-Commit-ID: 40vvPG0UzNZ --HG-- extra : rebase_source : 3006a2a98e75513b64412217e837f8f9d38914e1
220 lines
7.4 KiB
JavaScript
220 lines
7.4 KiB
JavaScript
"use strict";
|
|
|
|
ChromeUtils.import("resource://gre/modules/IndexedDB.jsm", this);
|
|
ChromeUtils.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
|
|
ChromeUtils.import("resource://normandy/lib/PreferenceRollouts.jsm", this);
|
|
ChromeUtils.import("resource://normandy/lib/TelemetryEvents.jsm", this);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetMissing() {
|
|
is(
|
|
await PreferenceRollouts.get("does-not-exist"),
|
|
null,
|
|
"get should return null when the requested rollout does not exist"
|
|
);
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testAddUpdateAndGet() {
|
|
const rollout = {slug: "test-rollout", state: PreferenceRollouts.STATE_ACTIVE, preferences: []};
|
|
await PreferenceRollouts.add(rollout);
|
|
let storedRollout = await PreferenceRollouts.get(rollout.slug);
|
|
Assert.deepEqual(rollout, storedRollout, "get should retrieve a rollout from storage.");
|
|
|
|
rollout.state = PreferenceRollouts.STATE_GRADUATED;
|
|
await PreferenceRollouts.update(rollout);
|
|
storedRollout = await PreferenceRollouts.get(rollout.slug);
|
|
Assert.deepEqual(rollout, storedRollout, "get should retrieve a rollout from storage.");
|
|
},
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testCantUpdateNonexistent() {
|
|
const rollout = {slug: "test-rollout", state: PreferenceRollouts.STATE_ACTIVE, preferences: []};
|
|
await Assert.rejects(
|
|
PreferenceRollouts.update(rollout),
|
|
/doesn't already exist/,
|
|
"Update should fail if the rollout doesn't exist",
|
|
);
|
|
ok(!await PreferenceRollouts.has("test-rollout"), "rollout should not have been added");
|
|
},
|
|
);
|
|
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetAll() {
|
|
const rollout1 = {slug: "test-rollout-1", preference: []};
|
|
const rollout2 = {slug: "test-rollout-2", preference: []};
|
|
await PreferenceRollouts.add(rollout1);
|
|
await PreferenceRollouts.add(rollout2);
|
|
|
|
const storedRollouts = await PreferenceRollouts.getAll();
|
|
Assert.deepEqual(
|
|
storedRollouts.sort((a, b) => a.id - b.id),
|
|
[rollout1, rollout2],
|
|
"getAll should return every stored rollout.",
|
|
);
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testGetAllActive() {
|
|
const rollout1 = {slug: "test-rollout-1", state: PreferenceRollouts.STATE_ACTIVE};
|
|
const rollout2 = {slug: "test-rollout-2", state: PreferenceRollouts.STATE_GRADUATED};
|
|
const rollout3 = {slug: "test-rollout-3", state: PreferenceRollouts.STATE_ROLLED_BACK};
|
|
await PreferenceRollouts.add(rollout1);
|
|
await PreferenceRollouts.add(rollout2);
|
|
await PreferenceRollouts.add(rollout3);
|
|
|
|
const activeRollouts = await PreferenceRollouts.getAllActive();
|
|
Assert.deepEqual(activeRollouts, [rollout1], "getAllActive should return only active rollouts");
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testHas() {
|
|
const rollout = {slug: "test-rollout", preferences: []};
|
|
await PreferenceRollouts.add(rollout);
|
|
ok(await PreferenceRollouts.has(rollout.slug), "has should return true for an existing rollout");
|
|
ok(!await PreferenceRollouts.has("does not exist"), "has should return false for a missing rollout");
|
|
}
|
|
);
|
|
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testCloseDatabase() {
|
|
await PreferenceRollouts.closeDB();
|
|
const openSpy = sinon.spy(IndexedDB, "open");
|
|
sinon.assert.notCalled(openSpy);
|
|
|
|
try {
|
|
// Using rollouts at all should open the database, but only once.
|
|
await PreferenceRollouts.has("foo");
|
|
await PreferenceRollouts.get("foo");
|
|
sinon.assert.calledOnce(openSpy);
|
|
openSpy.reset();
|
|
|
|
// close can be called multiple times
|
|
await PreferenceRollouts.closeDB();
|
|
await PreferenceRollouts.closeDB();
|
|
// and don't cause the database to be opened (that would be weird)
|
|
sinon.assert.notCalled(openSpy);
|
|
|
|
// After being closed, new operations cause the database to be opened again, but only once
|
|
await PreferenceRollouts.has("foo");
|
|
await PreferenceRollouts.get("foo");
|
|
sinon.assert.calledOnce(openSpy);
|
|
|
|
} finally {
|
|
openSpy.restore();
|
|
}
|
|
}
|
|
);
|
|
|
|
// recordOriginalValue should update storage to note the original values
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
async function testRecordOriginalValuesUpdatesPreviousValues() {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [{preferenceName: "test.pref", value: 2, previousValue: null}],
|
|
});
|
|
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref": 1});
|
|
|
|
Assert.deepEqual(
|
|
await PreferenceRollouts.getAll(),
|
|
[{
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [{preferenceName: "test.pref", value: 2, previousValue: 1}],
|
|
}],
|
|
"rollout in database should be updated",
|
|
);
|
|
},
|
|
);
|
|
|
|
// recordOriginalValue should graduate a study when it is no longer relevant.
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
withSendEventStub,
|
|
async function testRecordOriginalValuesUpdatesPreviousValues(sendEventStub) {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
preferences: [
|
|
{preferenceName: "test.pref1", value: 2, previousValue: null},
|
|
{preferenceName: "test.pref2", value: 2, previousValue: null},
|
|
],
|
|
});
|
|
|
|
// one pref being the same isn't enough to graduate
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref1": 1, "test.pref2": 2});
|
|
let rollout = await PreferenceRollouts.get("test-rollout");
|
|
is(
|
|
rollout.state,
|
|
PreferenceRollouts.STATE_ACTIVE,
|
|
"rollouts should remain active when only one pref matches the built-in default",
|
|
);
|
|
|
|
Assert.deepEqual(sendEventStub.args, [], "no events should be sent yet");
|
|
|
|
// both prefs is enough
|
|
await PreferenceRollouts.recordOriginalValues({"test.pref1": 2, "test.pref2": 2});
|
|
rollout = await PreferenceRollouts.get("test-rollout");
|
|
is(
|
|
rollout.state,
|
|
PreferenceRollouts.STATE_GRADUATED,
|
|
"rollouts should graduate when all prefs matches the built-in defaults",
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
sendEventStub.args,
|
|
[["graduate", "preference_rollout", "test-rollout", {}]],
|
|
"a graduation event should be sent",
|
|
);
|
|
},
|
|
);
|
|
|
|
// init should mark active rollouts in telemetry
|
|
decorate_task(
|
|
PreferenceRollouts.withTestMock,
|
|
withStub(TelemetryEnvironment, "setExperimentActive"),
|
|
async function testInitTelemetry(setExperimentActiveStub) {
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-active-1",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-active-2",
|
|
state: PreferenceRollouts.STATE_ACTIVE,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-rolled-back",
|
|
state: PreferenceRollouts.STATE_ROLLED_BACK,
|
|
});
|
|
await PreferenceRollouts.add({
|
|
slug: "test-rollout-graduated",
|
|
state: PreferenceRollouts.STATE_GRADUATED,
|
|
});
|
|
|
|
await PreferenceRollouts.init();
|
|
|
|
Assert.deepEqual(
|
|
setExperimentActiveStub.args,
|
|
[
|
|
["test-rollout-active-1", "active", {type: "normandy-prefrollout"}],
|
|
["test-rollout-active-2", "active", {type: "normandy-prefrollout"}],
|
|
],
|
|
"init should set activate a telemetry experiment for active preferences"
|
|
);
|
|
},
|
|
);
|