Commit eb4aab70 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'add-tracking-to-group-invite-banner' into 'master'

Add tracking to group invite banner

Closes #219240 and #229619

See merge request gitlab-org/gitlab!41774
parents e5db4679 48585204
...@@ -2,21 +2,50 @@ ...@@ -2,21 +2,50 @@
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { parseBoolean, setCookie, getCookie } from '~/lib/utils/common_utils'; import { parseBoolean, setCookie, getCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
export default { export default {
components: { components: {
GlBanner, GlBanner,
}, },
inject: ['svgPath', 'inviteMembersPath', 'isDismissedKey'], mixins: [trackingMixin],
inject: ['svgPath', 'inviteMembersPath', 'isDismissedKey', 'trackLabel'],
data() { data() {
return { return {
isDismissed: parseBoolean(getCookie(this.isDismissedKey)), isDismissed: parseBoolean(getCookie(this.isDismissedKey)),
tracking: {
label: this.trackLabel,
},
}; };
}, },
created() {
this.$nextTick(() => {
this.addTrackingAttributesToButton();
});
},
mounted() {
this.trackOnShow();
},
methods: { methods: {
handleClose() { handleClose() {
setCookie(this.isDismissedKey, true); setCookie(this.isDismissedKey, true);
this.isDismissed = true; this.isDismissed = true;
this.track(this.$options.dismissEvent);
},
trackOnShow() {
if (!this.isDismissed) this.track(this.$options.displayEvent);
},
addTrackingAttributesToButton() {
if (this.$refs.banner === undefined) return;
const button = this.$refs.banner.$el.querySelector(`[href='${this.inviteMembersPath}']`);
if (button) {
button.setAttribute('data-track-event', this.$options.buttonClickEvent);
button.setAttribute('data-track-label', this.trackLabel);
}
}, },
}, },
i18n: { i18n: {
...@@ -26,6 +55,9 @@ export default { ...@@ -26,6 +55,9 @@ export default {
), ),
button_text: s__('InviteMembersBanner|Invite your colleagues'), button_text: s__('InviteMembersBanner|Invite your colleagues'),
}, },
displayEvent: 'invite_members_banner_displayed',
buttonClickEvent: 'invite_members_banner_button_clicked',
dismissEvent: 'invite_members_banner_dismissed',
}; };
</script> </script>
......
...@@ -8,7 +8,7 @@ export default function initInviteMembersBanner() { ...@@ -8,7 +8,7 @@ export default function initInviteMembersBanner() {
return false; return false;
} }
const { svgPath, inviteMembersPath, isDismissedKey } = el.dataset; const { svgPath, inviteMembersPath, isDismissedKey, trackLabel } = el.dataset;
return new Vue({ return new Vue({
el, el,
...@@ -16,6 +16,7 @@ export default function initInviteMembersBanner() { ...@@ -16,6 +16,7 @@ export default function initInviteMembersBanner() {
svgPath, svgPath,
inviteMembersPath, inviteMembersPath,
isDismissedKey, isDismissedKey,
trackLabel,
}, },
render: createElement => createElement(InviteMembersBanner), render: createElement => createElement(InviteMembersBanner),
}); });
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
.container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" } .container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" }
.js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/merge_requests.svg'), .js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/merge_requests.svg'),
is_dismissed_key: "invite_#{@group.id}_#{current_user.id}", is_dismissed_key: "invite_#{@group.id}_#{current_user.id}",
track_label: 'invite_members_banner',
invite_members_path: group_group_members_path(@group) } } invite_members_path: group_group_members_path(@group) } }
= content_for :meta_tags do = content_for :meta_tags do
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { setCookie, parseBoolean } from '~/lib/utils/common_utils'; import { setCookie, parseBoolean } from '~/lib/utils/common_utils';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
jest.mock('~/lib/utils/common_utils'); jest.mock('~/lib/utils/common_utils');
...@@ -12,6 +13,7 @@ const body = ...@@ -12,6 +13,7 @@ const body =
const svgPath = '/illustrations/background'; const svgPath = '/illustrations/background';
const inviteMembersPath = 'groups/members'; const inviteMembersPath = 'groups/members';
const buttonText = 'Invite your colleagues'; const buttonText = 'Invite your colleagues';
const trackLabel = 'invite_members_banner';
const createComponent = (stubs = {}) => { const createComponent = (stubs = {}) => {
return shallowMount(InviteMembersBanner, { return shallowMount(InviteMembersBanner, {
...@@ -19,6 +21,7 @@ const createComponent = (stubs = {}) => { ...@@ -19,6 +21,7 @@ const createComponent = (stubs = {}) => {
svgPath, svgPath,
inviteMembersPath, inviteMembersPath,
isDismissedKey, isDismissedKey,
trackLabel,
}, },
stubs, stubs,
}); });
...@@ -26,10 +29,51 @@ const createComponent = (stubs = {}) => { ...@@ -26,10 +29,51 @@ const createComponent = (stubs = {}) => {
describe('InviteMembersBanner', () => { describe('InviteMembersBanner', () => {
let wrapper; let wrapper;
let trackingSpy;
beforeEach(() => {
document.body.dataset.page = 'any:page';
trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
unmockTracking();
});
describe('tracking', () => {
beforeEach(() => {
wrapper = createComponent({ GlBanner });
});
const trackCategory = undefined;
const displayEvent = 'invite_members_banner_displayed';
const buttonClickEvent = 'invite_members_banner_button_clicked';
const dismissEvent = 'invite_members_banner_dismissed';
it('sends the displayEvent when the banner is displayed', () => {
expect(trackingSpy).toHaveBeenCalledWith(trackCategory, displayEvent, {
label: trackLabel,
});
});
it('sets the button attributes for the buttonClickEvent', () => {
const button = wrapper.find(`[href='${wrapper.vm.inviteMembersPath}']`);
expect(button.attributes()).toMatchObject({
'data-track-event': buttonClickEvent,
'data-track-label': trackLabel,
});
});
it('sends the dismissEvent when the banner is dismissed', () => {
wrapper.find(GlBanner).vm.$emit('close');
expect(trackingSpy).toHaveBeenCalledWith(trackCategory, dismissEvent, {
label: trackLabel,
});
});
}); });
describe('rendering', () => { describe('rendering', () => {
......
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