diff --git a/app/assets/javascripts/security_configuration/components/training_provider_list.vue b/app/assets/javascripts/security_configuration/components/training_provider_list.vue index 7a4c0205569a453ffa8f2c994f31b0d188c279bf..dea94503e62c033b1b2d82de118f23685bad7704 100644 --- a/app/assets/javascripts/security_configuration/components/training_provider_list.vue +++ b/app/assets/javascripts/security_configuration/components/training_provider_list.vue @@ -1,7 +1,12 @@ <script> import { GlAlert, GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui'; import * as Sentry from '@sentry/browser'; +import Tracking from '~/tracking'; import { __ } from '~/locale'; +import { + TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, + TRACK_TOGGLE_TRAINING_PROVIDER_LABEL, +} from '~/security_configuration/constants'; import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql'; import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql'; import configureSecurityTrainingProvidersMutation from '../graphql/configure_security_training_providers.mutation.graphql'; @@ -23,6 +28,7 @@ export default { GlLink, GlSkeletonLoader, }, + mixins: [Tracking.mixin()], inject: ['projectFullPath'], apollo: { securityTrainingProviders: { @@ -93,9 +99,14 @@ export default { .filter(({ isEnabled }) => isEnabled) .map(({ id }) => id); - this.storeEnabledProviders(toggledProviders, enabledProviderIds); + const { isEnabled: selectedProviderIsEnabled } = toggledProviders.find( + (provider) => provider.id === selectedProviderId, + ); + + this.trackProviderToggle(selectedProviderId, selectedProviderIsEnabled); + this.storeEnabledProviders(enabledProviderIds); }, - async storeEnabledProviders(toggledProviders, enabledProviderIds) { + async storeEnabledProviders(enabledProviderIds) { this.toggleLoading = true; try { @@ -125,6 +136,15 @@ export default { this.toggleLoading = false; } }, + trackProviderToggle(providerId, providerIsEnabled) { + this.track(TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, { + label: TRACK_TOGGLE_TRAINING_PROVIDER_LABEL, + property: providerId, + extra: { + providerIsEnabled, + }, + }); + }, }, i18n, }; diff --git a/app/assets/javascripts/security_configuration/constants.js b/app/assets/javascripts/security_configuration/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..dc76436e91dbcf01a08208ad05ed0e56bff98d26 --- /dev/null +++ b/app/assets/javascripts/security_configuration/constants.js @@ -0,0 +1,2 @@ +export const TRACK_TOGGLE_TRAINING_PROVIDER_ACTION = 'toggle_security_training_provider'; +export const TRACK_TOGGLE_TRAINING_PROVIDER_LABEL = 'update_security_training_provider'; diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js index ef850c33d6e2454423121119047d2e851bacaba4..ea5df9ca550655af9ab6b9bf833a92dac6ed43fc 100644 --- a/spec/frontend/security_configuration/components/training_provider_list_spec.js +++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js @@ -4,6 +4,11 @@ import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; +import { + TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, + TRACK_TOGGLE_TRAINING_PROVIDER_LABEL, +} from '~/security_configuration/constants'; import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue'; import securityTrainingProvidersQuery from '~/security_configuration/graphql/security_training_providers.query.graphql'; import configureSecurityTrainingProvidersMutation from '~/security_configuration/graphql/configure_security_training_providers.mutation.graphql'; @@ -197,6 +202,36 @@ describe('TrainingProviderList component', () => { ); }); }); + + describe('metrics', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + }); + + afterEach(() => { + unmockTracking(); + }); + + it('tracks when a provider gets toggled', () => { + expect(trackingSpy).not.toHaveBeenCalled(); + + toggleFirstProvider(); + + // Note: Ideally we also want to test that the tracking event is called correctly when a + // provider gets disabled, but that's a bit tricky to do with the current implementation + // Once https://gitlab.com/gitlab-org/gitlab/-/issues/348985 and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79492 + // are merged this will be much easer to do and should be tackled then. + expect(trackingSpy).toHaveBeenCalledWith(undefined, TRACK_TOGGLE_TRAINING_PROVIDER_ACTION, { + property: securityTrainingProviders[0].id, + label: TRACK_TOGGLE_TRAINING_PROVIDER_LABEL, + extra: { + providerIsEnabled: true, + }, + }); + }); + }); }); describe('with errors', () => {