gecko-dev/toolkit/components/normandy/test/unit/test_PrefUtils.js
Michael Cooper 74cce16d19 Bug 1698684 - Leave users in Normandy experiments when prefs change r=Gijs
This reverses a decision that was made in the original design of Normandy's preference experiments. That decision was made assuming simple experiments that only change one preference.

Today, preferences are more complicated, have more interactions, and often change more than one preferences. Unenrolling users from experiments due to preferences changing causes bugs, unexpected experiences for users, and bad experiment outcomes.

This change will make Normandy act more in alignment with how experimenter owners and data analysts already treat it, improving the overall experience of the experiments program.

Differential Revision: https://phabricator.services.mozilla.com/D112070
2021-04-26 21:12:26 +00:00

223 lines
6.2 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { PrefUtils } = ChromeUtils.import(
"resource://normandy/lib/PrefUtils.jsm"
);
add_task(function getPrefGetsValues() {
const defaultBranch = Services.prefs.getDefaultBranch("");
const userBranch = Services.prefs;
defaultBranch.setBoolPref("test.bool", false);
userBranch.setBoolPref("test.bool", true);
defaultBranch.setIntPref("test.int", 1);
userBranch.setIntPref("test.int", 2);
defaultBranch.setStringPref("test.string", "default");
userBranch.setStringPref("test.string", "user");
equal(
PrefUtils.getPref("test.bool", { branch: "user" }),
true,
"should read user branch bools"
);
equal(
PrefUtils.getPref("test.int", { branch: "user" }),
2,
"should read user branch ints"
);
equal(
PrefUtils.getPref("test.string", { branch: "user" }),
"user",
"should read user branch strings"
);
equal(
PrefUtils.getPref("test.bool", { branch: "default" }),
false,
"should read default branch bools"
);
equal(
PrefUtils.getPref("test.int", { branch: "default" }),
1,
"should read default branch ints"
);
equal(
PrefUtils.getPref("test.string", { branch: "default" }),
"default",
"should read default branch strings"
);
equal(
PrefUtils.getPref("test.bool"),
true,
"should read bools from the user branch by default"
);
equal(
PrefUtils.getPref("test.int"),
2,
"should read ints from the user branch by default"
);
equal(
PrefUtils.getPref("test.string"),
"user",
"should read strings from the user branch by default"
);
equal(
PrefUtils.getPref("test.does_not_exist"),
null,
"Should return null for non-existent prefs by default"
);
let defaultValue = Symbol();
equal(
PrefUtils.getPref("test.does_not_exist", { defaultValue }),
defaultValue,
"Should use the passed default value"
);
});
// This is an important test because the pref system can behave in strange ways
// when the user branch has a value, but the default branch does not.
add_task(function getPrefHandlesUserValueNoDefaultValue() {
Services.prefs.setStringPref("test.only-user-value", "user");
let defaultValue = Symbol();
equal(
PrefUtils.getPref("test.only-user-value", {
branch: "default",
defaultValue,
}),
defaultValue
);
equal(PrefUtils.getPref("test.only-user-value", { branch: "default" }), null);
equal(PrefUtils.getPref("test.only-user-value", { branch: "user" }), "user");
equal(PrefUtils.getPref("test.only-user-value"), "user");
});
add_task(function getPrefInvalidBranch() {
Assert.throws(
() => PrefUtils.getPref("test.pref", { branch: "invalid" }),
PrefUtils.UnexpectedPreferenceBranch
);
});
add_task(function setPrefSetsValues() {
const defaultBranch = Services.prefs.getDefaultBranch("");
const userBranch = Services.prefs;
defaultBranch.setIntPref("test.int", 1);
userBranch.setIntPref("test.int", 2);
defaultBranch.setStringPref("test.string", "default");
userBranch.setStringPref("test.string", "user");
defaultBranch.setBoolPref("test.bool", false);
userBranch.setBoolPref("test.bool", true);
PrefUtils.setPref("test.int", 3);
equal(
userBranch.getIntPref("test.int"),
3,
"the user branch should change for ints"
);
PrefUtils.setPref("test.int", 4, { branch: "default" });
equal(
userBranch.getIntPref("test.int"),
3,
"changing the default branch shouldn't affect the user branch for ints"
);
PrefUtils.setPref("test.int", null, { branch: "user" });
equal(
userBranch.getIntPref("test.int"),
4,
"clearing the user branch should reveal the default value for ints"
);
PrefUtils.setPref("test.string", "user override");
equal(
userBranch.getStringPref("test.string"),
"user override",
"the user branch should change for strings"
);
PrefUtils.setPref("test.string", "default override", { branch: "default" });
equal(
userBranch.getStringPref("test.string"),
"user override",
"changing the default branch shouldn't affect the user branch for strings"
);
PrefUtils.setPref("test.string", null, { branch: "user" });
equal(
userBranch.getStringPref("test.string"),
"default override",
"clearing the user branch should reveal the default value for strings"
);
PrefUtils.setPref("test.bool", false);
equal(
userBranch.getBoolPref("test.bool"),
false,
"the user branch should change for bools"
);
// The above effectively unsets the user branch, since it is now the same as the default branch
PrefUtils.setPref("test.bool", true, { branch: "default" });
equal(
userBranch.getBoolPref("test.bool"),
true,
"the default branch should change for bools"
);
defaultBranch.setBoolPref("test.bool", false);
userBranch.setBoolPref("test.bool", true);
equal(
userBranch.getBoolPref("test.bool"),
true,
"the precondition should hold"
);
PrefUtils.setPref("test.bool", null, { branch: "user" });
equal(
userBranch.getBoolPref("test.bool"),
false,
"setting the user branch to null should reveal the default value for bools"
);
});
add_task(function setPrefInvalidBranch() {
Assert.throws(
() => PrefUtils.setPref("test.pref", "value", { branch: "invalid" }),
PrefUtils.UnexpectedPreferenceBranch
);
});
add_task(function clearPrefClearsValues() {
const defaultBranch = Services.prefs.getDefaultBranch("");
const userBranch = Services.prefs;
defaultBranch.setStringPref("test.string", "default");
userBranch.setStringPref("test.string", "user");
equal(
userBranch.getStringPref("test.string"),
"user",
"the precondition should hold"
);
PrefUtils.clearPref("test.string");
equal(
userBranch.getStringPref("test.string"),
"default",
"clearing the user branch should reveal the default value for bools"
);
PrefUtils.clearPref("test.string", { branch: "default" });
equal(
userBranch.getStringPref("test.string"),
"default",
"clearing the default branch shouldn't do anything"
);
});
add_task(function clearPrefInvalidBranch() {
Assert.throws(
() => PrefUtils.clearPref("test.pref", { branch: "invalid" }),
PrefUtils.UnexpectedPreferenceBranch
);
});