2018-05-09 15:14:44 +00:00
|
|
|
/*
|
|
|
|
* Bucketing wrapper for creating AB-tests.
|
|
|
|
*
|
2018-10-26 00:10:06 +00:00
|
|
|
* Given a test name, sampling rate, and session ID, provides a class that buckets a user into
|
|
|
|
* a predefined bucket ("unsampled", "control", or "treatment") and starts an AB-test.
|
2018-05-09 15:14:44 +00:00
|
|
|
*/
|
2019-09-27 18:53:01 +00:00
|
|
|
( function ( mwExperiments ) {
|
2018-08-13 21:54:24 +00:00
|
|
|
var bucket = {
|
2018-10-26 00:10:06 +00:00
|
|
|
UNSAMPLED: 'unsampled', // Old treatment: not sampled and not instrumented.
|
|
|
|
CONTROL: 'control', // Old treatment: sampled and instrumented.
|
|
|
|
TREATMENT: 'treatment' // New treatment: sampled and instrumented.
|
2018-08-13 21:54:24 +00:00
|
|
|
};
|
|
|
|
|
2018-05-09 15:14:44 +00:00
|
|
|
/**
|
2018-10-26 00:10:06 +00:00
|
|
|
* Buckets users based on params and exposes an `isSampled` and `getBucket` method.
|
2020-06-02 21:21:44 +00:00
|
|
|
*
|
2018-10-26 00:10:06 +00:00
|
|
|
* @param {Object} config Configuration object for AB test.
|
|
|
|
* @param {string} config.testName
|
|
|
|
* @param {number} config.samplingRate Sampling rate for the AB-test.
|
|
|
|
* @param {number} config.sessionId Session ID for user bucketing.
|
2018-05-09 15:14:44 +00:00
|
|
|
* @constructor
|
|
|
|
*/
|
2018-07-02 13:15:04 +00:00
|
|
|
function AB( config ) {
|
2018-08-13 21:54:24 +00:00
|
|
|
var
|
2018-07-02 13:15:04 +00:00
|
|
|
testName = config.testName,
|
|
|
|
samplingRate = config.samplingRate,
|
|
|
|
sessionId = config.sessionId,
|
2018-05-09 15:14:44 +00:00
|
|
|
test = {
|
|
|
|
name: testName,
|
|
|
|
enabled: !!samplingRate,
|
|
|
|
buckets: {
|
2018-10-26 00:10:06 +00:00
|
|
|
unsampled: 1 - samplingRate,
|
|
|
|
control: samplingRate / 2,
|
|
|
|
treatment: samplingRate / 2
|
2018-05-09 15:14:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2018-08-13 21:54:24 +00:00
|
|
|
* Gets the users AB-test bucket.
|
|
|
|
*
|
2018-09-13 15:33:20 +00:00
|
|
|
* A boolean instead of an enum is usually a code smell. However, the nature of A/B testing
|
|
|
|
* is to compare an A group's performance to a B group's so a boolean seems natural, even
|
2018-10-26 00:10:06 +00:00
|
|
|
* in the long term, and preferable to showing bucketing encoding ("unsampled", "control",
|
|
|
|
* "treatment") to callers which is necessary if getBucket(). The downside is that now two
|
|
|
|
* functions exist where one would suffice.
|
2018-08-13 21:54:24 +00:00
|
|
|
*
|
2018-10-26 00:10:06 +00:00
|
|
|
* @return {string} AB-test bucket, `bucket.UNSAMPLED` by default, `bucket.CONTROL` or
|
|
|
|
* `bucket.TREATMENT` buckets otherwise.
|
2018-05-09 15:14:44 +00:00
|
|
|
*/
|
|
|
|
function getBucket() {
|
|
|
|
return mwExperiments.getBucket( test, sessionId );
|
|
|
|
}
|
|
|
|
|
2018-10-26 00:10:06 +00:00
|
|
|
function isControl() {
|
|
|
|
return getBucket() === bucket.CONTROL;
|
2018-08-13 21:54:24 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 00:10:06 +00:00
|
|
|
function isTreatment() {
|
|
|
|
return getBucket() === bucket.TREATMENT;
|
2018-08-13 21:54:24 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 15:14:44 +00:00
|
|
|
/**
|
|
|
|
* Checks whether or not a user is in the AB-test,
|
2020-06-02 21:21:44 +00:00
|
|
|
*
|
2018-05-09 15:14:44 +00:00
|
|
|
* @return {boolean}
|
|
|
|
*/
|
2018-10-26 00:10:06 +00:00
|
|
|
function isSampled() {
|
|
|
|
return getBucket() !== bucket.UNSAMPLED; // I.e., `isControl() || isTreatment()`
|
2018-05-09 15:14:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2018-10-26 00:10:06 +00:00
|
|
|
isControl: isControl,
|
|
|
|
isTreatment: isTreatment,
|
|
|
|
isSampled: isSampled
|
2018-05-09 15:14:44 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-07-02 21:10:10 +00:00
|
|
|
module.exports = AB;
|
2019-09-27 18:53:01 +00:00
|
|
|
|
|
|
|
}( mw.experiments ) );
|