summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjejacks0n <jjackson@gitlab.com>2019-09-06 12:56:40 -0600
committerjejacks0n <jjackson@gitlab.com>2019-09-06 15:02:44 -0600
commitba550e468cee09fdc80cb74043b9f54446a81a32 (patch)
treedf9d454e9e27301f8aba7dd3bf24f9afcab76cef
parent5e7b3f6285236c7dcfada72635df2f9baf620379 (diff)
downloadgitlab-ce-tracking-performance.tar.gz
Restructures Vue mixin to not be globaltracking-performance
This includes refactors around usage in Vue components and specs.
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue2
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js2
-rw-r--r--app/assets/javascripts/tracking.js85
-rw-r--r--spec/frontend/tracking_spec.js22
-rw-r--r--spec/javascripts/sidebar/assignee_title_spec.js10
-rw-r--r--spec/javascripts/sidebar/subscriptions_spec.js2
7 files changed, 55 insertions, 70 deletions
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
index 3568c66f612..ea5441f31e9 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
@@ -1,8 +1,10 @@
<script>
import { n__ } from '~/locale';
+import Tracking from '~/tracking';
export default {
name: 'AssigneeTitle',
+ mixins: [Tracking.mixin({ label: 'right_sidebar' })],
props: {
loading: {
type: Boolean,
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 6fd14560d04..ea5edb3ce3f 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,5 +1,6 @@
<script>
import { __ } from '~/locale';
+import Tracking from '~/tracking';
import icon from '~/vue_shared/components/icon.vue';
import toggleButton from '~/vue_shared/components/toggle_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
@@ -18,6 +19,7 @@ export default {
icon,
toggleButton,
},
+ mixins: [Tracking.mixin({ label: 'right_sidebar' })],
props: {
loading: {
type: Boolean,
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 5dcf1a3125c..6f8214b18ee 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -8,10 +8,8 @@ import LockIssueSidebar from './components/lock/lock_issue_sidebar.vue';
import sidebarParticipants from './components/participants/sidebar_participants.vue';
import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
import Translate from '../vue_shared/translate';
-import Tracking from '~/tracking';
Vue.use(Translate);
-Vue.use(Tracking, { label: 'right_sidebar' });
function mountAssigneesComponent(mediator) {
const el = document.getElementById('js-vue-sidebar-assignees');
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index f04cfa7432a..e1519d49018 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -18,6 +18,33 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
activityTrackingEnabled: false,
};
+const eventHandler = (e, func, opts = {}) => {
+ const el = e.target.closest('[data-track-event]');
+ const action = el && el.dataset.trackEvent;
+ if (!action) return;
+
+ let value = el.dataset.trackValue || el.value || undefined;
+ if (el.type === 'checkbox' && !el.checked) value = false;
+
+ const data = {
+ label: el.dataset.trackLabel,
+ property: el.dataset.trackProperty,
+ value,
+ context: el.dataset.trackContext,
+ };
+
+ func(opts.category, action + (opts.suffix || ''), _.omit(data, _.isUndefined));
+};
+
+const eventHandlers = (category, func) => {
+ const handler = opts => e => eventHandler(e, func, { ...{ category }, ...opts });
+ const handlers = [];
+ handlers.push({ name: 'click', func: handler() });
+ handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
+ handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
+ return handlers;
+};
+
export default class Tracking {
static trackable() {
return !['1', 'yes'].includes(
@@ -39,58 +66,34 @@ export default class Tracking {
return window.snowplow('trackStructEvent', category, action, label, property, value, contexts);
}
- static install(Vue, defaults = {}) {
- Vue.mixin({
- methods: {
- track(action, data) {
- let category = defaults.category || data.category;
- // eslint-disable-next-line no-underscore-dangle
- category = category || this.$options.name || this.$options._componentTag;
- Tracking.event(category || 'unspecified', action, { ...defaults, ...data });
- },
- },
- });
- }
-
static bindDocument(category = document.body.dataset.page, documentOverride = null) {
const el = documentOverride || document;
if (!this.enabled() || el.trackingBound) return [];
el.trackingBound = true;
- const handlers = this.eventHandlers(category);
+ const handlers = eventHandlers(category, (...args) => this.event(...args));
handlers.forEach(event => el.addEventListener(event.name, event.func));
return handlers;
}
- static eventHandlers(category) {
- const handler = opts => e => this.handleEvent(e, { ...{ category }, ...opts });
- const handlers = [];
- handlers.push({ name: 'click', func: handler() });
- handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
- handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
- return handlers;
- }
-
- static handleEvent(e, opts = {}) {
- const el = e.target.closest('[data-track-event]');
- const action = el && el.dataset.trackEvent;
- if (!action) return;
-
- const data = {
- label: el.dataset.trackLabel,
- property: el.dataset.trackProperty,
- value: this.elementValue(el),
- context: el.dataset.trackContext,
+ static mixin(opts) {
+ return {
+ data() {
+ return {
+ tracking: {
+ // eslint-disable-next-line no-underscore-dangle
+ category: this.$options.name || this.$options._componentTag,
+ },
+ };
+ },
+ methods: {
+ track(action, data) {
+ const category = opts.category || data.category || this.tracking.category;
+ Tracking.event(category || 'unspecified', action, { ...opts, ...this.tracking, ...data });
+ },
+ },
};
-
- this.event(opts.category, action + (opts.suffix || ''), _.omit(data, _.isUndefined));
- }
-
- static elementValue(el) {
- let value = el.dataset.trackValue || el.value || undefined;
- if (el.type === 'checkbox' && !el.checked) value = false;
- return value;
}
}
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index e6eea073dba..8432974b3a5 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -1,5 +1,4 @@
import { setHTMLFixture } from './helpers/fixtures';
-import Vue from 'vue';
import Tracking, { initUserTracking } from '~/tracking';
describe('Tracking', () => {
@@ -109,27 +108,6 @@ describe('Tracking', () => {
});
});
- describe('.install', () => {
- let eventSpy;
-
- Vue.use(Tracking, { category: '_category_', context: { foo: 'bar' } });
-
- beforeEach(() => {
- eventSpy = jest.spyOn(Tracking, 'event');
- });
-
- it('installs a track method', () => {
- const component = new (Vue.extend({}))();
- component.track('_action_', { label: '_label_' });
-
- expect(eventSpy).toHaveBeenCalledWith('_category_', '_action_', {
- category: '_category_', // disregarded within Tracking.event
- label: '_label_',
- context: { foo: 'bar' },
- });
- });
- });
-
describe('tracking interface events', () => {
let eventSpy;
diff --git a/spec/javascripts/sidebar/assignee_title_spec.js b/spec/javascripts/sidebar/assignee_title_spec.js
index 067d40888eb..7ba9d39da68 100644
--- a/spec/javascripts/sidebar/assignee_title_spec.js
+++ b/spec/javascripts/sidebar/assignee_title_spec.js
@@ -1,8 +1,6 @@
import Vue from 'vue';
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title.vue';
-import Tracking, { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
-
-Vue.use(Tracking);
+import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper';
describe('AssigneeTitle component', () => {
let component;
@@ -117,6 +115,10 @@ describe('AssigneeTitle component', () => {
const spy = mockTracking('_category_', component.$el, spyOn);
triggerEvent('.js-sidebar-dropdown-toggle');
- expect(spy).toHaveBeenCalled();
+ expect(spy).toHaveBeenCalledWith('AssigneeTitle', 'click_edit_button', {
+ label: 'right_sidebar',
+ category: 'AssigneeTitle',
+ property: 'assignee',
+ });
});
});
diff --git a/spec/javascripts/sidebar/subscriptions_spec.js b/spec/javascripts/sidebar/subscriptions_spec.js
index c0af4c014ac..a97608d6b8a 100644
--- a/spec/javascripts/sidebar/subscriptions_spec.js
+++ b/spec/javascripts/sidebar/subscriptions_spec.js
@@ -60,7 +60,7 @@ describe('Subscriptions', function() {
expect(vm.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
});
- it('calls trackEvent when toggled', () => {
+ it('tracks the event when toggled', () => {
vm = mountComponent(Subscriptions, { subscribed: true });
const spy = mockTracking('_category_', vm.$el, spyOn);
vm.toggleSubscription();