@gitlab/application-sdk-browser
Version:
Client side Browser SDK for GitLab Application services
384 lines (327 loc) • 10.4 kB
text/typescript
import {
newTracker,
trackSelfDescribingEvent,
trackPageView,
setUserId,
addGlobalContexts,
disableAnonymousTracking,
enableActivityTracking,
setCustomUrl,
setReferrerUrl,
} from '@snowplow/browser-tracker';
import { doNotTrackEnabled } from '../src/utils/doNotTrack';
import { glClientSDK } from '../src/main';
import {
DEFAULT_PAGEPING_OPTIONS,
DEFAULT_TRACKER_ID,
SCHEMAS,
} from '../src/utils/constants';
import { asMock } from './utils/asMock';
import { trackError } from '@snowplow/browser-plugin-error-tracking';
import { GitLabClientSDKType } from '../src/types';
jest.mock('../src/utils/doNotTrack', () => ({
doNotTrackEnabled: jest.fn(),
}));
jest.mock('@snowplow/browser-tracker', () => ({
...jest.requireActual('@snowplow/browser-tracker'),
newTracker: jest.fn(),
enableActivityTracking: jest.fn(),
trackSelfDescribingEvent: jest.fn(),
trackPageView: jest.fn(),
setUserId: jest.fn(),
addGlobalContexts: jest.fn(),
disableAnonymousTracking: jest.fn(),
setCustomUrl: jest.fn(),
setReferrerUrl: jest.fn(),
}));
jest.mock('@snowplow/browser-plugin-error-tracking', () => ({
...jest.requireActual('@snowplow/browser-plugin-error-tracking'),
trackError: jest.fn(),
}));
describe('GlClient', () => {
let glClient: GitLabClientSDKType;
beforeAll(() => {
Object.defineProperty(document, 'cookie', {
get: jest.fn().mockImplementation(() => {
return '';
}),
set: jest.fn().mockImplementation(() => {}),
});
});
describe.each`
name | func | funcValue
${'DNT'} | ${doNotTrackEnabled} | ${true}
`('with tracking disabled by $name', ({ func, funcValue }) => {
beforeEach(() => {
func.mockReturnValue(funcValue);
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
});
it('basic setup initialises GlClientSDK', () => {
expect(glClient).toBeDefined();
});
describe('track', () => {
it('does not call Snowplow', () => {
glClient.track('testEvent');
expect(trackSelfDescribingEvent).not.toHaveBeenCalled();
});
});
describe('page', () => {
it('does not call Snowplow', () => {
glClient.page();
expect(trackSelfDescribingEvent).not.toHaveBeenCalled();
});
});
describe('identify', () => {
it('does not call Snowplow', () => {
glClient.identify('1');
expect(setUserId).not.toHaveBeenCalled();
expect(addGlobalContexts).not.toHaveBeenCalled();
});
});
});
describe('with tracking enabled', () => {
beforeEach(() => {
asMock(doNotTrackEnabled).mockReturnValue(false);
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
});
it('basic setup initialises GlClientSDK', () => {
expect(glClient).toBeDefined();
});
describe('track', () => {
it('call will send off Snowplow Call', () => {
const eventAttributes = { key: 'value' };
const eventName = 'custom_event';
glClient.track(eventName, eventAttributes);
expect(trackSelfDescribingEvent).toHaveBeenCalledWith({
event: {
schema: SCHEMAS.CUSTOM_EVENT,
data: {
name: eventName,
props: { ...eventAttributes },
},
},
});
});
});
describe('pagePingTracking', () => {
it('call will enableActivityTracking with default options if set to true', () => {
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
pagePingTracking: true,
});
expect(enableActivityTracking).toHaveBeenCalledWith(
DEFAULT_PAGEPING_OPTIONS
);
});
it('call will disableActivityTracking if set to false', () => {
jest.resetAllMocks();
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
pagePingTracking: false,
});
expect(enableActivityTracking).not.toHaveBeenCalled();
});
it('call will enableActivityTracking with custom options if set to an object', () => {
const customOptions = { minimumVisitLength: 10, heartbeatDelay: 5 };
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
pagePingTracking: customOptions,
});
expect(enableActivityTracking).toHaveBeenCalledWith(customOptions);
});
it('call will enableActivityTracking with default options if not passed', () => {
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
expect(enableActivityTracking).toHaveBeenCalledWith(
DEFAULT_PAGEPING_OPTIONS
);
});
});
describe('page', () => {
it('call will send off snowplow page Track Call', () => {
glClient.page();
expect(trackPageView).toHaveBeenCalled();
});
});
describe('identify', () => {
it('call will send off Jitsu id Call', () => {
const USER_ID = '12345';
const USER_ATTRIBUTES = {
userId: USER_ID,
};
glClient.identify(USER_ID, USER_ATTRIBUTES);
expect(setUserId).toHaveBeenCalledWith(USER_ID);
expect(addGlobalContexts).toHaveBeenCalledWith([
{
schema: SCHEMAS.USER_CONTEXT,
data: USER_ATTRIBUTES,
},
]);
});
});
});
describe('with tracking enabled', () => {
beforeEach(() => {
asMock(doNotTrackEnabled).mockReturnValue(false);
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
});
describe('track', () => {
it('call will send off Snowplow Call', () => {
const eventAttributes = { key: 'value' };
const eventName = 'custom_event';
glClient.track(eventName, eventAttributes);
expect(trackSelfDescribingEvent).toHaveBeenCalledWith({
event: {
schema: SCHEMAS.CUSTOM_EVENT,
data: {
name: eventName,
props: { ...eventAttributes },
},
},
});
});
});
describe('addCookieConsent', () => {
it('will call disableAnonymousTracking', () => {
glClient.addCookieConsent();
expect(disableAnonymousTracking).toHaveBeenCalledWith({
stateStorageStrategy: 'cookieAndLocalStorage',
});
});
});
});
describe('stateStorageStrategy', () => {
beforeAll(() => {
asMock(doNotTrackEnabled).mockReturnValue(false);
});
it.each`
hasCookieConsent | value
${true} | ${undefined}
${false} | ${'none'}
`(
'sets stateStorageStrategy as `none` when set to `$hasCookieConsent`',
({ hasCookieConsent, value }) => {
glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
hasCookieConsent,
});
expect(newTracker).toHaveBeenCalledWith(
DEFAULT_TRACKER_ID,
'collector.gitlab.com',
hasCookieConsent
? expect.not.objectContaining({
stateStorageStrategy: value,
})
: expect.objectContaining({
stateStorageStrategy: value,
})
);
}
);
});
});
describe('trackError', () => {
it('should not be called when tracking is disabled', () => {
asMock(doNotTrackEnabled).mockReturnValue(true);
const glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
glClient.trackError({ message: 'Error occured' });
expect(trackError).not.toHaveBeenCalled();
});
it('should not be called when error tracking plugin is disabled', () => {
asMock(doNotTrackEnabled).mockReturnValue(false);
const glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
plugins: {
errorTracking: false,
},
});
glClient.trackError({ message: 'Error occured' });
expect(trackError).not.toHaveBeenCalled();
});
it('should be called when error tracking plugin is enabled and tracking is enabled', () => {
asMock(doNotTrackEnabled).mockReturnValue(false);
const glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
glClient.trackError({ message: 'Error occured' });
expect(trackError).toHaveBeenCalledWith({
message: 'Error occured',
});
});
});
describe('configuration checks', () => {
let spiedWarn: any;
beforeAll(() => {
asMock(doNotTrackEnabled).mockReturnValue(false);
spiedWarn = jest.spyOn(console, 'warn');
spiedWarn.mockImplementation(() => {});
});
afterAll(() => {
spiedWarn.mockRestore();
});
afterEach(() => {
spiedWarn.mockClear();
});
it('creates console warning if no tracking ID was provided', () => {
// @ts-ignore
glClientSDK();
expect(spiedWarn).toHaveBeenCalled();
expect(spiedWarn.mock.calls[0][0]).toContain(
'GitLab: No appId was provided'
);
});
it('creates console warning if no host was provided', () => {
// @ts-ignore
glClientSDK({
appId: '123',
});
expect(spiedWarn).toHaveBeenCalled();
expect(spiedWarn.mock.calls[0][0]).toContain(
'GitLab: No host was provided'
);
});
});
describe('setCustomUrl', () => {
it('should call the setCustomUrl method from Snowplow with the provided URL', () => {
const customUrl = 'https://example.com';
asMock(doNotTrackEnabled).mockReturnValue(false);
const glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
glClient.setCustomUrl(customUrl);
expect(setCustomUrl).toHaveBeenCalledWith(customUrl);
});
});
describe('setReferrerUrl', () => {
it('should call the setReferrerUrl method from Snowplow with the provided URL', () => {
const referrerUrl = 'https://referrer.com';
asMock(doNotTrackEnabled).mockReturnValue(false);
const glClient = glClientSDK({
appId: '123',
host: 'collector.gitlab.com',
});
glClient.setReferrerUrl(referrerUrl);
expect(setReferrerUrl).toHaveBeenCalledWith(referrerUrl);
});
});