Commit ecc5634f authored by David Pisek's avatar David Pisek Committed by Savas Vedova

Only track sec training urls load once

This change makes sure that the tracking of loading security
training urls only happens once.
parent f32d23cc
......@@ -22,6 +22,8 @@ export const i18n = {
loading: __('Loading'),
};
export const TRAINING_URL_POLLING_INTERVAL = 5000;
export default {
i18n,
TEMP_PROVIDER_LOGOS,
......@@ -61,7 +63,7 @@ export default {
},
securityTrainingUrls: {
query: securityTrainingVulnerabilityQuery,
pollInterval: 5000,
pollInterval: TRAINING_URL_POLLING_INTERVAL,
update({ project }) {
if (!project) {
return [];
......@@ -119,15 +121,7 @@ export default {
return this.supportedIdentifiersExternalIds.length > 0;
},
hasSecurityTrainingUrls() {
const hasSecurityTrainingUrls = this.securityTrainingUrls?.length > 0;
if (hasSecurityTrainingUrls) {
this.track(TRACK_TRAINING_LOADED_ACTION, {
property: this.projectFullPath,
});
}
return hasSecurityTrainingUrls;
return this.securityTrainingUrls?.length > 0;
},
},
watch: {
......@@ -138,6 +132,17 @@ export default {
},
},
},
created() {
const unwatchHasSecurityTrainingUrls = this.$watch('hasSecurityTrainingUrls', (hasUrls) => {
if (hasUrls) {
this.track(TRACK_TRAINING_LOADED_ACTION, {
property: this.projectFullPath,
});
// we only want to track this once, so we immediately unsubscribe after the first track
unwatchHasSecurityTrainingUrls();
}
});
},
methods: {
clickTrainingLink(name) {
this.track(TRACK_CLICK_TRAINING_LINK_ACTION, {
......
......@@ -5,6 +5,7 @@ import { GlLink, GlIcon, GlSkeletonLoader } from '@gitlab/ui';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import VulnerabilityTraining, {
i18n,
TRAINING_URL_POLLING_INTERVAL,
} from 'ee/vulnerabilities/components/vulnerability_training.vue';
import securityTrainingProvidersQuery from '~/security_configuration/graphql/security_training_providers.query.graphql';
import securityTrainingVulnerabilityQuery from '~/security_configuration/graphql/security_training_vulnerability.query.graphql';
......@@ -29,15 +30,6 @@ import { getSecurityTrainingProjectData, testIdentifiers } from './mock_data';
Vue.use(VueApollo);
const createTrainingData = (first = {}, second = {}, urls) =>
getSecurityTrainingProjectData({
urls,
urlOverrides: {
first,
second,
},
});
const projectFullPath = 'namespace/project';
const TEST_TRAINING_PROVIDERS_ALL_DISABLED = getSecurityTrainingProvidersData();
......@@ -45,8 +37,8 @@ const TEST_TRAINING_PROVIDERS_FIRST_ENABLED = getSecurityTrainingProvidersData({
providerOverrides: { first: { isEnabled: true } },
});
const TEST_TRAINING_PROVIDERS_DEFAULT = TEST_TRAINING_PROVIDERS_FIRST_ENABLED;
const TEST_TRAINING_VULNERABILITY_DEFAULT = getSecurityTrainingProjectData();
const TEST_TRAINING_VULNERABILITY_NO_URLS = createTrainingData(null, null, []);
const TEST_TRAINING_URLS_DEFAULT = getSecurityTrainingProjectData();
const TEST_TRAINING_URLS_EMPTY = getSecurityTrainingProjectData({ urls: [] });
describe('VulnerabilityTraining component', () => {
let wrapper;
......@@ -61,8 +53,7 @@ describe('VulnerabilityTraining component', () => {
],
[
securityTrainingVulnerabilityQuery,
projectQueryHandler ||
jest.fn().mockResolvedValue(TEST_TRAINING_VULNERABILITY_DEFAULT.response),
projectQueryHandler || jest.fn().mockResolvedValue(TEST_TRAINING_URLS_DEFAULT.response),
],
]);
};
......@@ -152,9 +143,7 @@ describe('VulnerabilityTraining component', () => {
it('displays message when there are no security training urls', async () => {
createApolloProvider({
projectQueryHandler: jest
.fn()
.mockResolvedValue(TEST_TRAINING_VULNERABILITY_NO_URLS.response),
projectQueryHandler: jest.fn().mockResolvedValue(TEST_TRAINING_URLS_EMPTY.response),
});
createComponent();
await waitForQueryToBeLoaded();
......@@ -179,8 +168,12 @@ describe('VulnerabilityTraining component', () => {
it('displays when there are supported identifiers and some urls are in pending status', async () => {
createApolloProvider({
projectQueryHandler: jest.fn().mockResolvedValue(
createTrainingData({
status: SECURITY_TRAINING_URL_STATUS_PENDING,
getSecurityTrainingProjectData({
urlOverrides: {
first: {
status: SECURITY_TRAINING_URL_STATUS_PENDING,
},
},
}).response,
),
});
......@@ -200,8 +193,8 @@ describe('VulnerabilityTraining component', () => {
apolloQuery = wrapper.vm.$apollo.queries.securityTrainingUrls;
});
it('sets polling at 5000 ms', () => {
expect(apolloQuery.options.pollInterval).toBe(5000);
it(`sets polling at ${TRAINING_URL_POLLING_INTERVAL} ms`, () => {
expect(apolloQuery.options.pollInterval).toBe(TRAINING_URL_POLLING_INTERVAL);
});
it('stops polling when every training url status is completed', async () => {
......@@ -260,9 +253,7 @@ describe('VulnerabilityTraining component', () => {
it('does not display training item if there are no securityTrainingUrls', async () => {
createApolloProvider({
projectQueryHandler: jest
.fn()
.mockResolvedValue(TEST_TRAINING_VULNERABILITY_NO_URLS.response),
projectQueryHandler: jest.fn().mockResolvedValue(TEST_TRAINING_URLS_EMPTY.response),
});
createComponent();
await waitForQueryToBeLoaded();
......@@ -305,20 +296,39 @@ describe('VulnerabilityTraining component', () => {
property: projectFullPath,
});
it('tracks when the training link is loading', async () => {
it('tracks when the training urls are first loaded', async () => {
jest.useFakeTimers();
const projectQueryHandler = jest.fn().mockResolvedValue(
getSecurityTrainingProjectData({
urlOverrides: {
first: {
status: SECURITY_TRAINING_URL_STATUS_PENDING,
},
},
}).response,
);
expect(trackingSpy).not.toHaveBeenCalled();
createApolloProvider({
projectQueryHandler: jest.fn().mockResolvedValue(
createTrainingData({
status: SECURITY_TRAINING_URL_STATUS_PENDING,
}).response,
),
projectQueryHandler,
});
createComponent();
await waitForQueryToBeLoaded();
// after the first loading of the urls, the tracking should be called
expect(trackingSpy).toHaveBeenCalledWith(undefined, TRACK_TRAINING_LOADED_ACTION, {
property: projectFullPath,
});
// fake a poll-cycle
jest.advanceTimersByTime(TRAINING_URL_POLLING_INTERVAL);
await waitForQueryToBeLoaded();
// make sure that we queried twice
expect(projectQueryHandler).toHaveBeenCalledTimes(2);
expect(trackingSpy).toHaveBeenCalledTimes(1);
});
it.each([0, 1])('tracks when training link %s gets clicked', async (index) => {
......
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