"use strict"; const FEATURE_ID = "testfeature1"; // Note: this gets deleted at the end of tests const TEST_PREF_BRANCH = "testfeature1."; const TEST_FEATURE = new ExperimentFeature(FEATURE_ID, { variables: { enabled: { type: "boolean", fallbackPref: `${TEST_PREF_BRANCH}enabled`, }, name: { type: "string", fallbackPref: `${TEST_PREF_BRANCH}name`, }, count: { type: "int", fallbackPref: `${TEST_PREF_BRANCH}count`, }, items: { type: "json", fallbackPref: `${TEST_PREF_BRANCH}items`, }, jsonNoFallback: { type: "json", }, }, }); add_setup(() => { const cleanupFeature = NimbusTestUtils.addTestFeatures(TEST_FEATURE); registerCleanupFunction(() => { cleanupFeature(); }); }); add_task(async function test_ExperimentFeature_getFallbackPrefName() { Assert.equal( TEST_FEATURE.getFallbackPrefName("enabled"), "testfeature1.enabled", "should return the fallback preference name" ); }); add_task( { skip_if: () => !AppConstants.NIGHTLY_BUILD, }, async function test_ExperimentFeature_getVariable_notRegistered() { Assert.throws( () => { TEST_FEATURE.getVariable("non_existant_variable"); }, /Nimbus: Warning - variable "non_existant_variable" is not defined in FeatureManifest\.yaml/, "should throw in automation for variables not defined in the manifest" ); } ); add_task(async function test_ExperimentFeature_getVariable_noFallbackPref() { const { cleanup } = await NimbusTestUtils.setupTest(); Assert.equal( TEST_FEATURE.getVariable("jsonNoFallback"), undefined, "should return undefined if no values are set and no fallback pref is defined" ); await cleanup(); }); add_task(async function test_ExperimentFeature_getVariable_precedence() { const { manager, cleanup } = await NimbusTestUtils.setupTest(); const prefName = TEST_FEATURE.manifest.variables.items.fallbackPref; const rollout = NimbusTestUtils.factories.recipe.withFeatureConfig( `${FEATURE_ID}-rollout`, { branchSlug: "slug", featureId: FEATURE_ID, value: { items: [4, 5, 6] }, }, { isRollout: true } ); Services.prefs.clearUserPref(prefName); Assert.equal( TEST_FEATURE.getVariable("items"), undefined, "should return undefined if the fallback pref is not set" ); // Default pref values Services.prefs.setStringPref(prefName, JSON.stringify([1, 2, 3])); Assert.deepEqual( TEST_FEATURE.getVariable("items"), [1, 2, 3], "should return the default pref value" ); await manager.enroll(rollout, "test"); Assert.deepEqual( TEST_FEATURE.getVariable("items"), [4, 5, 6], "should return the remote default value over the default pref value" ); // Experiment values const doExperimentCleanup = await NimbusTestUtils.enrollWithFeatureConfig( { featureId: FEATURE_ID, value: { items: [7, 8, 9], }, }, { manager } ); Assert.deepEqual( TEST_FEATURE.getVariable("items"), [7, 8, 9], "should return the experiment value over the remote value" ); Services.prefs.deleteBranch(TEST_PREF_BRANCH); doExperimentCleanup(); manager.unenroll(rollout.slug); await cleanup(); }); add_task(async function test_ExperimentFeature_getVariable_partial_values() { const { manager, cleanup } = await NimbusTestUtils.setupTest(); const rollout = NimbusTestUtils.factories.recipe.withFeatureConfig( `${FEATURE_ID}-rollout`, { branchSlug: "slug", featureId: FEATURE_ID, value: { name: "abc" }, }, { isRollout: true } ); // Set up a pref value for .enabled, // a remote value for .name, // an experiment value for .items Services.prefs.setBoolPref( TEST_FEATURE.manifest.variables.enabled.fallbackPref, true ); await manager.enroll(rollout, "test"); const doExperimentCleanup = await NimbusTestUtils.enrollWithFeatureConfig( { featureId: FEATURE_ID, value: {}, }, { manager } ); Assert.equal( TEST_FEATURE.getVariable("enabled"), true, "should skip missing variables from remote defaults" ); Assert.equal( TEST_FEATURE.getVariable("name"), "abc", "should skip missing variables from experiments" ); Services.prefs.getDefaultBranch(null).deleteBranch(TEST_PREF_BRANCH); Services.prefs.deleteBranch(TEST_PREF_BRANCH); doExperimentCleanup(); manager.unenroll(rollout.slug); await cleanup(); }); add_task(async function testGetVariableCoenrolling() { const cleanupFeature = NimbusTestUtils.addTestFeatures( new ExperimentFeature("foo", { allowCoenrollment: true, variables: { bar: { type: "string", }, }, }) ); Assert.throws( () => NimbusFeatures.foo.getVariable("bar"), /Co-enrolling features must use the getAllEnrollments API/ ); cleanupFeature(); });