fune/toolkit/components/normandy/test/browser/browser_PreferenceRollouts.js
Mike Cooper 737340a5cf Bug 1457511 - Check that Normandy telemetry events match schema r=Gijs
MozReview-Commit-ID: 40vvPG0UzNZ

--HG--
extra : rebase_source : 3006a2a98e75513b64412217e837f8f9d38914e1
2018-04-30 09:27:52 -07:00

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"
);
},
);