Commit 23cc2460 authored by Jeremy Jackson's avatar Jeremy Jackson Committed by Mike Greiling

Adds new tracking interface for snowplow

This will ultimately replace the stats.js that
exists in EE.
parent d89d71eb
import $ from 'jquery';
const extractData = (el, opts = {}) => {
const { trackEvent, trackLabel = '', trackProperty = '' } = el.dataset;
let trackValue = el.dataset.trackValue || el.value || '';
if (el.type === 'checkbox' && !el.checked) trackValue = false;
return [
trackEvent + (opts.suffix || ''),
{
label: trackLabel,
property: trackProperty,
value: trackValue,
},
];
};
export default class Tracking {
static enabled() {
return typeof window.snowplow === 'function';
}
static event(category = document.body.dataset.page, event = 'generic', data = {}) {
if (!this.enabled()) return false;
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
if (!category) throw new Error('Tracking: no category provided for tracking.');
return window.snowplow(
'trackStructEvent',
category,
event,
Object.assign({}, { label: '', property: '', value: '' }, data),
);
}
constructor(category = document.body.dataset.page) {
this.category = category;
}
bind(container = document) {
if (!this.constructor.enabled()) return;
container.querySelectorAll(`[data-track-event]`).forEach(el => {
if (this.customHandlingFor(el)) return;
// jquery is required for select2, so we use it always
// see: https://github.com/select2/select2/issues/4686
$(el).on('click', this.eventHandler(this.category));
});
}
customHandlingFor(el) {
const classes = el.classList;
// bootstrap dropdowns
if (classes.contains('dropdown')) {
$(el).on('show.bs.dropdown', this.eventHandler(this.category, { suffix: '_show' }));
$(el).on('hide.bs.dropdown', this.eventHandler(this.category, { suffix: '_hide' }));
return true;
}
return false;
}
eventHandler(category = null, opts = {}) {
return e => {
this.constructor.event(category || this.category, ...extractData(e.currentTarget, opts));
};
}
}
---
title: Moves snowplow tracking from ee to ce
merge_request: 31160
author: jejacks0n
type: added
This diff is collapsed.
import $ from 'jquery';
import { setHTMLFixture } from './helpers/fixtures';
import Tracking from '~/tracking';
describe('Tracking', () => {
beforeEach(() => {
window.snowplow = window.snowplow || (() => {});
});
describe('.event', () => {
let snowplowSpy = null;
beforeEach(() => {
snowplowSpy = jest.spyOn(window, 'snowplow');
});
it('tracks to snowplow (our current tracking system)', () => {
Tracking.event('_category_', '_eventName_', { label: '_label_' });
expect(snowplowSpy).toHaveBeenCalledWith('trackStructEvent', '_category_', '_eventName_', {
label: '_label_',
property: '',
value: '',
});
});
it('skips tracking if snowplow is unavailable', () => {
window.snowplow = false;
Tracking.event('_category_', '_eventName_');
expect(snowplowSpy).not.toHaveBeenCalled();
});
it('skips tracking if ', () => {
window.snowplow = false;
Tracking.event('_category_', '_eventName_');
expect(snowplowSpy).not.toHaveBeenCalled();
});
});
describe('tracking interface events', () => {
let eventSpy = null;
let subject = null;
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
subject = new Tracking('_category_');
setHTMLFixture(`
<input data-track-event="click_input1" data-track-label="_label_" value="_value_"/>
<input data-track-event="click_input2" data-track-value="_value_override_" value="_value_"/>
<input type="checkbox" data-track-event="toggle_checkbox" value="_value_" checked/>
<input class="dropdown" data-track-event="toggle_dropdown"/>
<div class="js-projects-list-holder"></div>
`);
});
it('binds to clicks on elements matching [data-track-event]', () => {
subject.bind(document);
$('[data-track-event="click_input1"]').click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input1', {
label: '_label_',
value: '_value_',
property: '',
});
});
it('allows value override with the data-track-value attribute', () => {
subject.bind(document);
$('[data-track-event="click_input2"]').click();
expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input2', {
label: '',
value: '_value_override_',
property: '',
});
});
it('handles checkbox values correctly', () => {
subject.bind(document);
const $checkbox = $('[data-track-event="toggle_checkbox"]');
$checkbox.click(); // unchecking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
label: '',
property: '',
value: false,
});
$checkbox.click(); // checking
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
label: '',
property: '',
value: '_value_',
});
});
it('handles bootstrap dropdowns', () => {
new Tracking('_category_').bind(document);
const $dropdown = $('[data-track-event="toggle_dropdown"]');
$dropdown.trigger('show.bs.dropdown'); // showing
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_show', {
label: '',
property: '',
value: '',
});
$dropdown.trigger('hide.bs.dropdown'); // hiding
expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_hide', {
label: '',
property: '',
value: '',
});
});
});
});
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