2021-11-10 13:12:35 -05:00
|
|
|
import { stubExperiments } from 'helpers/experimentation_helper';
|
2021-04-23 08:09:52 -04:00
|
|
|
import {
|
|
|
|
DEFAULT_VARIANT,
|
|
|
|
CANDIDATE_VARIANT,
|
|
|
|
TRACKING_CONTEXT_SCHEMA,
|
|
|
|
} from '~/experimentation/constants';
|
2021-03-10 10:09:11 -05:00
|
|
|
import * as experimentUtils from '~/experimentation/utils';
|
|
|
|
|
|
|
|
describe('experiment Utilities', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
const ABC_KEY = 'abc';
|
|
|
|
const DEF_KEY = 'def';
|
|
|
|
|
|
|
|
let origGon;
|
|
|
|
let origGl;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
origGon = window.gon;
|
|
|
|
origGl = window.gl;
|
|
|
|
window.gon.experiment = {};
|
|
|
|
window.gl.experiments = {};
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
window.gon = origGon;
|
|
|
|
window.gl = origGl;
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
|
|
|
|
describe('getExperimentData', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
const ABC_DATA = '_abc_data_';
|
|
|
|
const ABC_DATA2 = '_updated_abc_data_';
|
|
|
|
const DEF_DATA = '_def_data_';
|
|
|
|
|
2021-04-02 14:09:20 -04:00
|
|
|
describe.each`
|
2021-11-10 13:12:35 -05:00
|
|
|
gonData | glData | input | output
|
|
|
|
${[ABC_KEY, ABC_DATA]} | ${[]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
|
|
|
|
${[]} | ${[ABC_KEY, ABC_DATA]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
|
|
|
|
${[ABC_KEY, ABC_DATA]} | ${[DEF_KEY, DEF_DATA]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA }}
|
|
|
|
${[ABC_KEY, ABC_DATA]} | ${[DEF_KEY, DEF_DATA]} | ${[DEF_KEY]} | ${{ experiment: DEF_KEY, variant: DEF_DATA }}
|
|
|
|
${[ABC_KEY, ABC_DATA]} | ${[ABC_KEY, ABC_DATA2]} | ${[ABC_KEY]} | ${{ experiment: ABC_KEY, variant: ABC_DATA2 }}
|
|
|
|
${[]} | ${[]} | ${[ABC_KEY]} | ${undefined}
|
|
|
|
`('with input=$input, gon=$gonData, & gl=$glData', ({ gonData, glData, input, output }) => {
|
|
|
|
beforeEach(() => {
|
|
|
|
const [gonKey, gonVariant] = gonData;
|
|
|
|
const [glKey, glVariant] = glData;
|
|
|
|
|
|
|
|
if (gonKey) window.gon.experiment[gonKey] = { experiment: gonKey, variant: gonVariant };
|
|
|
|
if (glKey) window.gl.experiments[glKey] = { experiment: glKey, variant: glVariant };
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
|
2021-04-02 14:09:20 -04:00
|
|
|
it(`returns ${output}`, () => {
|
|
|
|
expect(experimentUtils.getExperimentData(...input)).toEqual(output);
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
});
|
2021-11-18 07:13:46 -05:00
|
|
|
|
|
|
|
it('only collects the data properties which are supported by the schema', () => {
|
|
|
|
origGl = window.gl;
|
|
|
|
window.gl.experiments = {
|
|
|
|
my_experiment: {
|
|
|
|
experiment: 'my_experiment',
|
|
|
|
variant: 'control',
|
|
|
|
key: 'randomization-unit-key',
|
|
|
|
migration_keys: 'migration_keys object',
|
|
|
|
excluded: false,
|
|
|
|
other: 'foobar',
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
expect(experimentUtils.getExperimentData('my_experiment')).toEqual({
|
|
|
|
experiment: 'my_experiment',
|
|
|
|
variant: 'control',
|
|
|
|
key: 'randomization-unit-key',
|
|
|
|
migration_keys: 'migration_keys object',
|
|
|
|
});
|
|
|
|
|
|
|
|
window.gl = origGl;
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
});
|
|
|
|
|
2021-08-31 08:11:07 -04:00
|
|
|
describe('getAllExperimentContexts', () => {
|
|
|
|
const schema = TRACKING_CONTEXT_SCHEMA;
|
|
|
|
|
|
|
|
it('collects all of the experiment contexts into a single array', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
const experiments = { [ABC_KEY]: 'candidate', [DEF_KEY]: 'control', ghi: 'blue' };
|
|
|
|
|
|
|
|
stubExperiments(experiments);
|
2021-08-31 08:11:07 -04:00
|
|
|
|
|
|
|
expect(experimentUtils.getAllExperimentContexts()).toEqual(
|
2021-11-10 13:12:35 -05:00
|
|
|
Object.entries(experiments).map(([experiment, variant]) => ({
|
|
|
|
schema,
|
|
|
|
data: { experiment, variant },
|
|
|
|
})),
|
2021-08-31 08:11:07 -04:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('returns an empty array if there are no experiments', () => {
|
|
|
|
expect(experimentUtils.getAllExperimentContexts()).toEqual([]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-03-10 10:09:11 -05:00
|
|
|
describe('isExperimentVariant', () => {
|
2021-04-02 14:09:20 -04:00
|
|
|
describe.each`
|
2021-11-18 10:10:19 -05:00
|
|
|
experiment | variant | input | output
|
|
|
|
${ABC_KEY} | ${CANDIDATE_VARIANT} | ${[ABC_KEY]} | ${true}
|
|
|
|
${ABC_KEY} | ${DEFAULT_VARIANT} | ${[ABC_KEY, DEFAULT_VARIANT]} | ${true}
|
|
|
|
${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_variant_name']} | ${true}
|
|
|
|
${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_bogus_name']} | ${false}
|
|
|
|
${ABC_KEY} | ${'_variant_name'} | ${['boguskey', '_variant_name']} | ${false}
|
|
|
|
${undefined} | ${undefined} | ${[ABC_KEY, '_variant_name']} | ${false}
|
2021-11-10 13:12:35 -05:00
|
|
|
`(
|
|
|
|
'with input=$input, experiment=$experiment, variant=$variant',
|
|
|
|
({ experiment, variant, input, output }) => {
|
|
|
|
it(`returns ${output}`, () => {
|
|
|
|
if (experiment) stubExperiments({ [experiment]: variant });
|
|
|
|
|
|
|
|
expect(experimentUtils.isExperimentVariant(...input)).toEqual(output);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
);
|
2021-04-02 14:09:20 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('experiment', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
const experiment = 'marley';
|
2021-11-08 22:42:22 -05:00
|
|
|
const useSpy = jest.fn();
|
2021-04-02 14:09:20 -04:00
|
|
|
const controlSpy = jest.fn();
|
2021-11-08 22:42:22 -05:00
|
|
|
const trySpy = jest.fn();
|
2021-04-02 14:09:20 -04:00
|
|
|
const candidateSpy = jest.fn();
|
|
|
|
const getUpStandUpSpy = jest.fn();
|
|
|
|
|
|
|
|
const variants = {
|
2021-11-08 22:42:22 -05:00
|
|
|
use: useSpy,
|
|
|
|
try: trySpy,
|
2021-04-02 14:09:20 -04:00
|
|
|
get_up_stand_up: getUpStandUpSpy,
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('when there is no experiment data', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
it('calls the use variant', () => {
|
|
|
|
experimentUtils.experiment(experiment, variants);
|
2021-11-08 22:42:22 -05:00
|
|
|
expect(useSpy).toHaveBeenCalled();
|
2021-04-02 14:09:20 -04:00
|
|
|
});
|
2021-11-10 13:12:35 -05:00
|
|
|
|
|
|
|
describe("when 'control' is provided instead of 'use'", () => {
|
|
|
|
it('calls the control variant', () => {
|
|
|
|
experimentUtils.experiment(experiment, { control: controlSpy });
|
|
|
|
expect(controlSpy).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
2021-04-02 14:09:20 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('when experiment variant is "control"', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
beforeEach(() => {
|
|
|
|
stubExperiments({ [experiment]: DEFAULT_VARIANT });
|
|
|
|
});
|
2021-04-02 14:09:20 -04:00
|
|
|
|
2021-11-10 13:12:35 -05:00
|
|
|
it('calls the use variant', () => {
|
|
|
|
experimentUtils.experiment(experiment, variants);
|
2021-11-08 22:42:22 -05:00
|
|
|
expect(useSpy).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when 'control' is provided instead of 'use'", () => {
|
|
|
|
it('calls the control variant', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
experimentUtils.experiment(experiment, { control: controlSpy });
|
2021-11-08 22:42:22 -05:00
|
|
|
expect(controlSpy).toHaveBeenCalled();
|
|
|
|
});
|
2021-04-02 14:09:20 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when experiment variant is "candidate"', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
beforeEach(() => {
|
|
|
|
stubExperiments({ [experiment]: CANDIDATE_VARIANT });
|
|
|
|
});
|
2021-04-02 14:09:20 -04:00
|
|
|
|
2021-11-10 13:12:35 -05:00
|
|
|
it('calls the try variant', () => {
|
|
|
|
experimentUtils.experiment(experiment, variants);
|
2021-11-08 22:42:22 -05:00
|
|
|
expect(trySpy).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when 'candidate' is provided instead of 'try'", () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
it('calls the candidate variant', () => {
|
|
|
|
experimentUtils.experiment(experiment, { candidate: candidateSpy });
|
2021-11-08 22:42:22 -05:00
|
|
|
expect(candidateSpy).toHaveBeenCalled();
|
|
|
|
});
|
2021-04-02 14:09:20 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when experiment variant is "get_up_stand_up"', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
beforeEach(() => {
|
|
|
|
stubExperiments({ [experiment]: 'get_up_stand_up' });
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
|
2021-04-02 14:09:20 -04:00
|
|
|
it('calls the get-up-stand-up variant', () => {
|
2021-11-10 13:12:35 -05:00
|
|
|
experimentUtils.experiment(experiment, variants);
|
2021-04-02 14:09:20 -04:00
|
|
|
expect(getUpStandUpSpy).toHaveBeenCalled();
|
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
});
|
|
|
|
});
|
2021-03-22 17:08:59 -04:00
|
|
|
|
|
|
|
describe('getExperimentVariant', () => {
|
|
|
|
it.each`
|
2021-11-10 13:12:35 -05:00
|
|
|
experiment | variant | input | output
|
|
|
|
${ABC_KEY} | ${DEFAULT_VARIANT} | ${ABC_KEY} | ${DEFAULT_VARIANT}
|
|
|
|
${ABC_KEY} | ${CANDIDATE_VARIANT} | ${ABC_KEY} | ${CANDIDATE_VARIANT}
|
|
|
|
${undefined} | ${undefined} | ${ABC_KEY} | ${DEFAULT_VARIANT}
|
|
|
|
`(
|
|
|
|
'with input=$input, experiment=$experiment, & variant=$variant; returns $output',
|
|
|
|
({ experiment, variant, input, output }) => {
|
|
|
|
stubExperiments({ [experiment]: variant });
|
|
|
|
|
|
|
|
expect(experimentUtils.getExperimentVariant(input)).toEqual(output);
|
|
|
|
},
|
|
|
|
);
|
2021-03-22 17:08:59 -04:00
|
|
|
});
|
2021-03-10 10:09:11 -05:00
|
|
|
});
|