Commit b4a35f5a authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'rk/214679-track-client-design-views' into 'master'

Track Client Design Detail View Event

See merge request gitlab-org/gitlab!30516
parents e47f8abd adf5f83e
......@@ -35,6 +35,7 @@ import {
UPDATE_NOTE_ERROR,
designDeletionError,
} from '../../utils/error_messages';
import { trackDesignDetailView } from '../../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
export default {
......@@ -257,8 +258,21 @@ export default {
query: this.$route.query,
});
},
trackEvent() {
trackDesignDetailView(
'issue-design-collection',
this.$route.query.version || this.latestVersionId,
this.isLatestVersion,
);
},
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.trackEvent();
});
},
beforeRouteUpdate(to, from, next) {
this.trackEvent();
this.closeCommentForm();
next();
},
......
import Tracking from '~/tracking';
function assembleDesignPayload(payloadArr) {
return {
value: {
'internal-object-refrerer': payloadArr[0],
'version-number': payloadArr[1],
'current-version': payloadArr[2],
},
};
}
// Tracking Constants
const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
// eslint-disable-next-line import/prefer-default-export
export function trackDesignDetailView(refrerer = '', designVersion = 1, latestVersion = false) {
Tracking.event(DESIGN_TRACKING_PAGE_NAME, 'design_viewed', {
label: 'design_viewed',
...assembleDesignPayload([refrerer, designVersion, latestVersion]),
});
}
import { mount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import VueRouter from 'vue-router';
import App from '~/design_management/components/app.vue';
import Designs from '~/design_management/pages/index.vue';
......@@ -11,74 +12,66 @@ import {
} from '~/design_management/router/constants';
import '~/commons/bootstrap';
jest.mock('mousetrap', () => ({
bind: jest.fn(),
unbind: jest.fn(),
}));
describe('Design management router', () => {
let vm;
let router;
function factory() {
const localVue = createLocalVue();
localVue.use(VueRouter);
function factory(routeArg) {
const localVue = createLocalVue();
localVue.use(VueRouter);
window.gon = { sprite_icons: '' };
window.gon = { sprite_icons: '' };
router = createRouter('/');
const router = createRouter('/');
if (routeArg !== undefined) {
router.push(routeArg);
}
vm = mount(App, {
localVue,
router,
mocks: {
$apollo: {
queries: {
designs: { loading: true },
design: { loading: true },
permissions: { loading: true },
},
return mount(App, {
localVue,
router,
mocks: {
$apollo: {
queries: {
designs: { loading: true },
design: { loading: true },
permissions: { loading: true },
},
},
});
}
beforeEach(() => {
factory();
},
});
}
afterEach(() => {
vm.destroy();
jest.mock('mousetrap', () => ({
bind: jest.fn(),
unbind: jest.fn(),
}));
router.app.$destroy();
describe('Design management router', () => {
afterEach(() => {
window.location.hash = '';
});
describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', pushArg => {
describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', routeArg => {
it('pushes home component', () => {
router.push(pushArg);
const wrapper = factory(routeArg);
expect(vm.find(Designs).exists()).toBe(true);
expect(wrapper.find(Designs).exists()).toBe(true);
});
});
describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', pushArg => {
describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', routeArg => {
it('pushes designs root component', () => {
router.push(pushArg);
const wrapper = factory(routeArg);
expect(vm.find(Designs).exists()).toBe(true);
expect(wrapper.find(Designs).exists()).toBe(true);
});
});
describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])(
'designs detail route',
pushArg => {
routeArg => {
it('pushes designs detail component', () => {
router.push(pushArg);
const wrapper = factory(routeArg);
return vm.vm.$nextTick().then(() => {
const detail = vm.find(DesignDetail);
return nextTick().then(() => {
const detail = wrapper.find(DesignDetail);
expect(detail.exists()).toBe(true);
expect(detail.props('id')).toEqual('1');
});
......
import { mockTracking } from 'helpers/tracking_helper';
import { trackDesignDetailView } from '~/design_management/utils/tracking';
function getTrackingSpy(key) {
return mockTracking(key, undefined, jest.spyOn);
}
describe('Tracking Events', () => {
describe('trackDesignDetailView', () => {
const eventKey = 'projects:issues:design';
const eventName = 'design_viewed';
it('trackDesignDetailView fires a tracking event when called', () => {
const trackingSpy = getTrackingSpy(eventKey);
trackDesignDetailView();
expect(trackingSpy).toHaveBeenCalledWith(
eventKey,
eventName,
expect.objectContaining({
label: eventName,
value: {
'internal-object-refrerer': '',
'version-number': 1,
'current-version': false,
},
}),
);
});
it('trackDesignDetailView allows to customize the value payload', () => {
const trackingSpy = getTrackingSpy(eventKey);
trackDesignDetailView('from-a-test', 100, true);
expect(trackingSpy).toHaveBeenCalledWith(
eventKey,
eventName,
expect.objectContaining({
label: eventName,
value: {
'internal-object-refrerer': 'from-a-test',
'version-number': 100,
'current-version': true,
},
}),
);
});
});
});
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