Skip to content
Snippets Groups Projects
Commit de099492 authored by Andrei Oprea's avatar Andrei Oprea
Browse files

Bug 1698795 - Add an option to send exposure once per instance r=k88hudson

parent 992e14cc
No related branches found
No related tags found
No related merge requests found
...@@ -361,6 +361,8 @@ class ExperimentFeature { ...@@ -361,6 +361,8 @@ class ExperimentFeature {
`No manifest entry for ${featureId}. Please add one to toolkit/components/messaging-system/experiments/ExperimentAPI.jsm` `No manifest entry for ${featureId}. Please add one to toolkit/components/messaging-system/experiments/ExperimentAPI.jsm`
); );
} }
// Prevent the instance from sending multiple exposure events
this._sendExposureEventOnce = true;
this._onRemoteReady = null; this._onRemoteReady = null;
this._waitForRemote = new Promise( this._waitForRemote = new Promise(
resolve => (this._onRemoteReady = resolve) resolve => (this._onRemoteReady = resolve)
...@@ -458,9 +460,14 @@ class ExperimentFeature { ...@@ -458,9 +460,14 @@ class ExperimentFeature {
isEnabled({ sendExposureEvent, defaultValue = null } = {}) { isEnabled({ sendExposureEvent, defaultValue = null } = {}) {
const branch = ExperimentAPI.activateBranch({ const branch = ExperimentAPI.activateBranch({
featureId: this.featureId, featureId: this.featureId,
sendExposureEvent, sendExposureEvent: sendExposureEvent && this._sendExposureEventOnce,
}); });
// Prevent future exposure events if user is enrolled in an experiment
if (branch && sendExposureEvent) {
this._sendExposureEventOnce = false;
}
// First, try to return an experiment value if it exists. // First, try to return an experiment value if it exists.
if (isBooleanValueDefined(branch?.feature.enabled)) { if (isBooleanValueDefined(branch?.feature.enabled)) {
return branch.feature.enabled; return branch.feature.enabled;
...@@ -490,8 +497,14 @@ class ExperimentFeature { ...@@ -490,8 +497,14 @@ class ExperimentFeature {
let userPrefs = this._getUserPrefsValues(); let userPrefs = this._getUserPrefsValues();
const branch = ExperimentAPI.activateBranch({ const branch = ExperimentAPI.activateBranch({
featureId: this.featureId, featureId: this.featureId,
sendExposureEvent, sendExposureEvent: sendExposureEvent && this._sendExposureEventOnce,
}); });
// Prevent future exposure events if user is enrolled in an experiment
if (branch && sendExposureEvent) {
this._sendExposureEventOnce = false;
}
if (branch?.feature?.value) { if (branch?.feature?.value) {
return { ...branch.feature.value, ...userPrefs }; return { ...branch.feature.value, ...userPrefs };
} }
...@@ -516,10 +529,17 @@ class ExperimentFeature { ...@@ -516,10 +529,17 @@ class ExperimentFeature {
} }
recordExposureEvent() { recordExposureEvent() {
ExperimentAPI.activateBranch({ if (this._sendExposureEventOnce) {
featureId: this.featureId, let experimentData = ExperimentAPI.activateBranch({
sendExposureEvent: true, featureId: this.featureId,
}); sendExposureEvent: true,
});
// Exposure only sent if user is enrolled in an experiment
if (experimentData) {
this._sendExposureEventOnce = false;
}
}
} }
onUpdate(callback) { onUpdate(callback) {
......
...@@ -352,3 +352,99 @@ add_task(async function test_record_exposure_event() { ...@@ -352,3 +352,99 @@ add_task(async function test_record_exposure_event() {
sandbox.restore(); sandbox.restore();
}); });
add_task(async function test_record_exposure_event_once() {
const { sandbox, manager } = await setupForExperimentFeature();
const featureInstance = new ExperimentFeature("foo", FAKE_FEATURE_MANIFEST);
const exposureSpy = sandbox.spy(ExperimentAPI, "recordExposureEvent");
sandbox.stub(ExperimentAPI, "_store").get(() => manager.store);
manager.store.addExperiment(
ExperimentFakes.experiment("blah", {
featureIds: ["foo"],
branch: {
slug: "treatment",
feature: {
featureId: "foo",
enabled: false,
value: null,
},
},
})
);
featureInstance.recordExposureEvent();
featureInstance.recordExposureEvent();
featureInstance.recordExposureEvent();
Assert.ok(exposureSpy.calledOnce, "Should emit a single exposure event.");
sandbox.restore();
});
add_task(async function test_prevent_double_exposure_getValue() {
const { sandbox, manager } = await setupForExperimentFeature();
const featureInstance = new ExperimentFeature("foo", FAKE_FEATURE_MANIFEST);
const exposureSpy = sandbox.spy(ExperimentAPI, "recordExposureEvent");
sandbox.stub(ExperimentAPI, "_store").get(() => manager.store);
manager.store.addExperiment(
ExperimentFakes.experiment("blah", {
featureIds: ["foo"],
branch: {
slug: "treatment",
feature: {
featureId: "foo",
enabled: false,
value: null,
},
},
})
);
featureInstance.getValue({ sendExposureEvent: true });
featureInstance.getValue({ sendExposureEvent: true });
featureInstance.getValue({ sendExposureEvent: true });
Assert.ok(
exposureSpy.calledOnce,
"Should emit a single exposure event (getValue)."
);
sandbox.restore();
});
add_task(async function test_prevent_double_exposure_isEnabled() {
const { sandbox, manager } = await setupForExperimentFeature();
const featureInstance = new ExperimentFeature("foo", FAKE_FEATURE_MANIFEST);
const exposureSpy = sandbox.spy(ExperimentAPI, "recordExposureEvent");
sandbox.stub(ExperimentAPI, "_store").get(() => manager.store);
manager.store.addExperiment(
ExperimentFakes.experiment("blah", {
featureIds: ["foo"],
branch: {
slug: "treatment",
feature: {
featureId: "foo",
enabled: false,
value: null,
},
},
})
);
featureInstance.isEnabled({ sendExposureEvent: true });
featureInstance.isEnabled({ sendExposureEvent: true });
featureInstance.isEnabled({ sendExposureEvent: true });
Assert.ok(
exposureSpy.calledOnce,
"Should emit a single exposure event (getValue)."
);
sandbox.restore();
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment