From a93571a45876698c2af4893be1efc01dd347195d Mon Sep 17 00:00:00 2001
From: Doug Stull <dstull@gitlab.com>
Date: Wed, 15 Dec 2021 18:00:22 +0000
Subject: [PATCH] Add preview text to invit emails with goto action

---
 app/controllers/invites_controller.rb         |  5 ---
 app/controllers/registrations_controller.rb   |  2 -
 app/helpers/notify_helper.rb                  | 10 -----
 .../notify/member_invited_email.html.haml     | 20 +++++-----
 .../experiment/invite_email_preview_text.yml  |  8 ----
 spec/controllers/invites_controller_spec.rb   | 31 ----------------
 .../registrations_controller_spec.rb          | 37 +------------------
 spec/features/invites_spec.rb                 | 14 -------
 spec/helpers/notify_helper_spec.rb            | 27 --------------
 spec/mailers/notify_spec.rb                   | 25 +------------
 .../mailers/notify_shared_examples.rb         |  6 +++
 11 files changed, 18 insertions(+), 167 deletions(-)
 delete mode 100644 config/feature_flags/experiment/invite_email_preview_text.yml

diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index eb89fe58cc0e9..2a7f2d42e2af9 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -77,10 +77,6 @@ def ensure_member_exists
   def track_invite_join_click
     return unless member && initial_invite_email?
 
-    if params[:experiment_name] == 'invite_email_preview_text'
-      experiment(:invite_email_preview_text, actor: member).track(:join_clicked)
-    end
-
     Gitlab::Tracking.event(self.class.name, 'join_clicked', label: 'invite_email', property: member.id.to_s)
   end
 
@@ -102,7 +98,6 @@ def set_session_invite_params
     session[:invite_email] = member.invite_email
 
     session[:originating_member_id] = member.id if initial_invite_email?
-    session[:invite_email_experiment_name] = params[:experiment_name] if initial_invite_email? && params[:experiment_name]
   end
 
   def initial_invite_email?
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 6dc5cf57a9e90..ed3facd72c541 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -210,8 +210,6 @@ def after_pending_invitations_hook
 
     return unless member
 
-    experiment_name = session.delete(:invite_email_experiment_name)
-    experiment(:invite_email_preview_text, actor: member).track(:accepted) if experiment_name == 'invite_email_preview_text'
     Gitlab::Tracking.event(self.class.name, 'accepted', label: 'invite_email', property: member.id.to_s)
   end
 
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index da42740f99399..c0ba93f4a30ef 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -20,14 +20,4 @@ def invited_to_description(source)
 
     (source.description || default_description).truncate(200, separator: ' ')
   end
-
-  def invited_join_url(token, member)
-    additional_params = { invite_type: Emails::Members::INITIAL_INVITE }
-
-    if experiment(:invite_email_preview_text, actor: member).enabled?
-      additional_params[:experiment_name] = 'invite_email_preview_text'
-    end
-
-    invite_url(token, additional_params)
-  end
 end
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index 1d1f696e1b24b..6d5207510da31 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -6,17 +6,15 @@
   role: member.human_access.downcase }
 - join_text =  s_('InviteEmail|Join now')
 - inviter_name = member.created_by.name if member.created_by
+- join_url = invite_url(@token, invite_type: Emails::Members::INITIAL_INVITE)
 
-- experiment(:invite_email_preview_text, actor: member) do |experiment_instance|
-  - experiment_instance.use {}
-  - experiment_instance.candidate do
-    = content_for :preview_text do
-      %div{ style: "display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;" }
-        - if member.created_by
-          = s_('InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}') % { inviter: inviter_name, project_or_group_name: placeholders[:project_or_group_name] }
-        - else
-          = s_('InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}') % { project_or_group_name: placeholders[:project_or_group_name] }
-      = gmail_goto_action(join_text, invited_join_url(@token, member))
+= content_for :preview_text do
+  %div{ style: "display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;" }
+    - if member.created_by
+      = s_('InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}') % { inviter: inviter_name, project_or_group_name: placeholders[:project_or_group_name] }
+    - else
+      = s_('InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}') % { project_or_group_name: placeholders[:project_or_group_name] }
+  = gmail_goto_action(join_text, join_url)
 
 %tr
   %td.text-content{ colspan: 2 }
@@ -32,7 +30,7 @@
       - else
         = html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
     %p.invite-actions
-      = link_to join_text, invited_join_url(@token, member), class: 'invite-btn-join'
+      = link_to join_text, join_url, class: 'invite-btn-join'
 %tr.border-top
   %td.text-content.mailer-align-left.half-width
     %h4
diff --git a/config/feature_flags/experiment/invite_email_preview_text.yml b/config/feature_flags/experiment/invite_email_preview_text.yml
deleted file mode 100644
index fcb4cda0b1456..0000000000000
--- a/config/feature_flags/experiment/invite_email_preview_text.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_email_preview_text
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67236
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/421
-milestone: '14.2'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index dc1fb0454dfca..c5e693e3489c5 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -97,29 +97,6 @@
         )
       end
 
-      context 'when it is part of the invite_email_preview_text experiment' do
-        let(:extra_params) { { invite_type: 'initial_email', experiment_name: 'invite_email_preview_text' } }
-
-        it 'tracks the initial join click from email' do
-          experiment = double(track: true)
-          allow(controller).to receive(:experiment).with(:invite_email_preview_text, actor: member).and_return(experiment)
-
-          request
-
-          expect(experiment).to have_received(:track).with(:join_clicked)
-        end
-
-        context 'when member does not exist' do
-          let(:raw_invite_token) { '_bogus_token_' }
-
-          it 'does not track the experiment' do
-            expect(controller).not_to receive(:experiment).with(:invite_email_preview_text, actor: member)
-
-            request
-          end
-        end
-      end
-
       context 'when member does not exist' do
         let(:raw_invite_token) { '_bogus_token_' }
 
@@ -145,14 +122,6 @@
           label: 'invite_email'
         )
       end
-
-      context 'when it is not part of our invite email experiment' do
-        it 'does not track via experiment' do
-          expect(controller).not_to receive(:experiment).with(:invite_email_preview_text, actor: member)
-
-          request
-        end
-      end
     end
 
     context 'when not logged in' do
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 9094d23536674..3f7941b345651 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -159,12 +159,11 @@
               let_it_be(:member) { create(:project_member, :invited, invite_email: user_params.dig(:user, :email)) }
 
               let(:originating_member_id) { member.id }
-              let(:extra_session_params) { {} }
               let(:session_params) do
                 {
                   invite_email: user_params.dig(:user, :email),
                   originating_member_id: originating_member_id
-                }.merge extra_session_params
+                }
               end
 
               context 'when member exists from the session key value' do
@@ -193,40 +192,6 @@
                   )
                 end
               end
-
-              context 'with the invite_email_preview_text experiment', :experiment do
-                let(:extra_session_params) { { invite_email_experiment_name: 'invite_email_preview_text' } }
-
-                context 'when member and invite_email_experiment_name exists from the session key value' do
-                  it 'tracks the invite acceptance' do
-                    expect(experiment(:invite_email_preview_text)).to track(:accepted)
-                                                                        .with_context(actor: member)
-                                                                        .on_next_instance
-
-                    subject
-                  end
-                end
-
-                context 'when member does not exist from the session key value' do
-                  let(:originating_member_id) { -1 }
-
-                  it 'does not track invite acceptance' do
-                    expect(experiment(:invite_email_preview_text)).not_to track(:accepted)
-
-                    subject
-                  end
-                end
-
-                context 'when invite_email_experiment_name does not exist from the session key value' do
-                  let(:extra_session_params) { {} }
-
-                  it 'does not track invite acceptance' do
-                    expect(experiment(:invite_email_preview_text)).not_to track(:accepted)
-
-                    subject
-                  end
-                end
-              end
             end
 
             context 'when invite email matches email used on registration' do
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index d2bf35166ac31..9cb9416e7a032 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -226,20 +226,6 @@ def fill_in_welcome_form
           end
         end
 
-        context 'with invite email acceptance for the invite_email_preview_text experiment', :experiment do
-          let(:extra_params) do
-            { invite_type: Emails::Members::INITIAL_INVITE, experiment_name: 'invite_email_preview_text' }
-          end
-
-          it 'tracks the accepted invite' do
-            expect(experiment(:invite_email_preview_text)).to track(:accepted)
-                                                                .with_context(actor: group_invite)
-                                                                .on_next_instance
-
-            fill_in_sign_up_form(new_user)
-          end
-        end
-
         it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do
           fill_in_sign_up_form(new_user)
           fill_in_welcome_form
diff --git a/spec/helpers/notify_helper_spec.rb b/spec/helpers/notify_helper_spec.rb
index 633a4b65139fc..e2a7a212b1b61 100644
--- a/spec/helpers/notify_helper_spec.rb
+++ b/spec/helpers/notify_helper_spec.rb
@@ -55,31 +55,4 @@
   def reference_link(entity, url)
     "<a href=\"#{url}\">#{entity.to_reference}</a>"
   end
-
-  describe '#invited_join_url' do
-    let_it_be(:member) { create(:project_member) }
-
-    let(:token) { '_token_' }
-
-    context 'when invite_email_preview_text is enabled', :experiment do
-      before do
-        stub_experiments(invite_email_preview_text: :control)
-      end
-
-      it 'has correct params' do
-        expect(helper.invited_join_url(token, member))
-          .to eq("http://test.host/-/invites/#{token}?experiment_name=invite_email_preview_text&invite_type=initial_email")
-      end
-    end
-
-    context 'when invite_email_preview_text is disabled' do
-      before do
-        stub_feature_flags(invite_email_preview_text: false)
-      end
-
-      it 'has correct params' do
-        expect(helper.invited_join_url(token, member)).to eq("http://test.host/-/invites/#{token}?invite_type=initial_email")
-      end
-    end
-  end
 end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index ad9bd0faf8af5..44cb18008d2b7 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -829,7 +829,7 @@ def invite_to_project(project, inviter:, user: nil, tasks_to_be_done: [])
       end
 
       it_behaves_like 'an email sent from GitLab'
-      it_behaves_like 'it should not have Gmail Actions links'
+      it_behaves_like 'it should show Gmail Actions Join now link'
       it_behaves_like "a user cannot unsubscribe through footer link"
       it_behaves_like 'appearance header and footer enabled'
       it_behaves_like 'appearance header and footer not enabled'
@@ -867,27 +867,6 @@ def invite_to_project(project, inviter:, user: nil, tasks_to_be_done: [])
         end
       end
 
-      context 'with invite_email_preview_text enabled', :experiment do
-        before do
-          stub_experiments(invite_email_preview_text: :control)
-        end
-
-        it 'has the correct invite_url with params' do
-          is_expected.to have_link('Join now',
-                                   href: invite_url(project_member.invite_token,
-                                                    invite_type: Emails::Members::INITIAL_INVITE,
-                                                    experiment_name: 'invite_email_preview_text'))
-        end
-
-        it 'tracks the sent invite' do
-          expect(experiment(:invite_email_preview_text)).to track(:assignment)
-                                                      .with_context(actor: project_member)
-                                                      .on_next_instance
-
-          invite_email.deliver_now
-        end
-      end
-
       context 'when invite email sent is tracked', :snowplow do
         it 'tracks the sent invite' do
           invite_email.deliver_now
@@ -1461,7 +1440,7 @@ def invite_to_group(group, inviter:, user: nil, tasks_to_be_done: [])
       subject { described_class.member_invited_email('Group', group_member.id, group_member.invite_token) }
 
       it_behaves_like 'an email sent from GitLab'
-      it_behaves_like 'it should not have Gmail Actions links'
+      it_behaves_like 'it should show Gmail Actions Join now link'
       it_behaves_like "a user cannot unsubscribe through footer link"
       it_behaves_like 'appearance header and footer enabled'
       it_behaves_like 'appearance header and footer not enabled'
diff --git a/spec/support/shared_examples/mailers/notify_shared_examples.rb b/spec/support/shared_examples/mailers/notify_shared_examples.rb
index e1f7a9030e20f..20ed380fb18fd 100644
--- a/spec/support/shared_examples/mailers/notify_shared_examples.rb
+++ b/spec/support/shared_examples/mailers/notify_shared_examples.rb
@@ -161,6 +161,12 @@
   end
 end
 
+RSpec.shared_examples 'it should show Gmail Actions Join now link' do
+  it_behaves_like 'it should have Gmail Actions links'
+
+  it { is_expected.to have_body_text('Join now') }
+end
+
 RSpec.shared_examples 'it should show Gmail Actions View Issue link' do
   it_behaves_like 'it should have Gmail Actions links'
 
-- 
GitLab