gitlab-org--gitlab-foss/spec/frontend/experimentation/utils_spec.js

201 lines
7 KiB
JavaScript

import { stubExperiments } from 'helpers/experimentation_helper';
import {
DEFAULT_VARIANT,
CANDIDATE_VARIANT,
TRACKING_CONTEXT_SCHEMA,
} from '~/experimentation/constants';
import * as experimentUtils from '~/experimentation/utils';
describe('experiment Utilities', () => {
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;
});
describe('getExperimentData', () => {
const ABC_DATA = '_abc_data_';
const ABC_DATA2 = '_updated_abc_data_';
const DEF_DATA = '_def_data_';
describe.each`
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 };
});
it(`returns ${output}`, () => {
expect(experimentUtils.getExperimentData(...input)).toEqual(output);
});
});
});
describe('getAllExperimentContexts', () => {
const schema = TRACKING_CONTEXT_SCHEMA;
it('collects all of the experiment contexts into a single array', () => {
const experiments = { [ABC_KEY]: 'candidate', [DEF_KEY]: 'control', ghi: 'blue' };
stubExperiments(experiments);
expect(experimentUtils.getAllExperimentContexts()).toEqual(
Object.entries(experiments).map(([experiment, variant]) => ({
schema,
data: { experiment, variant },
})),
);
});
it('returns an empty array if there are no experiments', () => {
expect(experimentUtils.getAllExperimentContexts()).toEqual([]);
});
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', excluded: false },
};
expect(experimentUtils.getAllExperimentContexts()).toEqual([
{ schema, data: { experiment: 'my_experiment', variant: 'control' } },
]);
window.gl = origGl;
});
});
describe('isExperimentVariant', () => {
describe.each`
experiment | variant | input | output
${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}
`(
'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);
});
},
);
});
describe('experiment', () => {
const experiment = 'marley';
const useSpy = jest.fn();
const controlSpy = jest.fn();
const trySpy = jest.fn();
const candidateSpy = jest.fn();
const getUpStandUpSpy = jest.fn();
const variants = {
use: useSpy,
try: trySpy,
get_up_stand_up: getUpStandUpSpy,
};
describe('when there is no experiment data', () => {
it('calls the use variant', () => {
experimentUtils.experiment(experiment, variants);
expect(useSpy).toHaveBeenCalled();
});
describe("when 'control' is provided instead of 'use'", () => {
it('calls the control variant', () => {
experimentUtils.experiment(experiment, { control: controlSpy });
expect(controlSpy).toHaveBeenCalled();
});
});
});
describe('when experiment variant is "control"', () => {
beforeEach(() => {
stubExperiments({ [experiment]: DEFAULT_VARIANT });
});
it('calls the use variant', () => {
experimentUtils.experiment(experiment, variants);
expect(useSpy).toHaveBeenCalled();
});
describe("when 'control' is provided instead of 'use'", () => {
it('calls the control variant', () => {
experimentUtils.experiment(experiment, { control: controlSpy });
expect(controlSpy).toHaveBeenCalled();
});
});
});
describe('when experiment variant is "candidate"', () => {
beforeEach(() => {
stubExperiments({ [experiment]: CANDIDATE_VARIANT });
});
it('calls the try variant', () => {
experimentUtils.experiment(experiment, variants);
expect(trySpy).toHaveBeenCalled();
});
describe("when 'candidate' is provided instead of 'try'", () => {
it('calls the candidate variant', () => {
experimentUtils.experiment(experiment, { candidate: candidateSpy });
expect(candidateSpy).toHaveBeenCalled();
});
});
});
describe('when experiment variant is "get_up_stand_up"', () => {
beforeEach(() => {
stubExperiments({ [experiment]: 'get_up_stand_up' });
});
it('calls the get-up-stand-up variant', () => {
experimentUtils.experiment(experiment, variants);
expect(getUpStandUpSpy).toHaveBeenCalled();
});
});
});
describe('getExperimentVariant', () => {
it.each`
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);
},
);
});
});