Commit 2fde44f9 authored by Samantha Ming's avatar Samantha Ming

Add page load tracking for vulnerability details

Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/355479
parent 9f9b9070
...@@ -8,7 +8,10 @@ import { TYPE_VULNERABILITY } from '~/graphql_shared/constants'; ...@@ -8,7 +8,10 @@ import { TYPE_VULNERABILITY } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils'; import { convertToGraphQLId } from '~/graphql_shared/utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { TRACK_CLICK_TRAINING_LINK_ACTION } from '~/security_configuration/constants'; import {
TRACK_CLICK_TRAINING_LINK_ACTION,
TRACK_TRAINING_LOADED_ACTION,
} from '~/security_configuration/constants';
import { TEMP_PROVIDER_LOGOS } from '~/security_configuration/components/constants'; import { TEMP_PROVIDER_LOGOS } from '~/security_configuration/components/constants';
import { SUPPORTED_IDENTIFIER_TYPES, SECURITY_TRAINING_URL_STATUS_COMPLETED } from '../constants'; import { SUPPORTED_IDENTIFIER_TYPES, SECURITY_TRAINING_URL_STATUS_COMPLETED } from '../constants';
...@@ -101,7 +104,13 @@ export default { ...@@ -101,7 +104,13 @@ export default {
); );
}, },
hasSecurityTrainingUrls() { hasSecurityTrainingUrls() {
return this.vulnerability?.securityTrainingUrls?.length > 0; const hasSecurityTrainingUrls = this.vulnerability?.securityTrainingUrls?.length > 0;
if (hasSecurityTrainingUrls) {
this.track(TRACK_TRAINING_LOADED_ACTION, {
property: this.projectFullPath,
});
}
return hasSecurityTrainingUrls;
}, },
securityTrainingUrls() { securityTrainingUrls() {
return this.vulnerability?.securityTrainingUrls; return this.vulnerability?.securityTrainingUrls;
...@@ -116,13 +125,10 @@ export default { ...@@ -116,13 +125,10 @@ export default {
}, },
}, },
methods: { methods: {
clickTrainingLink(name, url) { clickTrainingLink(name) {
this.triggerMetric(TRACK_CLICK_TRAINING_LINK_ACTION, name, url); this.track(TRACK_CLICK_TRAINING_LINK_ACTION, {
},
triggerMetric(action, name, url) {
this.track(action, {
property: url,
label: `vendor_${name}`, label: `vendor_${name}`,
property: this.projectFullPath,
}); });
}, },
}, },
...@@ -149,7 +155,7 @@ export default { ...@@ -149,7 +155,7 @@ export default {
</span> </span>
<span class="gl-font-weight-bold gl-font-base">{{ name }}</span> <span class="gl-font-weight-bold gl-font-base">{{ name }}</span>
</div> </div>
<gl-link :href="url" target="_blank" @click="clickTrainingLink(name, url)"> <gl-link :href="url" target="_blank" @click="clickTrainingLink(name)">
{{ $options.i18n.viewTraining }} {{ $options.i18n.viewTraining }}
<gl-icon class="gl-ml-2" name="external-link" :size="12" /> <gl-icon class="gl-ml-2" name="external-link" :size="12" />
</gl-link> </gl-link>
......
...@@ -13,7 +13,10 @@ import { ...@@ -13,7 +13,10 @@ import {
SUPPORTED_IDENTIFIER_TYPES, SUPPORTED_IDENTIFIER_TYPES,
SECURITY_TRAINING_URL_STATUS_PENDING, SECURITY_TRAINING_URL_STATUS_PENDING,
} from 'ee/vulnerabilities/constants'; } from 'ee/vulnerabilities/constants';
import { TRACK_CLICK_TRAINING_LINK_ACTION } from '~/security_configuration/constants'; import {
TRACK_CLICK_TRAINING_LINK_ACTION,
TRACK_TRAINING_LOADED_ACTION,
} from '~/security_configuration/constants';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { import {
...@@ -40,6 +43,8 @@ const createTrainingData = (first = {}, second = {}, urls) => ...@@ -40,6 +43,8 @@ const createTrainingData = (first = {}, second = {}, urls) =>
}, },
}); });
const projectFullPath = 'namespace/project';
const TEST_TRAINING_PROVIDERS_ALL_DISABLED = getSecurityTrainingProvidersData(); const TEST_TRAINING_PROVIDERS_ALL_DISABLED = getSecurityTrainingProvidersData();
const TEST_TRAINING_PROVIDERS_FIRST_ENABLED = getSecurityTrainingProvidersData({ const TEST_TRAINING_PROVIDERS_FIRST_ENABLED = getSecurityTrainingProvidersData({
providerOverrides: { first: { isEnabled: true } }, providerOverrides: { first: { isEnabled: true } },
...@@ -76,7 +81,7 @@ describe('VulnerabilityTraining component', () => { ...@@ -76,7 +81,7 @@ describe('VulnerabilityTraining component', () => {
slots, slots,
apolloProvider, apolloProvider,
provide: { provide: {
projectFullPath: 'namespace/project', projectFullPath,
glFeatures: { glFeatures: {
secureVulnerabilityTraining, secureVulnerabilityTraining,
}, },
...@@ -297,11 +302,8 @@ describe('VulnerabilityTraining component', () => { ...@@ -297,11 +302,8 @@ describe('VulnerabilityTraining component', () => {
describe('metrics', () => { describe('metrics', () => {
let trackingSpy; let trackingSpy;
beforeEach(async () => { beforeEach(() => {
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
createApolloProvider();
createComponent();
await waitForQueryToBeLoaded();
}); });
afterEach(() => { afterEach(() => {
...@@ -309,11 +311,30 @@ describe('VulnerabilityTraining component', () => { ...@@ -309,11 +311,30 @@ describe('VulnerabilityTraining component', () => {
}); });
const expectedTrackingOptions = (index) => ({ const expectedTrackingOptions = (index) => ({
property: testTrainingUrls[index],
label: `vendor_${testProviderName[index]}`, label: `vendor_${testProviderName[index]}`,
property: projectFullPath,
});
it('tracks when the training link is loading', async () => {
createApolloProvider({
vulnerabilityQueryHandler: jest.fn().mockResolvedValue(
createTrainingData({
status: SECURITY_TRAINING_URL_STATUS_PENDING,
}).response,
),
});
createComponent();
await waitForQueryToBeLoaded();
expect(trackingSpy).toHaveBeenCalledWith(undefined, TRACK_TRAINING_LOADED_ACTION, {
property: projectFullPath,
});
}); });
it.each([0, 1])('tracks when training link %s gets clicked', async (index) => { it.each([0, 1])('tracks when training link %s gets clicked', async (index) => {
createApolloProvider();
createComponent();
await waitForQueryToBeLoaded();
await findTrainingItemLinks().at(index).vm.$emit('click'); await findTrainingItemLinks().at(index).vm.$emit('click');
expect(trackingSpy).toHaveBeenCalledWith( expect(trackingSpy).toHaveBeenCalledWith(
......
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