diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue index aeeb2654836b05c9c7ae0f597ccc612ae9f78d1d..3bfd5ca6f218078013e04a3a497e149ad3c13c34 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue @@ -158,6 +158,7 @@ export default { this.$el.parentElement.dispatchEvent(new Event('assignYourself')); this.mediator.addSelfReview(); + this.trackEvent('assign_self_as_reviewer_in_mr'); this.saveReviewers(); }, saveReviewers() { diff --git a/config/events/assign_self_as_reviewer_in_mr.yml b/config/events/assign_self_as_reviewer_in_mr.yml new file mode 100644 index 0000000000000000000000000000000000000000..acb52cd97964fc603fd436718fa605b9c162e383 --- /dev/null +++ b/config/events/assign_self_as_reviewer_in_mr.yml @@ -0,0 +1,17 @@ +--- +description: Number of times the "assign self" button is pressed in a Merge Request +internal_events: true +action: assign_self_as_reviewer_in_mr +identifiers: +- project +- namespace +- user +product_group: code_review +product_categories: +- code_review_workflow +milestone: '17.11' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183774 +tiers: +- free +- premium +- ultimate diff --git a/config/metrics/counts_all/count_total_assign_self_as_reviewer_in_mr.yml b/config/metrics/counts_all/count_total_assign_self_as_reviewer_in_mr.yml new file mode 100644 index 0000000000000000000000000000000000000000..a71738eb0bc0b50b689f6bfda29b998467a7bf2e --- /dev/null +++ b/config/metrics/counts_all/count_total_assign_self_as_reviewer_in_mr.yml @@ -0,0 +1,23 @@ +--- +key_path: counts.count_total_assign_self_as_reviewer_in_mr +description: Count of times that the 'assign self' button in the reviewers section is pressed in an MR +product_group: code_review +product_categories: +- code_review_workflow +performance_indicator_type: [] +value_type: number +status: active +milestone: '17.11' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183774 +time_frame: +- 28d +- 7d +- all +data_source: internal_events +data_category: optional +tiers: +- free +- premium +- ultimate +events: +- name: assign_self_as_reviewer_in_mr diff --git a/spec/frontend/sidebar/components/reviewers/sidebar_reviewers_spec.js b/spec/frontend/sidebar/components/reviewers/sidebar_reviewers_spec.js index c541f0357bcc69193790c5092924472f903cacf2..497a3f78eeccc221c96992827d2bb4baf3dfb89b 100644 --- a/spec/frontend/sidebar/components/reviewers/sidebar_reviewers_spec.js +++ b/spec/frontend/sidebar/components/reviewers/sidebar_reviewers_spec.js @@ -3,7 +3,9 @@ import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { useMockInternalEventsTracking } from 'helpers/tracking_internal_events_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import Reviewers from '~/sidebar/components/reviewers/reviewers.vue'; import SidebarReviewers from '~/sidebar/components/reviewers/sidebar_reviewers.vue'; import SidebarService from '~/sidebar/services/sidebar_service'; import SidebarMediator from '~/sidebar/sidebar_mediator'; @@ -13,6 +15,7 @@ import Mock from '../../mock_data'; jest.mock('~/super_sidebar/user_counts_fetch'); +const { bindInternalEventDocument } = useMockInternalEventsTracking(); Vue.use(VueApollo); describe('sidebar reviewers', () => { @@ -20,10 +23,12 @@ describe('sidebar reviewers', () => { let wrapper; let mediator; let axiosMock; + let trackEventSpy; const findAssignButton = () => wrapper.findByTestId('sidebar-reviewers-assign-button'); + const findReviewers = () => wrapper.findComponent(Reviewers); - const createComponent = (props) => { + const createComponent = ({ props, stubs, data } = {}) => { wrapper = shallowMountExtended(SidebarReviewers, { apolloProvider: apolloMock, propsData: { @@ -35,6 +40,11 @@ describe('sidebar reviewers', () => { changing: false, ...props, }, + data() { + return { + ...data, + }; + }, provide: { projectPath: 'projectPath', issuableId: 1, @@ -43,10 +53,13 @@ describe('sidebar reviewers', () => { }, stubs: { ApprovalSummary: true, + ...stubs, }, // Attaching to document is required because this component emits something from the parent element :/ attachTo: document.body, }); + + ({ trackEventSpy } = bindInternalEventDocument(wrapper.element)); }; beforeEach(() => { @@ -69,29 +82,9 @@ describe('sidebar reviewers', () => { ${'shows'} | ${true} | ${true} ${'does not show'} | ${false} | ${false} `('$copy Assign button when canUpdate is $canUpdate', ({ canUpdate, expected }) => { - wrapper = shallowMountExtended(SidebarReviewers, { - apolloProvider: apolloMock, - propsData: { - issuableIid: '1', - issuableId: 1, - mediator, - field: '', - projectPath: 'projectPath', - changing: false, - }, - data() { - return { - issuable: { userPermissions: { adminMergeRequest: canUpdate } }, - }; - }, - provide: { - projectPath: 'projectPath', - issuableId: 1, - issuableIid: 1, - multipleApprovalRulesAvailable: false, - }, - stubs: { - ApprovalSummary: true, + createComponent({ + data: { + issuable: { userPermissions: { adminMergeRequest: canUpdate } }, }, }); @@ -119,15 +112,36 @@ describe('sidebar reviewers', () => { expect(fetchUserCounts).toHaveBeenCalled(); }); - it('calls the mediator when "reviewBySelf" method is called', () => { - createComponent(); + describe('assign yourself', () => { + it('tracks how many times the Reviewers component indicates the user is assigning themself', async () => { + createComponent({ + data: { + issuable: { userPermissions: { adminMergeRequest: true } }, + }, + stubs: { + Reviewers, + }, + }); + + // Wait for Apollo to finish so the sidebar is enabled + await nextTick(); + + const reviewers = findReviewers(); + reviewers.vm.assignSelf(); - expect(mediator.addSelfReview).not.toHaveBeenCalled(); - expect(mediator.store.reviewers.length).toBe(0); + expect(trackEventSpy).toHaveBeenCalledWith('assign_self_as_reviewer_in_mr', {}, undefined); + }); + + it('calls the mediator when "reviewBySelf" method is called', () => { + createComponent(); - wrapper.vm.reviewBySelf(); + expect(mediator.addSelfReview).not.toHaveBeenCalled(); + expect(mediator.store.reviewers.length).toBe(0); - expect(mediator.addSelfReview).toHaveBeenCalled(); - expect(mediator.store.reviewers.length).toBe(1); + wrapper.vm.reviewBySelf(); + + expect(mediator.addSelfReview).toHaveBeenCalled(); + expect(mediator.store.reviewers.length).toBe(1); + }); }); });