fune/toolkit/components/normandy/test/browser/browser_NormandyDriver.js
Mike Cooper 101e2d9dff Bug 1440780 - Add Normandy action for add-on studies r=aswan
This ports the code from the Normandy server github repo to run as a local
action, instead of being fetched from the server.

The original code is here:
c0a8c53707/client/actions/opt-out-study

Differential Revision: https://phabricator.services.mozilla.com/D2973

--HG--
extra : moz-landing-system : lando
2018-08-22 19:25:10 +00:00

216 lines
7.8 KiB
JavaScript

"use strict";
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://normandy/lib/NormandyDriver.jsm", this);
ChromeUtils.import("resource://normandy/lib/PreferenceExperiments.jsm", this);
add_task(withDriver(Assert, async function uuids(driver) {
// Test that it is a UUID
const uuid1 = driver.uuid();
ok(UUID_REGEX.test(uuid1), "valid uuid format");
// Test that UUIDs are different each time
const uuid2 = driver.uuid();
isnot(uuid1, uuid2, "uuids are unique");
}));
add_task(withDriver(Assert, async function userId(driver) {
// Test that userId is a UUID
ok(UUID_REGEX.test(driver.userId), "userId is a uuid");
}));
add_task(withDriver(Assert, async function syncDeviceCounts(driver) {
let client = await driver.client();
is(client.syncMobileDevices, 0, "syncMobileDevices defaults to zero");
is(client.syncDesktopDevices, 0, "syncDesktopDevices defaults to zero");
is(client.syncTotalDevices, 0, "syncTotalDevices defaults to zero");
await SpecialPowers.pushPrefEnv({
set: [
["services.sync.clients.devices.mobile", 5],
["services.sync.clients.devices.desktop", 4],
],
});
client = await driver.client();
is(client.syncMobileDevices, 5, "syncMobileDevices is read when set");
is(client.syncDesktopDevices, 4, "syncDesktopDevices is read when set");
is(client.syncTotalDevices, 9, "syncTotalDevices is read when set");
}));
add_task(withDriver(Assert, async function distribution(driver) {
let client = await driver.client();
is(client.distribution, "default", "distribution has a default value");
await SpecialPowers.pushPrefEnv({set: [["distribution.id", "funnelcake"]]});
client = await driver.client();
is(client.distribution, "funnelcake", "distribution is read from preferences");
}));
decorate_task(
withSandboxManager(Assert),
async function testCreateStorage(sandboxManager) {
const driver = new NormandyDriver(sandboxManager);
sandboxManager.cloneIntoGlobal("driver", driver, {cloneFunctions: true});
// Assertion helpers
sandboxManager.addGlobal("is", is);
sandboxManager.addGlobal("deepEqual", (...args) => Assert.deepEqual(...args));
await sandboxManager.evalInSandbox(`
(async function sandboxTest() {
const store = driver.createStorage("testprefix");
const otherStore = driver.createStorage("othertestprefix");
await store.clear();
await otherStore.clear();
await store.setItem("willremove", 7);
await otherStore.setItem("willremove", 4);
is(await store.getItem("willremove"), 7, "createStorage stores sandbox values");
is(
await otherStore.getItem("willremove"),
4,
"values are not shared between createStorage stores",
);
const deepValue = {"foo": ["bar", "baz"]};
await store.setItem("deepValue", deepValue);
deepEqual(await store.getItem("deepValue"), deepValue, "createStorage clones stored values");
await store.removeItem("willremove");
is(await store.getItem("willremove"), null, "createStorage removes items");
is('prefix' in store, false, "createStorage doesn't expose non-whitelist attributes");
})();
`);
}
);
decorate_task(
withPrefEnv({
set: [
["test.char", "a string"],
["test.int", 5],
["test.bool", true],
],
}),
withSandboxManager(Assert, async function testPreferences(sandboxManager) {
const driver = new NormandyDriver(sandboxManager);
sandboxManager.cloneIntoGlobal("driver", driver, {cloneFunctions: true});
// Assertion helpers
sandboxManager.addGlobal("is", is);
sandboxManager.addGlobal("ok", ok);
sandboxManager.addGlobal("assertThrows", Assert.throws.bind(Assert));
await sandboxManager.evalInSandbox(`
(async function sandboxTest() {
ok(
driver.preferences.getBool("test.bool"),
"preferences.getBool can retrieve boolean preferences."
);
is(
driver.preferences.getInt("test.int"),
5,
"preferences.getInt can retrieve integer preferences."
);
is(
driver.preferences.getChar("test.char"),
"a string",
"preferences.getChar can retrieve string preferences."
);
assertThrows(
() => driver.preferences.getChar("test.int"),
"preferences.getChar throws when retreiving a non-string preference."
);
assertThrows(
() => driver.preferences.getInt("test.bool"),
"preferences.getInt throws when retreiving a non-integer preference."
);
assertThrows(
() => driver.preferences.getBool("test.char"),
"preferences.getBool throws when retreiving a non-boolean preference."
);
assertThrows(
() => driver.preferences.getChar("test.does.not.exist"),
"preferences.getChar throws when retreiving a non-existant preference."
);
assertThrows(
() => driver.preferences.getInt("test.does.not.exist"),
"preferences.getInt throws when retreiving a non-existant preference."
);
assertThrows(
() => driver.preferences.getBool("test.does.not.exist"),
"preferences.getBool throws when retreiving a non-existant preference."
);
ok(
driver.preferences.getBool("test.does.not.exist", true),
"preferences.getBool returns a default value if the preference doesn't exist."
);
is(
driver.preferences.getInt("test.does.not.exist", 7),
7,
"preferences.getInt returns a default value if the preference doesn't exist."
);
is(
driver.preferences.getChar("test.does.not.exist", "default"),
"default",
"preferences.getChar returns a default value if the preference doesn't exist."
);
ok(
driver.preferences.has("test.char"),
"preferences.has returns true if the given preference exists."
);
ok(
!driver.preferences.has("test.does.not.exist"),
"preferences.has returns false if the given preference does not exist."
);
})();
`);
})
);
decorate_task(
withSandboxManager(Assert),
withMockPreferences,
PreferenceExperiments.withMockExperiments,
async function testPreferenceStudies(sandboxManager) {
const driver = new NormandyDriver(sandboxManager);
sandboxManager.cloneIntoGlobal("driver", driver, {cloneFunctions: true});
// Assertion helpers
sandboxManager.addGlobal("is", is);
sandboxManager.addGlobal("ok", ok);
await sandboxManager.evalInSandbox(`
(async function sandboxTest() {
const studyName = "preftest";
let hasStudy = await driver.preferenceExperiments.has(studyName);
ok(!hasStudy, "preferenceExperiments.has returns false if the study hasn't been started yet.");
await driver.preferenceExperiments.start({
name: studyName,
branch: "control",
preferenceName: "test.pref",
preferenceValue: true,
preferenceBranchType: "user",
preferenceType: "boolean",
});
hasStudy = await driver.preferenceExperiments.has(studyName);
ok(hasStudy, "preferenceExperiments.has returns true after the study has been started.");
let study = await driver.preferenceExperiments.get(studyName);
is(
study.branch,
"control",
"preferenceExperiments.get fetches studies from within a sandbox."
);
ok(!study.expired, "Studies are marked as active after being started by the driver.");
await driver.preferenceExperiments.stop(studyName);
study = await driver.preferenceExperiments.get(studyName);
ok(study.expired, "Studies are marked as inactive after being stopped by the driver.");
})();
`);
}
);