Commit 950608cd authored by Savas Vedova's avatar Savas Vedova

Merge branch '355813-update-page-load-to-use-watcher' into 'master'

Only track sec training urls load once

See merge request gitlab-org/gitlab!82887
parents d3ae929c ecc5634f
......@@ -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({
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 () => {
createApolloProvider({
projectQueryHandler: jest.fn().mockResolvedValue(
createTrainingData({
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,
});
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