Commit 84b103c1 authored by Savas Vedova's avatar Savas Vedova

Merge branch '333226-move-non-core-tracking-logic-into-specific-files' into 'master'

Split tests for tracking related frontend files

See merge request gitlab-org/gitlab!70340
parents 1f580981 52940961
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData, getAllExperimentContexts } from '~/experimentation/utils';
import Tracking, { initUserTracking, initDefaultTrackers } from '~/tracking';
import getStandardContext from '~/tracking/get_standard_context';
jest.mock('~/experimentation/utils', () => ({
getExperimentData: jest.fn(),
getAllExperimentContexts: jest.fn(),
}));
describe('Tracking', () => {
let standardContext;
let snowplowSpy;
let bindDocumentSpy;
let trackLoadEventsSpy;
let enableFormTracking;
let setAnonymousUrlsSpy;
beforeAll(() => {
window.gl = window.gl || {};
window.gl.snowplowStandardContext = {
schema: 'iglu:com.gitlab/gitlab_standard',
data: {
environment: 'testing',
source: 'unknown',
extra: {},
},
};
standardContext = getStandardContext();
});
beforeEach(() => {
getExperimentData.mockReturnValue(undefined);
getAllExperimentContexts.mockReturnValue([]);
window.snowplow = window.snowplow || (() => {});
window.snowplowOptions = {
namespace: 'gl_test',
hostname: 'app.test.com',
cookieDomain: '.test.com',
};
snowplowSpy = jest.spyOn(window, 'snowplow');
});
describe('initUserTracking', () => {
it('calls through to get a new tracker with the expected options', () => {
initUserTracking();
expect(snowplowSpy).toHaveBeenCalledWith('newTracker', 'gl_test', 'app.test.com', {
namespace: 'gl_test',
hostname: 'app.test.com',
cookieDomain: '.test.com',
appId: '',
userFingerprint: false,
respectDoNotTrack: true,
forceSecureTracker: true,
eventMethod: 'post',
contexts: { webPage: true, performanceTiming: true },
formTracking: false,
linkClickTracking: false,
pageUnloadTimer: 10,
formTrackingConfig: {
fields: { allow: [] },
forms: { allow: [] },
},
});
});
});
describe('initDefaultTrackers', () => {
beforeEach(() => {
bindDocumentSpy = jest.spyOn(Tracking, 'bindDocument').mockImplementation(() => null);
trackLoadEventsSpy = jest.spyOn(Tracking, 'trackLoadEvents').mockImplementation(() => null);
enableFormTracking = jest
.spyOn(Tracking, 'enableFormTracking')
.mockImplementation(() => null);
setAnonymousUrlsSpy = jest.spyOn(Tracking, 'setAnonymousUrls').mockImplementation(() => null);
});
it('should activate features based on what has been enabled', () => {
initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30);
expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [standardContext]);
expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking');
expect(snowplowSpy).not.toHaveBeenCalledWith('enableLinkClickTracking');
window.snowplowOptions = {
...window.snowplowOptions,
formTracking: true,
linkClickTracking: true,
formTrackingConfig: { forms: { whitelist: ['foo'] }, fields: { whitelist: ['bar'] } },
};
initDefaultTrackers();
expect(enableFormTracking).toHaveBeenCalledWith(window.snowplowOptions.formTrackingConfig);
expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking');
});
it('binds the document event handling', () => {
initDefaultTrackers();
expect(bindDocumentSpy).toHaveBeenCalled();
});
it('tracks page loaded events', () => {
initDefaultTrackers();
expect(trackLoadEventsSpy).toHaveBeenCalled();
});
it('calls the anonymized URLs method', () => {
initDefaultTrackers();
expect(setAnonymousUrlsSpy).toHaveBeenCalled();
});
describe('when there are experiment contexts', () => {
const experimentContexts = [
{
schema: TRACKING_CONTEXT_SCHEMA,
data: { experiment: 'experiment1', variant: 'control' },
},
{
schema: TRACKING_CONTEXT_SCHEMA,
data: { experiment: 'experiment_two', variant: 'candidate' },
},
];
beforeEach(() => {
getAllExperimentContexts.mockReturnValue(experimentContexts);
});
it('includes those contexts alongside the standard context', () => {
initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [
standardContext,
...experimentContexts,
]);
});
});
});
});
...@@ -8,16 +8,16 @@ import getStandardContext from '~/tracking/get_standard_context'; ...@@ -8,16 +8,16 @@ import getStandardContext from '~/tracking/get_standard_context';
jest.mock('~/experimentation/utils', () => ({ jest.mock('~/experimentation/utils', () => ({
getExperimentData: jest.fn(), getExperimentData: jest.fn(),
getAllExperimentContexts: jest.fn(), getAllExperimentContexts: jest.fn().mockReturnValue([]),
})); }));
const TEST_CATEGORY = 'root:index';
const TEST_ACTION = 'generic';
const TEST_LABEL = 'button';
describe('Tracking', () => { describe('Tracking', () => {
let standardContext; let standardContext;
let snowplowSpy; let snowplowSpy;
let bindDocumentSpy;
let trackLoadEventsSpy;
let enableFormTracking;
let setAnonymousUrlsSpy;
beforeAll(() => { beforeAll(() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
...@@ -30,132 +30,46 @@ describe('Tracking', () => { ...@@ -30,132 +30,46 @@ describe('Tracking', () => {
extra: {}, extra: {},
}, },
}; };
window.snowplowOptions = {
namespace: 'gl_test',
hostname: 'app.test.com',
cookieDomain: '.test.com',
formTracking: true,
linkClickTracking: true,
formTrackingConfig: { forms: { allow: ['foo'] }, fields: { allow: ['bar'] } },
};
standardContext = getStandardContext(); standardContext = getStandardContext();
window.snowplow = window.snowplow || (() => {});
document.body.dataset.page = TEST_CATEGORY;
initUserTracking();
initDefaultTrackers();
}); });
beforeEach(() => { beforeEach(() => {
getExperimentData.mockReturnValue(undefined); getExperimentData.mockReturnValue(undefined);
getAllExperimentContexts.mockReturnValue([]); getAllExperimentContexts.mockReturnValue([]);
window.snowplow = window.snowplow || (() => {});
window.snowplowOptions = {
namespace: '_namespace_',
hostname: 'app.gitfoo.com',
cookieDomain: '.gitfoo.com',
};
snowplowSpy = jest.spyOn(window, 'snowplow'); snowplowSpy = jest.spyOn(window, 'snowplow');
}); });
describe('initUserTracking', () => {
it('calls through to get a new tracker with the expected options', () => {
initUserTracking();
expect(snowplowSpy).toHaveBeenCalledWith('newTracker', '_namespace_', 'app.gitfoo.com', {
namespace: '_namespace_',
hostname: 'app.gitfoo.com',
cookieDomain: '.gitfoo.com',
appId: '',
userFingerprint: false,
respectDoNotTrack: true,
forceSecureTracker: true,
eventMethod: 'post',
contexts: { webPage: true, performanceTiming: true },
formTracking: false,
linkClickTracking: false,
pageUnloadTimer: 10,
formTrackingConfig: {
fields: { allow: [] },
forms: { allow: [] },
},
});
});
});
describe('initDefaultTrackers', () => {
beforeEach(() => {
bindDocumentSpy = jest.spyOn(Tracking, 'bindDocument').mockImplementation(() => null);
trackLoadEventsSpy = jest.spyOn(Tracking, 'trackLoadEvents').mockImplementation(() => null);
enableFormTracking = jest
.spyOn(Tracking, 'enableFormTracking')
.mockImplementation(() => null);
setAnonymousUrlsSpy = jest.spyOn(Tracking, 'setAnonymousUrls').mockImplementation(() => null);
});
it('should activate features based on what has been enabled', () => {
initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30);
expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [standardContext]);
expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking');
expect(snowplowSpy).not.toHaveBeenCalledWith('enableLinkClickTracking');
window.snowplowOptions = {
...window.snowplowOptions,
formTracking: true,
linkClickTracking: true,
formTrackingConfig: { forms: { whitelist: ['foo'] }, fields: { whitelist: ['bar'] } },
};
initDefaultTrackers();
expect(enableFormTracking).toHaveBeenCalledWith(window.snowplowOptions.formTrackingConfig);
expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking');
});
it('binds the document event handling', () => {
initDefaultTrackers();
expect(bindDocumentSpy).toHaveBeenCalled();
});
it('tracks page loaded events', () => {
initDefaultTrackers();
expect(trackLoadEventsSpy).toHaveBeenCalled();
});
it('calls the anonymized URLs method', () => {
initDefaultTrackers();
expect(setAnonymousUrlsSpy).toHaveBeenCalled();
});
describe('when there are experiment contexts', () => {
const experimentContexts = [
{
schema: TRACKING_CONTEXT_SCHEMA,
data: { experiment: 'experiment1', variant: 'control' },
},
{
schema: TRACKING_CONTEXT_SCHEMA,
data: { experiment: 'experiment_two', variant: 'candidate' },
},
];
beforeEach(() => {
getAllExperimentContexts.mockReturnValue(experimentContexts);
});
it('includes those contexts alongside the standard context', () => {
initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('trackPageView', null, [
standardContext,
...experimentContexts,
]);
});
});
});
describe('.event', () => { describe('.event', () => {
afterEach(() => { afterEach(() => {
window.doNotTrack = undefined; window.doNotTrack = undefined;
navigator.doNotTrack = undefined; navigator.doNotTrack = undefined;
navigator.msDoNotTrack = undefined; navigator.msDoNotTrack = undefined;
jest.clearAllMocks();
}); });
it('tracks to snowplow (our current tracking system)', () => { it('tracks to snowplow (our current tracking system)', () => {
Tracking.event('_category_', '_eventName_', { label: '_label_' }); Tracking.event(TEST_CATEGORY, TEST_ACTION, { label: TEST_LABEL });
expect(snowplowSpy).toHaveBeenCalledWith( expect(snowplowSpy).toHaveBeenCalledWith(
'trackStructEvent', 'trackStructEvent',
'_category_', TEST_CATEGORY,
'_eventName_', TEST_ACTION,
'_label_', TEST_LABEL,
undefined, undefined,
undefined, undefined,
[standardContext], [standardContext],
...@@ -165,12 +79,12 @@ describe('Tracking', () => { ...@@ -165,12 +79,12 @@ describe('Tracking', () => {
it('allows adding extra data to the default context', () => { it('allows adding extra data to the default context', () => {
const extra = { foo: 'bar' }; const extra = { foo: 'bar' };
Tracking.event('_category_', '_eventName_', { extra }); Tracking.event(TEST_CATEGORY, TEST_ACTION, { extra });
expect(snowplowSpy).toHaveBeenCalledWith( expect(snowplowSpy).toHaveBeenCalledWith(
'trackStructEvent', 'trackStructEvent',
'_category_', TEST_CATEGORY,
'_eventName_', TEST_ACTION,
undefined, undefined,
undefined, undefined,
undefined, undefined,
...@@ -188,28 +102,28 @@ describe('Tracking', () => { ...@@ -188,28 +102,28 @@ describe('Tracking', () => {
it('skips tracking if snowplow is unavailable', () => { it('skips tracking if snowplow is unavailable', () => {
window.snowplow = false; window.snowplow = false;
Tracking.event('_category_', '_eventName_'); Tracking.event(TEST_CATEGORY, TEST_ACTION);
expect(snowplowSpy).not.toHaveBeenCalled(); expect(snowplowSpy).not.toHaveBeenCalled();
}); });
it('skips tracking if the user does not want to be tracked (general spec)', () => { it('skips tracking if the user does not want to be tracked (general spec)', () => {
window.doNotTrack = '1'; window.doNotTrack = '1';
Tracking.event('_category_', '_eventName_'); Tracking.event(TEST_CATEGORY, TEST_ACTION);
expect(snowplowSpy).not.toHaveBeenCalled(); expect(snowplowSpy).not.toHaveBeenCalled();
}); });
it('skips tracking if the user does not want to be tracked (firefox legacy)', () => { it('skips tracking if the user does not want to be tracked (firefox legacy)', () => {
navigator.doNotTrack = 'yes'; navigator.doNotTrack = 'yes';
Tracking.event('_category_', '_eventName_'); Tracking.event(TEST_CATEGORY, TEST_ACTION);
expect(snowplowSpy).not.toHaveBeenCalled(); expect(snowplowSpy).not.toHaveBeenCalled();
}); });
it('skips tracking if the user does not want to be tracked (IE legacy)', () => { it('skips tracking if the user does not want to be tracked (IE legacy)', () => {
navigator.msDoNotTrack = '1'; navigator.msDoNotTrack = '1';
Tracking.event('_category_', '_eventName_'); Tracking.event(TEST_CATEGORY, TEST_ACTION);
expect(snowplowSpy).not.toHaveBeenCalled(); expect(snowplowSpy).not.toHaveBeenCalled();
}); });
...@@ -237,7 +151,7 @@ describe('Tracking', () => { ...@@ -237,7 +151,7 @@ describe('Tracking', () => {
); );
}); });
it('does not add empty form whitelist rules', () => { it('does not add empty form allow rules', () => {
Tracking.enableFormTracking({ fields: { allow: ['input-class1'] } }); Tracking.enableFormTracking({ fields: { allow: ['input-class1'] } });
expect(snowplowSpy).toHaveBeenCalledWith( expect(snowplowSpy).toHaveBeenCalledWith(
...@@ -287,7 +201,7 @@ describe('Tracking', () => { ...@@ -287,7 +201,7 @@ describe('Tracking', () => {
describe('.flushPendingEvents', () => { describe('.flushPendingEvents', () => {
it('flushes any pending events', () => { it('flushes any pending events', () => {
Tracking.initialized = false; Tracking.initialized = false;
Tracking.event('_category_', '_eventName_', { label: '_label_' }); Tracking.event(TEST_CATEGORY, TEST_ACTION, { label: TEST_LABEL });
expect(snowplowSpy).not.toHaveBeenCalled(); expect(snowplowSpy).not.toHaveBeenCalled();
...@@ -295,9 +209,9 @@ describe('Tracking', () => { ...@@ -295,9 +209,9 @@ describe('Tracking', () => {
expect(snowplowSpy).toHaveBeenCalledWith( expect(snowplowSpy).toHaveBeenCalledWith(
'trackStructEvent', 'trackStructEvent',
'_category_', TEST_CATEGORY,
'_eventName_', TEST_ACTION,
'_label_', TEST_LABEL,
undefined, undefined,
undefined, undefined,
[standardContext], [standardContext],
...@@ -413,15 +327,14 @@ describe('Tracking', () => { ...@@ -413,15 +327,14 @@ describe('Tracking', () => {
beforeEach(() => { beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event'); eventSpy = jest.spyOn(Tracking, 'event');
Tracking.bindDocument('_category_'); // only happens once
setHTMLFixture(` setHTMLFixture(`
<input data-track-action="click_input1" data-track-label="_label_" value=0 /> <input data-track-action="click_input1" data-track-label="button" value="0" />
<input data-track-action="click_input2" data-track-value=0 value=0/> <input data-track-action="click_input2" data-track-value="0" value="0" />
<input type="checkbox" data-track-action="toggle_checkbox" value=1 checked/> <input type="checkbox" data-track-action="toggle_checkbox" value=1 checked />
<input class="dropdown" data-track-action="toggle_dropdown"/> <input class="dropdown" data-track-action="toggle_dropdown"/>
<div data-track-action="nested_event"><span class="nested"></span></div> <div data-track-action="nested_event"><span class="nested"></span></div>
<input data-track-bogus="click_bogusinput" data-track-label="_label_" value="_value_"/> <input data-track-bogus="click_bogusinput" data-track-label="button" value="1" />
<input data-track-action="click_input3" data-track-experiment="example" value="_value_"/> <input data-track-action="click_input3" data-track-experiment="example" value="1" />
<input data-track-action="event_with_extra" data-track-extra='{ "foo": "bar" }' /> <input data-track-action="event_with_extra" data-track-extra='{ "foo": "bar" }' />
<input data-track-action="event_with_invalid_extra" data-track-extra="invalid_json" /> <input data-track-action="event_with_invalid_extra" data-track-extra="invalid_json" />
`); `);
...@@ -430,8 +343,8 @@ describe('Tracking', () => { ...@@ -430,8 +343,8 @@ describe('Tracking', () => {
it(`binds to clicks on elements matching [data-track-action]`, () => { it(`binds to clicks on elements matching [data-track-action]`, () => {
document.querySelector(`[data-track-action="click_input1"]`).click(); document.querySelector(`[data-track-action="click_input1"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input1', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'click_input1', {
label: '_label_', label: TEST_LABEL,
value: '0', value: '0',
}); });
}); });
...@@ -445,7 +358,7 @@ describe('Tracking', () => { ...@@ -445,7 +358,7 @@ describe('Tracking', () => {
it('allows value override with the data-track-value attribute', () => { it('allows value override with the data-track-value attribute', () => {
document.querySelector(`[data-track-action="click_input2"]`).click(); document.querySelector(`[data-track-action="click_input2"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input2', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'click_input2', {
value: '0', value: '0',
}); });
}); });
...@@ -455,13 +368,13 @@ describe('Tracking', () => { ...@@ -455,13 +368,13 @@ describe('Tracking', () => {
checkbox.click(); // unchecking checkbox.click(); // unchecking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'toggle_checkbox', {
value: 0, value: 0,
}); });
checkbox.click(); // checking checkbox.click(); // checking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'toggle_checkbox', {
value: '1', value: '1',
}); });
}); });
...@@ -471,17 +384,17 @@ describe('Tracking', () => { ...@@ -471,17 +384,17 @@ describe('Tracking', () => {
dropdown.dispatchEvent(new Event('show.bs.dropdown', { bubbles: true })); dropdown.dispatchEvent(new Event('show.bs.dropdown', { bubbles: true }));
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_show', {}); expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'toggle_dropdown_show', {});
dropdown.dispatchEvent(new Event('hide.bs.dropdown', { bubbles: true })); dropdown.dispatchEvent(new Event('hide.bs.dropdown', { bubbles: true }));
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_hide', {}); expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'toggle_dropdown_hide', {});
}); });
it('handles nested elements inside an element with tracking', () => { it('handles nested elements inside an element with tracking', () => {
document.querySelector('span.nested').click(); document.querySelector('span.nested').click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'nested_event', {}); expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'nested_event', {});
}); });
it('includes experiment data if linked to an experiment', () => { it('includes experiment data if linked to an experiment', () => {
...@@ -494,8 +407,8 @@ describe('Tracking', () => { ...@@ -494,8 +407,8 @@ describe('Tracking', () => {
document.querySelector(`[data-track-action="click_input3"]`).click(); document.querySelector(`[data-track-action="click_input3"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input3', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'click_input3', {
value: '_value_', value: '1',
context: { schema: TRACKING_CONTEXT_SCHEMA, data: mockExperimentData }, context: { schema: TRACKING_CONTEXT_SCHEMA, data: mockExperimentData },
}); });
}); });
...@@ -503,7 +416,7 @@ describe('Tracking', () => { ...@@ -503,7 +416,7 @@ describe('Tracking', () => {
it('supports extra data as JSON', () => { it('supports extra data as JSON', () => {
document.querySelector(`[data-track-action="event_with_extra"]`).click(); document.querySelector(`[data-track-action="event_with_extra"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'event_with_extra', { expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'event_with_extra', {
extra: { foo: 'bar' }, extra: { foo: 'bar' },
}); });
}); });
...@@ -511,7 +424,7 @@ describe('Tracking', () => { ...@@ -511,7 +424,7 @@ describe('Tracking', () => {
it('ignores extra if provided JSON is invalid', () => { it('ignores extra if provided JSON is invalid', () => {
document.querySelector(`[data-track-action="event_with_invalid_extra"]`).click(); document.querySelector(`[data-track-action="event_with_invalid_extra"]`).click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'event_with_invalid_extra', {}); expect(eventSpy).toHaveBeenCalledWith(TEST_CATEGORY, 'event_with_invalid_extra', {});
}); });
}); });
...@@ -522,20 +435,20 @@ describe('Tracking', () => { ...@@ -522,20 +435,20 @@ describe('Tracking', () => {
eventSpy = jest.spyOn(Tracking, 'event'); eventSpy = jest.spyOn(Tracking, 'event');
setHTMLFixture(` setHTMLFixture(`
<div data-track-action="click_link" data-track-label="all_nested_links"> <div data-track-action="click_link" data-track-label="all_nested_links">
<input data-track-action="render" data-track-label="label1" value=1 data-track-property="_property_"/> <input data-track-action="render" data-track-label="label1" value=1 data-track-property="_property_" />
<span data-track-action="render" data-track-label="label2" data-track-value=1> <span data-track-action="render" data-track-label="label2" data-track-value="1">
<a href="#" id="link">Something</a> <a href="#" id="link">Something</a>
</span> </span>
<input data-track-action="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/> <input data-track-action="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_" />
</div> </div>
`); `);
Tracking.trackLoadEvents('_category_'); // only happens once Tracking.trackLoadEvents(TEST_CATEGORY);
}); });
it(`sends tracking events when [data-track-action="render"] is on an element`, () => { it(`sends tracking events when [data-track-action="render"] is on an element`, () => {
expect(eventSpy.mock.calls).toEqual([ expect(eventSpy.mock.calls).toEqual([
[ [
'_category_', TEST_CATEGORY,
'render', 'render',
{ {
label: 'label1', label: 'label1',
...@@ -544,7 +457,7 @@ describe('Tracking', () => { ...@@ -544,7 +457,7 @@ describe('Tracking', () => {
}, },
], ],
[ [
'_category_', TEST_CATEGORY,
'render', 'render',
{ {
label: 'label2', label: 'label2',
...@@ -571,12 +484,12 @@ describe('Tracking', () => { ...@@ -571,12 +484,12 @@ describe('Tracking', () => {
link.dispatchEvent(new Event(event, { bubbles: true })); link.dispatchEvent(new Event(event, { bubbles: true }));
expect(eventSpy).not.toHaveBeenCalledWith( expect(eventSpy).not.toHaveBeenCalledWith(
'_category_', TEST_CATEGORY,
`render${actionSuffix}`, `render${actionSuffix}`,
expect.any(Object), expect.any(Object),
); );
expect(eventSpy).toHaveBeenCalledWith( expect(eventSpy).toHaveBeenCalledWith(
'_category_', TEST_CATEGORY,
`click_link${actionSuffix}`, `click_link${actionSuffix}`,
expect.objectContaining({ label: 'all_nested_links' }), expect.objectContaining({ label: 'all_nested_links' }),
); );
......
import {
renameKey,
getReferrersCache,
addExperimentContext,
addReferrersCacheEntry,
filterOldReferrersCacheEntries,
} from '~/tracking/utils';
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { REFERRER_TTL, URLS_CACHE_STORAGE_KEY } from '~/tracking/constants';
import { TEST_HOST } from 'helpers/test_constants';
jest.mock('~/experimentation/utils', () => ({
getExperimentData: jest.fn().mockReturnValue({}),
}));
describe('~/tracking/utils', () => {
beforeEach(() => {
window.gl = window.gl || {};
window.gl.snowplowStandardContext = {};
});
describe('addExperimentContext', () => {
const options = {
category: 'root:index',
action: 'generic',
};
it('returns same options if no experiment is provided', () => {
expect(addExperimentContext({ options })).toStrictEqual({ options });
});
it('adds experiment if provided', () => {
const experiment = 'TEST_EXPERIMENT_NAME';
expect(addExperimentContext({ experiment, ...options })).toStrictEqual({
...options,
context: { data: {}, schema: TRACKING_CONTEXT_SCHEMA },
});
});
});
describe('renameKey', () => {
it('renames a given key', () => {
expect(renameKey({ allow: [] }, 'allow', 'permit')).toStrictEqual({ permit: [] });
});
});
describe('referrers cache', () => {
describe('filterOldReferrersCacheEntries', () => {
it('removes entries with old or no timestamp', () => {
const now = Date.now();
const cache = [{ timestamp: now }, { timestamp: now - REFERRER_TTL }, { referrer: '' }];
expect(filterOldReferrersCacheEntries(cache)).toStrictEqual([{ timestamp: now }]);
});
});
describe('getReferrersCache', () => {
beforeEach(() => {
localStorage.removeItem(URLS_CACHE_STORAGE_KEY);
});
it('returns an empty array if cache is not found', () => {
expect(getReferrersCache()).toHaveLength(0);
});
it('returns an empty array if cache is invalid', () => {
localStorage.setItem(URLS_CACHE_STORAGE_KEY, 'Invalid JSON');
expect(getReferrersCache()).toHaveLength(0);
});
it('returns parsed entries if valid', () => {
localStorage.setItem(
URLS_CACHE_STORAGE_KEY,
JSON.stringify([{ referrer: '', timestamp: Date.now() }]),
);
expect(getReferrersCache()).toHaveLength(1);
});
});
describe('addReferrersCacheEntry', () => {
it('unshifts entry and adds timestamp', () => {
const now = Date.now();
addReferrersCacheEntry([{ referrer: '', originalUrl: TEST_HOST, timestamp: now }], {
referrer: TEST_HOST,
});
const cache = getReferrersCache();
expect(cache).toHaveLength(2);
expect(cache[0].referrer).toBe(TEST_HOST);
expect(cache[0].timestamp).toBeDefined();
});
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment