From 93f710036e91dd54bb1e64b9d2d88d79d28fbb42 Mon Sep 17 00:00:00 2001
From: Doug Stull <dstull@gitlab.com>
Date: Wed, 8 Dec 2021 13:25:45 +0000
Subject: [PATCH] Remove invite members in comment experiment

---
 .../components/invite_members_modal.vue       |  7 ----
 .../components/invite_members_trigger.vue     | 15 -------
 .../javascripts/invite_members/constants.js   |  1 -
 .../components/markdown/toolbar.vue           | 18 ---------
 app/controllers/projects/issues_controller.rb |  9 -----
 .../projects/merge_requests_controller.rb     |  9 -----
 .../experiment/invite_members_in_comment.yml  |  8 ----
 locale/gitlab.pot                             |  3 --
 .../projects/issues_controller_spec.rb        | 26 -------------
 .../merge_requests_controller_spec.rb         | 26 -------------
 .../user_invites_from_a_comment_spec.rb       | 25 ------------
 .../user_invites_from_a_comment_spec.rb       | 25 ------------
 .../components/invite_members_modal_spec.js   | 27 -------------
 .../components/invite_members_trigger_spec.js | 14 -------
 .../components/markdown/toolbar_spec.js       | 39 -------------------
 15 files changed, 252 deletions(-)
 delete mode 100644 config/feature_flags/experiment/invite_members_in_comment.yml
 delete mode 100644 spec/features/issues/user_invites_from_a_comment_spec.rb
 delete mode 100644 spec/features/merge_request/user_invites_from_a_comment_spec.rb

diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 7163d1be7735..91a139a51058 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -20,7 +20,6 @@ import { BV_SHOW_MODAL } from '~/lib/utils/constants';
 import { getParameterValues } from '~/lib/utils/url_utility';
 import { sprintf } from '~/locale';
 import {
-  INVITE_MEMBERS_IN_COMMENT,
   GROUP_FILTERS,
   USERS_FILTER_ALL,
   INVITE_MEMBERS_FOR_TASK,
@@ -254,11 +253,6 @@ export default {
         this.submitInviteMembers();
       }
     },
