Commit 659dfa75 authored by Nicolas Dular's avatar Nicolas Dular

New group and project invite email design

This makes the invite mail experiment the default experience and
therefore improves our invitation emails by having one clear call to
action with a neater design.
parent ca29a313
...@@ -119,7 +119,6 @@ linters: ...@@ -119,7 +119,6 @@ linters:
- 'app/views/invites/show.html.haml' - 'app/views/invites/show.html.haml'
- 'app/views/jira_connect/subscriptions/index.html.haml' - 'app/views/jira_connect/subscriptions/index.html.haml'
- 'app/views/layouts/_mailer.html.haml' - 'app/views/layouts/_mailer.html.haml'
- 'app/views/layouts/experiment_mailer.html.haml'
- 'app/views/layouts/header/_default.html.haml' - 'app/views/layouts/header/_default.html.haml'
- 'app/views/layouts/header/_new_dropdown.haml' - 'app/views/layouts/header/_new_dropdown.haml'
- 'app/views/layouts/jira_connect.html.haml' - 'app/views/layouts/jira_connect.html.haml'
......
...@@ -143,4 +143,21 @@ tr.footer td { ...@@ -143,4 +143,21 @@ tr.footer td {
color: $mailer-link-color; color: $mailer-link-color;
text-decoration: none; text-decoration: none;
} }
.gitlab-info {
padding: $gl-padding-24 0;
}
.gitlab-info-text {
max-width: 640px;
margin: 0 auto;
text-align: center;
color: $gray-400;
font-size: $gl-font-size-small;
}
.footer-logo {
width: 90px;
height: 33px;
}
} }
...@@ -15,13 +15,11 @@ class InvitesController < ApplicationController ...@@ -15,13 +15,11 @@ class InvitesController < ApplicationController
feature_category :authentication_and_authorization feature_category :authentication_and_authorization
def show def show
track_new_user_invite_experiment('opened')
accept if skip_invitation_prompt? accept if skip_invitation_prompt?
end end
def accept def accept
if member.accept_invite!(current_user) if member.accept_invite!(current_user)
track_new_user_invite_experiment('accepted')
track_invitation_reminders_experiment('accepted') track_invitation_reminders_experiment('accepted')
redirect_to invite_details[:path], notice: _("You have been granted %{member_human_access} access to %{title} %{name}.") % redirect_to invite_details[:path], notice: _("You have been granted %{member_human_access} access to %{title} %{name}.") %
{ member_human_access: member.human_access, title: invite_details[:title], name: invite_details[:name] } { member_human_access: member.human_access, title: invite_details[:title], name: invite_details[:name] }
...@@ -110,25 +108,13 @@ class InvitesController < ApplicationController ...@@ -110,25 +108,13 @@ class InvitesController < ApplicationController
end end
end end
def track_new_user_invite_experiment(action)
return unless params[:new_user_invite]
property = params[:new_user_invite] == 'experiment' ? 'experiment_group' : 'control_group'
track_experiment(:invite_email, action, property)
end
def track_invitation_reminders_experiment(action) def track_invitation_reminders_experiment(action)
return unless Gitlab::Experimentation.enabled?(:invitation_reminders) return unless Gitlab::Experimentation.enabled?(:invitation_reminders)
property = Gitlab::Experimentation.enabled_for_attribute?(:invitation_reminders, member.invite_email) ? 'experimental_group' : 'control_group' property = Gitlab::Experimentation.enabled_for_attribute?(:invitation_reminders, member.invite_email) ? 'experimental_group' : 'control_group'
track_experiment(:invitation_reminders, action, property)
end
def track_experiment(experiment_key, action, property)
Gitlab::Tracking.event( Gitlab::Tracking.event(
Gitlab::Experimentation.experiment(experiment_key).tracking_category, Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category,
action, action,
property: property, property: property,
label: Digest::MD5.hexdigest(member.to_global_id.to_s) label: Digest::MD5.hexdigest(member.to_global_id.to_s)
......
...@@ -51,34 +51,20 @@ module Emails ...@@ -51,34 +51,20 @@ module Emails
return unless member_exists? return unless member_exists?
subject_line = subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}") subject_line =
if member.created_by
if member.invite_to_unknown_user? && Feature.enabled?(:invite_email_experiment) subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
subject_line = subject("#{member.created_by.name} invited you to join GitLab") if member.created_by
@invite_url_params = { new_user_invite: 'experiment' }
member_email_with_layout(
to: member.invite_email,
subject: subject_line,
template: 'member_invited_email_experiment',
layout: 'experiment_mailer'
)
Gitlab::Tracking.event(Gitlab::Experimentation::EXPERIMENTS[:invite_email][:tracking_category], 'sent', property: 'experiment_group')
else else
@invite_url_params = member.invite_to_unknown_user? ? { new_user_invite: 'control' } : {} subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
end
member_email_with_layout( member_email_with_layout(
to: member.invite_email, to: member.invite_email,
subject: subject_line subject: subject_line,
layout: 'unknown_user_mailer'
) )
if member.invite_to_unknown_user? if Gitlab::Experimentation.enabled?(:invitation_reminders)
Gitlab::Tracking.event(Gitlab::Experimentation::EXPERIMENTS[:invite_email][:tracking_category], 'sent', property: 'control_group')
end
end
if member.invite_to_unknown_user? && Gitlab::Experimentation.enabled?(:invitation_reminders)
Gitlab::Tracking.event( Gitlab::Tracking.event(
Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category, Gitlab::Experimentation.experiment(:invitation_reminders).tracking_category,
'sent', 'sent',
...@@ -105,7 +91,7 @@ module Emails ...@@ -105,7 +91,7 @@ module Emails
subject_line = subjects[reminder_index] % { inviter: member.created_by.name } subject_line = subjects[reminder_index] % { inviter: member.created_by.name }
member_email_with_layout( member_email_with_layout(
layout: 'experiment_mailer', layout: 'unknown_user_mailer',
to: member.invite_email, to: member.invite_email,
subject: subject(subject_line) subject: subject(subject_line)
) )
...@@ -162,16 +148,11 @@ module Emails ...@@ -162,16 +148,11 @@ module Emails
@member_source_type.classify.constantize @member_source_type.classify.constantize
end end
def member_email_with_layout(to:, subject:, template: nil, layout: 'mailer') def member_email_with_layout(to:, subject:, layout: 'mailer')
mail(to: to, subject: subject) do |format| mail(to: to, subject: subject) do |format|
if template
format.html { render template, layout: layout }
format.text { render template, layout: layout }
else
format.html { render layout: layout } format.html { render layout: layout }
format.text { render layout: layout } format.text { render layout: layout }
end end
end end
end end
end
end end
...@@ -25,5 +25,5 @@ ...@@ -25,5 +25,5 @@
- if !member? - if !member?
.actions .actions
= link_to _("Accept invitation"), accept_invite_url(@token, new_user_invite: params[:new_user_invite]), method: :post, class: "btn gl-button btn-success" = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-success"
= link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button btn-danger gl-ml-3" = link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button btn-danger gl-ml-3"
...@@ -34,13 +34,7 @@ ...@@ -34,13 +34,7 @@
= render_if_exists 'layouts/mailer/additional_text' = render_if_exists 'layouts/mailer/additional_text'
%tr.footer = yield :footer
%td
%img{ alt: "GitLab", height: "33", width: "90", src: image_url('mailers/gitlab_footer_logo.gif') }
%div
- manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, class: 'mng-notif-link')
- help_link = link_to(_("Help"), help_url, class: 'help-link')
= _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
= yield :additional_footer = yield :additional_footer
%tr %tr
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
%html{ lang: "en" }
%head
%meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }/
%meta{ content: "width=device-width, initial-scale=1", name: "viewport" }/
%meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }/
%title= message.subject
-# Avoid premailer processing of client-specific styles (@media tag not supported)
-# We need to inline the contents here because mail clients (e.g. iOS Mail, Outlook)
-# do not support linked stylesheets.
%style{ type: 'text/css', 'data-premailer': 'ignore' }
= asset_to_string('mailer_client_specific.css').html_safe
= stylesheet_link_tag 'mailer.css'
%body
%table#body{ border: "0", cellpadding: "0", cellspacing: "0" }
%tbody
%tr.line
%td
%tr.header
%td
= html_header_message
= header_logo
%tr
%td
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0" }
%tbody
%tr
%td.wrapper-cell{ style: "padding: 0" }
%table.content{ border: "0", cellpadding: "0", cellspacing: "0" }
%tbody
= yield
= render_if_exists 'layouts/mailer/additional_text'
%tr.footer
%td{ style: "padding: 24px 0" }
%img{ alt: "GitLab", height: "33", width: "90", src: image_url('mailers/gitlab_footer_logo.gif') }
%p{ style: "color: #949ba5; max-width: 640px; margin: 0 auto; text-align: left; font-size: 12px;" }
GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way
%br
Development, Security, and Ops teams collaborate.
= yield :additional_footer
%tr
%td.footer-message
= html_footer_message
= content_for :footer do
%tr.footer
%td
%img.footer-logo{ alt: "GitLab", src: image_url('mailers/gitlab_footer_logo.gif') }
%div
- manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, class: 'mng-notif-link')
- help_link = link_to(_("Help"), help_url, class: 'help-link')
= _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
= render 'layouts/mailer' = render 'layouts/mailer'
= content_for :footer do
%tr.footer
%td.gitlab-info
%img.footer-logo{ alt: "GitLab", src: image_url('mailers/gitlab_footer_logo.gif') }
%p.gitlab-info-text
= html_escape(_("GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate")) % { br_tag: '<br/>'.html_safe }
= render 'layouts/mailer'
<%= text_header_message %>
<%= yield -%>
-- <%# signature marker %>
<%= _("GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate") %>
<%= render_if_exists 'layouts/mailer/additional_text' %>
<%= text_footer_message %>
- placeholders = { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, br_tag: '<br/>'.html_safe, role: member.human_access.downcase }
%tr %tr
%td.text-content %td.text-content
%h2.invite-header
= s_('InviteEmail|You are invited!')
%p %p
You have been invited
- if member.created_by - if member.created_by
by = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
= link_to member.created_by.name, user_url(member.created_by) - else
to join the = 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
= link_to member_source.human_name, member_source.public? ? member_source.web_url : invite_url(@token), class: :highlight %p.invite-actions
#{member_source.model_name.singular} as #{content_tag :span, member.human_access, class: :highlight}. = link_to s_('InviteEmail|Join now'), invite_url(@token), class: 'invite-btn-join'
%p
= link_to 'Accept invitation', invite_url(@token, @invite_url_params)
or
= link_to 'decline', decline_invite_url(@token)
You have been invited <%= "by #{sanitize_name(member.created_by.name)} " if member.created_by %>to join the <%= member_source.human_name %> <%= member_source.model_name.singular %> as <%= member.human_access %>. <% placeholders = { project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, role: member.human_access.downcase } %>
Accept invitation: <%= invite_url(@token, @invite_url_params) %> <% if member.created_by %>
Decline invitation: <%= decline_invite_url(@token) %> <%= s_('InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}') % placeholders.merge({ inviter: sanitize_name(member.created_by.name) }) %>
<% else %>
<%= s_('InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}') % placeholders %>
<% end %>
<%= s_('InviteEmail|Join now') %>: <%= invite_url(@token) %>
%tr
%td.text-content
%h2.invite-header
= s_('InviteEmail|You are invited!')
%p
- if member.created_by
= html_escape(s_("InviteEmail|%{inviter} invited you")) % { inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe }
= html_escape(s_("InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}")) % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_or_group_name: member_source.human_name }
%br
= s_("InviteEmail|%{project_or_group} as a %{role}") % { project_or_group: member_source.model_name.singular, role: member.human_access.downcase }
%p.invite-actions
= link_to s_('InviteEmail|Join now'), invite_url(@token, @invite_url_params), class: 'invite-btn-join'
<% project_and_role = s_('InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}') \
% { project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, role: member.human_access.downcase } %>
<% if member.created_by %>
<%= s_('InviteEmail|%{inviter} invited you') % { inviter: sanitize_name(member.created_by.name) } %> <%= project_and_role %>
<% else %>
<%= s_('InviteEmail|You have been invited') %> <%= project_and_role %>
<% end %>
Join now: <%= invite_url(@token, @invite_url_params) %>
---
title: New group and project invite mail design
merge_request: 44940
author:
type: changed
...@@ -12205,6 +12205,12 @@ msgstr "" ...@@ -12205,6 +12205,12 @@ msgstr ""
msgid "GitLab for Slack" msgid "GitLab for Slack"
msgstr "" msgstr ""
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way%{br_tag}Development, Security, and Ops teams collaborate"
msgstr ""
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security." msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
msgstr "" msgstr ""
...@@ -14249,25 +14255,22 @@ msgstr "" ...@@ -14249,25 +14255,22 @@ msgstr ""
msgid "Invite teammates (optional)" msgid "Invite teammates (optional)"
msgstr "" msgstr ""
msgid "InviteEmail|%{inviter} invited you" msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr "" msgstr ""
msgid "InviteEmail|%{project_or_group} as a %{role}" msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr "" msgstr ""
msgid "InviteEmail|Join now" msgid "InviteEmail|Join now"
msgstr "" msgstr ""
msgid "InviteEmail|You are invited!" msgid "InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
msgid "InviteEmail|You have been invited"
msgstr "" msgstr ""
msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}" msgid "InviteEmail|You are invited!"
msgstr "" msgstr ""
msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}" msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr "" msgstr ""
msgid "InviteMembersBanner|Collaborate with your team" msgid "InviteMembersBanner|Collaborate with your team"
...@@ -16065,6 +16068,12 @@ msgstr "" ...@@ -16065,6 +16068,12 @@ msgstr ""
msgid "Member since %{date}" msgid "Member since %{date}"
msgstr "" msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
msgid "Members" msgid "Members"
msgstr "" msgstr ""
......
...@@ -9,13 +9,6 @@ RSpec.describe InvitesController, :snowplow do ...@@ -9,13 +9,6 @@ RSpec.describe InvitesController, :snowplow do
let(:project_members) { member.source.users } let(:project_members) { member.source.users }
let(:md5_member_global_id) { Digest::MD5.hexdigest(member.to_global_id.to_s) } let(:md5_member_global_id) { Digest::MD5.hexdigest(member.to_global_id.to_s) }
let(:params) { { id: raw_invite_token } } let(:params) { { id: raw_invite_token } }
let(:snowplow_event) do
{
category: 'Growth::Acquisition::Experiment::InviteEmail',
label: md5_member_global_id,
property: group_type
}
end
shared_examples 'invalid token' do shared_examples 'invalid token' do
context 'when invite token is not valid' do context 'when invite token is not valid' do
...@@ -94,38 +87,6 @@ RSpec.describe InvitesController, :snowplow do ...@@ -94,38 +87,6 @@ RSpec.describe InvitesController, :snowplow do
expect(flash[:notice]).to be_nil expect(flash[:notice]).to be_nil
end end
context 'when new_user_invite is not set' do
it 'does not track the user as experiment group' do
request
expect_no_snowplow_event
end
end
context 'when new_user_invite is experiment' do
let(:params) { { id: raw_invite_token, new_user_invite: 'experiment' } }
let(:group_type) { 'experiment_group' }
it 'tracks the user as experiment group' do
request
expect_snowplow_event(**snowplow_event.merge(action: 'opened'))
expect_snowplow_event(**snowplow_event.merge(action: 'accepted'))
end
end
context 'when new_user_invite is control' do
let(:params) { { id: raw_invite_token, new_user_invite: 'control' } }
let(:group_type) { 'control_group' }
it 'tracks the user as control group' do
request
expect_snowplow_event(**snowplow_event.merge(action: 'opened'))
expect_snowplow_event(**snowplow_event.merge(action: 'accepted'))
end
end
it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment" it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment"
it_behaves_like 'invalid token' it_behaves_like 'invalid token'
end end
...@@ -158,36 +119,6 @@ RSpec.describe InvitesController, :snowplow do ...@@ -158,36 +119,6 @@ RSpec.describe InvitesController, :snowplow do
subject(:request) { post :accept, params: params } subject(:request) { post :accept, params: params }
context 'when new_user_invite is not set' do
it 'does not track an event' do
request
expect_no_snowplow_event
end
end
context 'when new_user_invite is experiment' do
let(:params) { { id: raw_invite_token, new_user_invite: 'experiment' } }
let(:group_type) { 'experiment_group' }
it 'tracks the user as experiment group' do
request
expect_snowplow_event(**snowplow_event.merge(action: 'accepted'))
end
end
context 'when new_user_invite is control' do
let(:params) { { id: raw_invite_token, new_user_invite: 'control' } }
let(:group_type) { 'control_group' }
it 'tracks the user as control group' do
request
expect_snowplow_event(**snowplow_event.merge(action: 'accepted'))
end
end
it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment" it_behaves_like "tracks the 'accepted' event for the invitation reminders experiment"
it_behaves_like 'invalid token' it_behaves_like 'invalid token'
end end
......
...@@ -887,64 +887,22 @@ RSpec.describe Notify do ...@@ -887,64 +887,22 @@ RSpec.describe Notify do
subject { described_class.member_invited_email('project', project_member.id, project_member.invite_token) } subject { described_class.member_invited_email('project', project_member.id, project_member.invite_token) }
context 'when invite_email_experiment is disabled' do
before do
stub_feature_flags(invite_email_experiment: false)
end
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links' it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer 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 enabled'
it_behaves_like 'appearance header and footer not enabled' it_behaves_like 'appearance header and footer not enabled'
it_behaves_like 'does not render a manage notifications link'
context 'when there is an inviter' do
it 'contains all the useful information' do it 'contains all the useful information' do
is_expected.to have_subject "Invitation to join the #{project.full_name} project" is_expected.to have_subject "#{inviter.name} invited you to join GitLab"
is_expected.to have_body_text project.full_name is_expected.to have_body_text project.full_name
is_expected.to have_body_text project_member.human_access is_expected.to have_body_text project_member.human_access.downcase
is_expected.to have_body_text project_member.invite_token is_expected.to have_body_text project_member.invite_token
end end
context 'when member is invited via an email address' do
it 'does add a param to the invite link' do
is_expected.to have_body_text 'new_user_invite=control'
end
it 'tracks an event' do
expect(Gitlab::Tracking).to receive(:event).with(
'Growth::Acquisition::Experiment::InviteEmail',
'sent',
property: 'control_group'
)
subject.deliver_now
end
end
context 'when member is already a user' do
let(:project_member) { invite_to_project(project, inviter: maintainer, user: create(:user)) }
it 'does not add a param to the invite link' do
is_expected.not_to have_body_text 'new_user_invite'
end
it 'does not track an event' do
expect(Gitlab::Tracking).not_to receive(:event)
subject.deliver_now
end
end
end end
context 'when invite_email_experiment is enabled' do
before do
stub_feature_flags(invite_email_experiment: true)
end
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
context 'when there is no inviter' do context 'when there is no inviter' do
let(:inviter) { nil } let(:inviter) { nil }
...@@ -955,30 +913,6 @@ RSpec.describe Notify do ...@@ -955,30 +913,6 @@ RSpec.describe Notify do
is_expected.to have_body_text project_member.invite_token is_expected.to have_body_text project_member.invite_token
end end
end end
context 'when there is an inviter' do
it 'contains all the useful information' do
is_expected.to have_subject "#{inviter.name} invited you to join GitLab"
is_expected.to have_body_text project.full_name
is_expected.to have_body_text project_member.human_access.downcase
is_expected.to have_body_text project_member.invite_token
end
end
it 'adds a param to the invite link' do
is_expected.to have_body_text 'new_user_invite=experiment'
end
it 'tracks an event' do
expect(Gitlab::Tracking).to receive(:event).with(
'Growth::Acquisition::Experiment::InviteEmail',
'sent',
property: 'experiment_group'
)
subject.deliver_now
end
end
end end
describe 'project invitation accepted' do describe 'project invitation accepted' do
...@@ -1547,63 +1481,23 @@ RSpec.describe Notify do ...@@ -1547,63 +1481,23 @@ RSpec.describe Notify do
end end
end end
context 'when invite_email_experiment is disabled' do
before do
stub_feature_flags(invite_email_experiment: false)
end
it_behaves_like 'an email sent from GitLab' it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links' it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer 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 enabled'
it_behaves_like 'appearance header and footer not enabled' it_behaves_like 'appearance header and footer not enabled'
it_behaves_like 'it requires a group' it_behaves_like 'it requires a group'
it_behaves_like 'does not render a manage notifications link'
context 'when there is an inviter' do
it 'contains all the useful information' do it 'contains all the useful information' do
is_expected.to have_subject "Invitation to join the #{group.name} group" is_expected.to have_subject "#{group_member.created_by.name} invited you to join GitLab"
is_expected.to have_body_text group.name is_expected.to have_body_text group.name
is_expected.to have_body_text group.web_url is_expected.to have_body_text group_member.human_access.downcase
is_expected.to have_body_text group_member.human_access
is_expected.to have_body_text group_member.invite_token is_expected.to have_body_text group_member.invite_token
end end
context 'when member is invited via an email address' do
it 'does add a param to the invite link' do
is_expected.to have_body_text 'new_user_invite=control'
end
it 'tracks an event' do
expect(Gitlab::Tracking).to receive(:event).with(
'Growth::Acquisition::Experiment::InviteEmail',
'sent',
property: 'control_group'
)
subject.deliver_now
end
end
context 'when member is already a user' do
let(:group_member) { invite_to_group(group, inviter: owner, user: create(:user)) }
it 'does not add a param to the invite link' do
is_expected.not_to have_body_text 'new_user_invite'
end end
it 'does not track an event' do
expect(Gitlab::Tracking).not_to receive(:event)
subject.deliver_now
end
end
end
context 'when invite_email_experiment is enabled' do
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
it_behaves_like 'it requires a group'
context 'when there is no inviter' do context 'when there is no inviter' do
let(:inviter) { nil } let(:inviter) { nil }
...@@ -1614,30 +1508,6 @@ RSpec.describe Notify do ...@@ -1614,30 +1508,6 @@ RSpec.describe Notify do
is_expected.to have_body_text group_member.invite_token is_expected.to have_body_text group_member.invite_token
end end
end end
context 'when there is an inviter' do
it 'contains all the useful information' do
is_expected.to have_subject "#{group_member.created_by.name} invited you to join GitLab"
is_expected.to have_body_text group.name
is_expected.to have_body_text group_member.human_access.downcase
is_expected.to have_body_text group_member.invite_token
end
end
it 'does add a param to the invite link' do
is_expected.to have_body_text 'new_user_invite'
end
it 'tracks an event' do
expect(Gitlab::Tracking).to receive(:event).with(
'Growth::Acquisition::Experiment::InviteEmail',
'sent',
property: 'experiment_group'
)
subject.deliver_now
end
end
end end
describe 'group invitation reminders' do describe 'group invitation reminders' do
......
...@@ -273,3 +273,12 @@ RSpec.shared_examples 'no email is sent' do ...@@ -273,3 +273,12 @@ RSpec.shared_examples 'no email is sent' do
expect(subject.message).to be_a_kind_of(ActionMailer::Base::NullMail) expect(subject.message).to be_a_kind_of(ActionMailer::Base::NullMail)
end end
end end
RSpec.shared_examples 'does not render a manage notifications link' do
it do
aggregate_failures do
expect(subject).not_to have_body_text("Manage all notifications")
expect(subject).not_to have_body_text(profile_notifications_url)
end
end
end
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