mediawiki-skins-MinervaNeue/resources/skins.minerva.scripts/AB.js
jdlrobson 72df451bd3 Embrace packageFiles
Help with readability by using module.exports and require rather than the MobileFrontend
provided mw.mobileFrontend module manager (and avoid adopting webpack at this time)

Replace usages of mw.mobileFrontend.require with local require and module.exports
(compatible with RL or Node implementation)

Changes:
* Notifications modules are merged into skins.minerva.scripts and initialised
via a client side check.
* new file overlayManager for exporting an overlayManager singleton
rather than being hidden inside resources/skins.minerva.scripts/init.js
* All M.define/M.requires swapped out for require where possible
The `define` method is now forbidden in the repo.

Bug: T212944
Change-Id: I44790dd3fc6fe42bb502d79c39c4081c223bf2b1
2019-07-16 18:04:10 +00:00

78 lines
2.3 KiB
JavaScript

/*
* Bucketing wrapper for creating AB-tests.
*
* 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.
*/
( function ( M, mwExperiments ) {
var bucket = {
UNSAMPLED: 'unsampled', // Old treatment: not sampled and not instrumented.
CONTROL: 'control', // Old treatment: sampled and instrumented.
TREATMENT: 'treatment' // New treatment: sampled and instrumented.
};
/**
* Buckets users based on params and exposes an `isSampled` and `getBucket` method.
* @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.
* @constructor
*/
function AB( config ) {
var
testName = config.testName,
samplingRate = config.samplingRate,
sessionId = config.sessionId,
test = {
name: testName,
enabled: !!samplingRate,
buckets: {
unsampled: 1 - samplingRate,
control: samplingRate / 2,
treatment: samplingRate / 2
}
};
/**
* Gets the users AB-test bucket.
*
* 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
* 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.
*
* @return {string} AB-test bucket, `bucket.UNSAMPLED` by default, `bucket.CONTROL` or
* `bucket.TREATMENT` buckets otherwise.
*/
function getBucket() {
return mwExperiments.getBucket( test, sessionId );
}
function isControl() {
return getBucket() === bucket.CONTROL;
}
function isTreatment() {
return getBucket() === bucket.TREATMENT;
}
/**
* Checks whether or not a user is in the AB-test,
* @return {boolean}
*/
function isSampled() {
return getBucket() !== bucket.UNSAMPLED; // I.e., `isControl() || isTreatment()`
}
return {
isControl: isControl,
isTreatment: isTreatment,
isSampled: isSampled
};
}
module.exports = AB;
}( mw.mobileFrontend, mw.experiments ) );