-    trackInvite() {
-      if (this.source === INVITE_MEMBERS_IN_COMMENT) {
-        this.trackEvent(INVITE_MEMBERS_IN_COMMENT, 'comment_invite_success');
-      }
-    },
     trackinviteMembersForTask() {
       const label = 'selected_tasks_to_be_done';
       const property = this.selectedTasksToBeDone.join(',');
@@ -312,7 +306,6 @@ export default {
 
         promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
       }
-      this.trackInvite();
       this.trackinviteMembersForTask();
 
       Promise.all(promises)
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index bf3250f63a5c..7dd74f8803a8 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -1,6 +1,5 @@
 <script>
 import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
-import ExperimentTracking from '~/experimentation/experiment_tracking';
 import { s__ } from '~/locale';
 import eventHub from '../event_hub';
 import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '../constants';
@@ -32,11 +31,6 @@ export default {
       type: String,
       required: true,
     },
-    trackExperiment: {
-      type: String,
-      required: false,
-      default: undefined,
-    },
     triggerElement: {
       type: String,
       required: false,
@@ -72,9 +66,6 @@ export default {
       return baseAttributes;
     },
   },
-  mounted() {
-    this.trackExperimentOnShow();
-  },
   methods: {
     checkTrigger(targetTriggerElement) {
       return this.triggerElement === targetTriggerElement;
@@ -82,12 +73,6 @@ export default {
     openModal() {
       eventHub.$emit('openModal', { inviteeType: 'members', source: this.triggerSource });
     },
-    trackExperimentOnShow() {
-      if (this.trackExperiment) {
-        const tracking = new ExperimentTracking(this.trackExperiment);
-        tracking.event('comment_invite_shown');
-      }
-    },
   },
   TRIGGER_ELEMENT_BUTTON,
   TRIGGER_ELEMENT_SIDE_NAV,
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 87d2fbc6aac1..ec59b3909fe1 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -2,7 +2,6 @@ import { __, s__ } from '~/locale';
 
 export const SEARCH_DELAY = 200;
 
-export const INVITE_MEMBERS_IN_COMMENT = 'invite_members_in_comment';
 export const INVITE_MEMBERS_FOR_TASK = {
   minimum_access_level: 30,
   name: 'invite_members_for_task',
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 912aa8ce2944..f1c293c87f47 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,18 +1,13 @@
 <script>
 import { GlButton, GlLink, GlLoadingIcon, GlSprintf, GlIcon } from '@gitlab/ui';
-import { isExperimentVariant } from '~/experimentation/utils';
-import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
-import { INVITE_MEMBERS_IN_COMMENT } from '~/invite_members/constants';
 
 export default {
-  inviteMembersInComment: INVITE_MEMBERS_IN_COMMENT,
   components: {
     GlButton,
     GlLink,
     GlLoadingIcon,
     GlSprintf,
     GlIcon,
-    InviteMembersTrigger,
   },
   props: {
     markdownDocsPath: {
@@ -34,9 +29,6 @@ export default {
     hasQuickActionsDocsPath() {
       return this.quickActionsDocsPath !== '';
     },
-    inviteCommentEnabled() {
-      return isExperimentVariant(INVITE_MEMBERS_IN_COMMENT, 'invite_member_link');
-    },
   },
 };
 </script>
@@ -67,16 +59,6 @@ export default {
       </template>
     </div>
     <span v-if="canAttachFile" class="uploading-container">
-      <invite-members-trigger
-        v-if="inviteCommentEnabled"
-        classes="gl-mr-3 gl-vertical-align-text-bottom"
-        :display-text="s__('InviteMember|Invite Member')"
-        icon="assignee"
-        variant="link"
-        :track-experiment="$options.inviteMembersInComment"
-        :trigger-source="$options.inviteMembersInComment"
-        data-track-action="comment_invite_click"
-      />
       <span class="uploading-progress-container hide">
         <gl-icon name="media" />
         <span class="attaching-file-message"></span>
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 345e4434f4da..d2d7ecfab6f6 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -52,15 +52,6 @@ class Projects::IssuesController < Projects::ApplicationController
     push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
     push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
     push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml)
-
-    experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
-      experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
-
-      experiment_instance.use {}
-      experiment_instance.try(:invite_member_link) {}
-
-      experiment_instance.track(:view, property: @project.root_ancestor.id.to_s)
-    end
   end
 
   around_action :allow_gitaly_ref_name_caching, only: [:discussions]
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 3cffa9136d6c..ccc34e2940ec 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -47,15 +47,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
     push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
     push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)
     push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml)
-
-    experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
-      experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
-
-      experiment_instance.use {}
-      experiment_instance.try(:invite_member_link) {}
-
-      experiment_instance.track(:view, property: @project.root_ancestor.id.to_s)
-    end
   end
 
   before_action do
diff --git a/config/feature_flags/experiment/invite_members_in_comment.yml b/config/feature_flags/experiment/invite_members_in_comment.yml
deleted file mode 100644
index 521574ad71be..000000000000
--- a/config/feature_flags/experiment/invite_members_in_comment.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_members_in_comment
-introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51400'
-rollout_issue_url: 'https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/300'
-milestone: '13.10'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 40079e9bdeb8..69d3e5096e31 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -19317,9 +19317,6 @@ msgstr ""
 msgid "InviteMember|Add members to this project and start collaborating with your team."
 msgstr ""
 
-msgid "InviteMember|Invite Member"
-msgstr ""
-
 msgid "InviteMember|Invite Members (optional)"
 msgstr ""
 
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index ce8bbf92cdfc..763c3e43e27c 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -201,32 +201,6 @@
       expect(response).to have_gitlab_http_status(:ok)
       expect(json_response['issue_email_participants']).to contain_exactly({ "email" => participants[0].email }, { "email" => participants[1].email })
     end
-
-    context 'with the invite_members_in_comment experiment', :experiment do
-      context 'when user can invite' do
-        before do
-          stub_experiments(invite_members_in_comment: :invite_member_link)
-          project.add_maintainer(user)
-        end
-
-        it 'assigns the candidate experience and tracks the event' do
-          expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
-            .for(:invite_member_link)
-            .with_context(namespace: project.root_ancestor)
-            .on_next_instance
-
-          get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
-        end
-      end
-
-      context 'when user can not invite' do
-        it 'does not track the event' do
-          expect(experiment(:invite_members_in_comment)).not_to track(:view)
-
-          get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
-        end
-      end
-    end
   end
 
   describe 'GET #new' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index f4a5044c0496..36b6df59ef55 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -42,32 +42,6 @@ def go(extra_params = {})
       get :show, params: params.merge(extra_params)
     end
 
-    context 'with the invite_members_in_comment experiment', :experiment do
-      context 'when user can invite' do
-        before do
-          stub_experiments(invite_members_in_comment: :invite_member_link)
-          project.add_maintainer(user)
-        end
-
-        it 'assigns the candidate experience and tracks the event' do
-          expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
-            .for(:invite_member_link)
-            .with_context(namespace: project.root_ancestor)
-            .on_next_instance
-
-          go
-        end
-      end
-
-      context 'when user can not invite' do
-        it 'does not track the event' do
-          expect(experiment(:invite_members_in_comment)).not_to track(:view)
-
-          go
-        end
-      end
-    end
-
     context 'with view param' do
       before do
         go(view: 'parallel')
diff --git a/spec/features/issues/user_invites_from_a_comment_spec.rb b/spec/features/issues/user_invites_from_a_comment_spec.rb
deleted file mode 100644
index 82061f6ed792..000000000000
--- a/spec/features/issues/user_invites_from_a_comment_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe "User invites from a comment", :js do
-  let_it_be(:project) { create(:project_empty_repo, :public) }
-  let_it_be(:issue) { create(:issue, project: project) }
-  let_it_be(:user) { project.owner }
-
-  before do
-    sign_in(user)
-  end
-
-  it "launches the invite modal from invite link on a comment" do
-    stub_experiments(invite_members_in_comment: :invite_member_link)
-
-    visit project_issue_path(project, issue)
-
-    page.within(".new-note") do
-      click_button 'Invite Member'
-    end
-
-    expect(page).to have_content("You're inviting members to the")
-  end
-end
diff --git a/spec/features/merge_request/user_invites_from_a_comment_spec.rb b/spec/features/merge_request/user_invites_from_a_comment_spec.rb
deleted file mode 100644
index 79865094fd08..000000000000
--- a/spec/features/merge_request/user_invites_from_a_comment_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe "User invites from a comment", :js do
-  let_it_be(:project) { create(:project, :public, :repository) }
-  let_it_be(:merge_request) { create(:merge_request, source_project: project) }
-  let_it_be(:user) { project.owner }
-
-  before do
-    sign_in(user)
-  end
-
-  it "launches the invite modal from invite link on a comment" do
-    stub_experiments(invite_members_in_comment: :invite_member_link)
-
-    visit project_merge_request_path(project, merge_request)
-
-    page.within(".new-note") do
-      click_button 'Invite Member'
-    end
-
-    expect(page).to have_content("You're inviting members to the")
-  end
-end
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index f3cad3fc0668..e190ddf243e6 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -17,7 +17,6 @@ import InviteMembersModal from '~/invite_members/components/invite_members_modal
 import ModalConfetti from '~/invite_members/components/confetti.vue';
 import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
 import {
-  INVITE_MEMBERS_IN_COMMENT,
   INVITE_MEMBERS_FOR_TASK,
   CANCEL_BUTTON_TEXT,
   INVITE_BUTTON_TEXT,
@@ -746,7 +745,6 @@ describe('InviteMembersModal', () => {
           wrapper.vm.$toast = { show: jest.fn() };
           jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
           jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
-          jest.spyOn(wrapper.vm, 'trackInvite');
         });
 
         describe('when triggered from regular mounting', () => {
@@ -864,31 +862,6 @@ describe('InviteMembersModal', () => {
         jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({});
       });
 
-      it('tracks the invite', () => {
-        eventHub.$emit('openModal', { inviteeType: 'members', source: INVITE_MEMBERS_IN_COMMENT });
-
-        clickInviteButton();
-
-        expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
-        expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('comment_invite_success');
-      });
-
-      it('does not track invite for unknown source', () => {
-        eventHub.$emit('openModal', { inviteeType: 'members', source: 'unknown' });
-
-        clickInviteButton();
-
-        expect(ExperimentTracking).not.toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
-      });
-
-      it('does not track invite undefined source', () => {
-        eventHub.$emit('openModal', { inviteeType: 'members' });
-
-        clickInviteButton();
-
-        expect(ExperimentTracking).not.toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
-      });
-
       it('tracks the view for learn_gitlab source', () => {
         eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
 
diff --git a/spec/frontend/invite_members/components/invite_members_trigger_spec.js b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
index 3fce23f854c9..429b6fad24a6 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -1,6 +1,5 @@
 import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
 import { shallowMount } from '@vue/test-utils';
-import ExperimentTracking from '~/experimentation/experiment_tracking';
 import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
 import eventHub from '~/invite_members/event_hub';
 import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '~/invite_members/constants';
@@ -79,19 +78,6 @@ describe.each(triggerItems)('with triggerElement as %s', (triggerItem) => {
   });
 
   describe('tracking', () => {
-    it('tracks on mounting', () => {
-      createComponent({ trackExperiment: '_track_experiment_' });
-
-      expect(ExperimentTracking).toHaveBeenCalledWith('_track_experiment_');
-      expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('comment_invite_shown');
-    });
-
-    it('does not track on mounting', () => {
-      createComponent();
-
-      expect(ExperimentTracking).not.toHaveBeenCalledWith('_track_experiment_');
-    });
-
     it('does not add tracking attributes', () => {
       createComponent();
 
diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
index eddc4033a652..8bff85b0bda3 100644
--- a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
@@ -1,24 +1,17 @@
 import { mount } from '@vue/test-utils';
-import { isExperimentVariant } from '~/experimentation/utils';
-import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
-import { INVITE_MEMBERS_IN_COMMENT } from '~/invite_members/constants';
 import Toolbar from '~/vue_shared/components/markdown/toolbar.vue';
 
-jest.mock('~/experimentation/utils', () => ({ isExperimentVariant: jest.fn() }));
-
 describe('toolbar', () => {
   let wrapper;
 
   const createMountedWrapper = (props = {}) => {
     wrapper = mount(Toolbar, {
       propsData: { markdownDocsPath: '', ...props },
-      stubs: { 'invite-members-trigger': true },
     });
   };
 
   afterEach(() => {
     wrapper.destroy();
-    isExperimentVariant.mockReset();
   });
 
   describe('user can attach file', () => {
@@ -40,36 +33,4 @@ describe('toolbar', () => {
       expect(wrapper.vm.$el.querySelector('.uploading-container')).toBeNull();
     });
   });
-
-  describe('user can invite member', () => {
-    const findInviteLink = () => wrapper.find(InviteMembersTrigger);
-
-    beforeEach(() => {
-      isExperimentVariant.mockReturnValue(true);
-      createMountedWrapper();
-    });
-
-    it('should render the invite members trigger', () => {
-      expect(findInviteLink().exists()).toBe(true);
-    });
-
-    it('should have correct props', () => {
-      expect(findInviteLink().props().displayText).toBe('Invite Member');
-      expect(findInviteLink().props().trackExperiment).toBe(INVITE_MEMBERS_IN_COMMENT);
-      expect(findInviteLink().props().triggerSource).toBe(INVITE_MEMBERS_IN_COMMENT);
-    });
-  });
-
-  describe('user can not invite member', () => {
-    const findInviteLink = () => wrapper.find(InviteMembersTrigger);
-
-    beforeEach(() => {
-      isExperimentVariant.mockReturnValue(false);
-      createMountedWrapper();
-    });
-
-    it('should render the invite members trigger', () => {
-      expect(findInviteLink().exists()).toBe(false);
-    });
-  });
 });
-- 
GitLab