Vector-Local/tests/jest/AB.test.js

230 lines
6.9 KiB
JavaScript

const AB = require( '../../resources/skins.vector.es6/AB.js' );
const NAME_OF_EXPERIMENT = 'name-of-experiment';
const TOKEN = 'token';
const MW_EXPERIMENT_PARAM = {
name: NAME_OF_EXPERIMENT,
enabled: true,
buckets: {
unsampled: 0.5,
control: 0.25,
treatment: 0.25
}
};
// eslint-disable-next-line jsdoc/require-returns
/**
* @param {Object} props
*/
function createInstance( props = {} ) {
const mergedProps = /** @type {AB.WebABTestProps} */ ( Object.assign( {
name: NAME_OF_EXPERIMENT,
buckets: {
unsampled: {
samplingRate: 0.5
},
control: {
samplingRate: 0.25
},
treatment: {
samplingRate: 0.25
}
},
token: TOKEN
}, props ) );
return AB( mergedProps );
}
describe( 'AB.js', () => {
const bucket = 'treatment';
const getBucketMock = jest.fn().mockReturnValue( bucket );
mw.experiments.getBucket = getBucketMock;
afterEach( () => {
document.body.removeAttribute( 'class' );
} );
describe( 'initialization when body tag does not contain bucket', () => {
let /** @type {jest.SpyInstance} */ hookMock;
beforeEach( () => {
hookMock = jest.spyOn( mw, 'hook' );
} );
it( 'sends data to WikimediaEvents when the bucket is part of sample (e.g. control)', () => {
getBucketMock.mockReturnValueOnce( 'control' );
createInstance();
expect( hookMock ).toHaveBeenCalled();
} );
it( 'sends data to WikimediaEvents when the bucket is part of sample (e.g. treatment)', () => {
getBucketMock.mockReturnValueOnce( 'treatment' );
createInstance();
expect( hookMock ).toHaveBeenCalled();
} );
it( 'does not send data to WikimediaEvents when the bucket is unsampled ', () => {
getBucketMock.mockReturnValueOnce( 'unsampled' );
createInstance();
expect( hookMock ).not.toHaveBeenCalled();
} );
} );
describe( 'initialization when body tag contains bucket', () => {
let /** @type {jest.SpyInstance} */ hookMock;
beforeEach( () => {
hookMock = jest.spyOn( mw, 'hook' );
} );
it( 'sends data to WikimediaEvents when the bucket is part of sample (e.g. control)', () => {
document.body.classList.add( 'name-of-experiment-control' );
createInstance();
expect( hookMock ).toHaveBeenCalled();
} );
it( 'sends data to WikimediaEvents when the bucket is part of sample (e.g. treatment)', () => {
document.body.classList.add( 'name-of-experiment-treatment' );
createInstance();
expect( hookMock ).toHaveBeenCalled();
} );
it( 'does not send data to WikimediaEvents when the bucket is unsampled ', () => {
document.body.classList.add( 'name-of-experiment-unsampled' );
createInstance();
expect( hookMock ).not.toHaveBeenCalled();
} );
} );
describe( 'initialization when token is undefined', () => {
it( 'throws an error', () => {
expect( () => {
createInstance( { token: undefined } );
} ).toThrow( 'Tried to call `getBucket`' );
} );
} );
describe( 'getBucket when body tag does not contain AB class', () => {
it( 'calls mw.experiments.getBucket with config data', () => {
const experiment = createInstance();
expect( getBucketMock ).toBeCalledWith( MW_EXPERIMENT_PARAM, TOKEN );
expect( experiment.getBucket() ).toBe( bucket );
} );
} );
describe( 'getBucket when body tag contains AB class that is in the sample', () => {
it( 'returns the bucket on the body tag', () => {
document.body.classList.add( 'name-of-experiment-control' );
const experiment = createInstance();
expect( getBucketMock ).not.toHaveBeenCalled();
expect( experiment.getBucket() ).toBe( 'control' );
} );
} );
describe( 'getBucket when body tag contains AB class that is not in the sample', () => {
it( 'returns the bucket on the body tag', () => {
document.body.classList.add( 'name-of-experiment-unsampled' );
const experiment = createInstance();
expect( getBucketMock ).not.toHaveBeenCalled();
expect( experiment.getBucket() ).toBe( 'unsampled' );
} );
} );
describe( 'isInBucket', () => {
it( 'compares assigned bucket with passed in bucket', () => {
const experiment = createInstance();
expect( experiment.isInBucket( 'treatment' ) ).toBe( true );
} );
} );
describe( 'isInTreatmentBucket when assigned to unsampled bucket (from server)', () => {
it( 'returns false', () => {
document.body.classList.add( 'name-of-experiment-unsampled' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( false );
} );
} );
describe( 'isInTreatmentBucket when assigned to control bucket (from server)', () => {
it( 'returns false', () => {
document.body.classList.add( 'name-of-experiment-control' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( false );
} );
} );
describe( 'isInTreatmentBucket when assigned to treatment bucket (from server)', () => {
it( 'returns true', () => {
document.body.classList.add( 'name-of-experiment-treatment' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( true );
} );
} );
describe( 'isInTreatmentBucket when assigned to unsampled bucket (from client)', () => {
it( 'returns false', () => {
getBucketMock.mockReturnValueOnce( 'unsampled' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( false );
} );
} );
describe( 'isInTreatmentBucket when assigned to control bucket (from client)', () => {
it( 'returns false', () => {
getBucketMock.mockReturnValueOnce( 'control' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( false );
} );
} );
describe( 'isInTreatmentBucket when assigned to treatment bucket (from client)', () => {
it( 'returns true', () => {
getBucketMock.mockReturnValueOnce( 'treatment' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( true );
} );
} );
describe( 'isInTreatmentBucket when assigned to treatment bucket (is case insensitive)', () => {
it( 'returns true', () => {
getBucketMock.mockReturnValueOnce( 'StickyHeaderVisibleTreatment' );
const experiment = createInstance();
expect( experiment.isInTreatmentBucket() ).toBe( true );
} );
} );
describe( 'isInSample when in unsampled bucket', () => {
it( 'returns false', () => {
document.body.classList.add( 'name-of-experiment-unsampled' );
const experiment = createInstance();
expect( experiment.isInSample() ).toBe( false );
} );
} );
describe( 'isInSample when in control bucket', () => {
it( 'returns true', () => {
document.body.classList.add( 'name-of-experiment-control' );
const experiment = createInstance();
expect( experiment.isInSample() ).toBe( true );
} );
} );
describe( 'isInSample when in treatment bucket', () => {
it( 'returns true', () => {
document.body.classList.add( 'name-of-experiment-treatment' );
const experiment = createInstance();
expect( experiment.isInSample() ).toBe( true );
} );
} );
} );