Commit caf5cef9 authored by Jay Swain's avatar Jay Swain

Auto-check trial toggle for company signups

For namespaces that are signing up for a company, auto-select the toggle
for a trial

part of:
https://gitlab.com/gitlab-org/gitlab/-/issues/334829
parent 0bd6434d
...@@ -16,7 +16,7 @@ module Registrations ...@@ -16,7 +16,7 @@ module Registrations
result = ::Users::SignupService.new(current_user, update_params).execute result = ::Users::SignupService.new(current_user, update_params).execute
if result[:status] == :success if result[:status] == :success
return redirect_to new_users_sign_up_group_path if show_signup_onboarding? return redirect_to new_users_sign_up_group_path(trial_params) if show_signup_onboarding?
members = current_user.members members = current_user.members
...@@ -67,6 +67,10 @@ module Registrations ...@@ -67,6 +67,10 @@ module Registrations
def show_signup_onboarding? def show_signup_onboarding?
false false
end end
def trial_params
nil
end
end end
end end
......
# frozen_string_literal: true
class ForceCompanyTrialExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
exclude :setup_for_personal
private
def setup_for_personal
!context.user.setup_for_company
end
end
---
name: force_company_trial
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65287
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335050
milestone: '14.1'
type: experiment
group: group::adoption
default_enabled: false
...@@ -62,6 +62,14 @@ module EE ...@@ -62,6 +62,14 @@ module EE
helpers.signup_onboarding_enabled? helpers.signup_onboarding_enabled?
end end
override :trial_params
def trial_params
experiment(:force_company_trial, user: current_user) do |e|
e.try { { trial: true } }
e.run
end
end
def authorized_for_trial_onboarding! def authorized_for_trial_onboarding!
access_denied! unless can?(current_user, :owner_access, learn_gitlab_project) access_denied! unless can?(current_user, :owner_access, learn_gitlab_project)
end end
......
...@@ -15,6 +15,8 @@ module Registrations ...@@ -15,6 +15,8 @@ module Registrations
def create def create
Members::CreateService.new(current_user, invite_params).execute Members::CreateService.new(current_user, invite_params).execute
experiment(:force_company_trial, user: current_user).track(:create_invite, namespace: group, user: current_user)
redirect_to new_users_sign_up_project_path(namespace_id: group.id, redirect_to new_users_sign_up_project_path(namespace_id: group.id,
trial: helpers.in_trial_during_signup_flow?, trial: helpers.in_trial_during_signup_flow?,
trial_onboarding_flow: helpers.in_trial_onboarding_flow?, trial_onboarding_flow: helpers.in_trial_onboarding_flow?,
......
...@@ -23,6 +23,9 @@ module Registrations ...@@ -23,6 +23,9 @@ module Registrations
if @group.persisted? if @group.persisted?
experiment(:jobs_to_be_done, user: current_user) experiment(:jobs_to_be_done, user: current_user)
.track(:create_group, namespace: @group) .track(:create_group, namespace: @group)
force_company_trial_experiment.track(:create_group, namespace: @group, user: current_user)
create_successful_flow create_successful_flow
else else
render action: :new render action: :new
...@@ -37,6 +40,11 @@ module Registrations ...@@ -37,6 +40,11 @@ module Registrations
private private
def force_company_trial_experiment
@force_company_trial_experiment ||=
experiment(:force_company_trial, user: current_user)
end
def create_successful_flow def create_successful_flow
if helpers.in_trial_onboarding_flow? if helpers.in_trial_onboarding_flow?
apply_trial_for_trial_onboarding_flow apply_trial_for_trial_onboarding_flow
...@@ -123,7 +131,11 @@ module Registrations ...@@ -123,7 +131,11 @@ module Registrations
result = GitlabSubscriptions::ApplyTrialService.new.execute(apply_trial_params) result = GitlabSubscriptions::ApplyTrialService.new.execute(apply_trial_params)
flash[:alert] = result&.dig(:errors) unless result&.dig(:success) flash[:alert] = result&.dig(:errors) unless result&.dig(:success)
result&.dig(:success) success = result&.dig(:success)
force_company_trial_experiment.track(:create_trial, namespace: @group, user: current_user, label: 'registrations_groups_controller') if success
success
end end
def learn_gitlab_context def learn_gitlab_context
......
...@@ -34,6 +34,9 @@ module Registrations ...@@ -34,6 +34,9 @@ module Registrations
experiment(:jobs_to_be_done, user: current_user) experiment(:jobs_to_be_done, user: current_user)
.track(:create_project, project: @project) .track(:create_project, project: @project)
experiment(:force_company_trial, user: current_user)
.track(:create_project, namespace: @project.namespace, project: @project, user: current_user)
if helpers.in_trial_onboarding_flow? if helpers.in_trial_onboarding_flow?
record_experiment_user(:trial_onboarding_issues, onboarding_context) record_experiment_user(:trial_onboarding_issues, onboarding_context)
record_experiment_conversion_event(:trial_onboarding_issues) record_experiment_conversion_event(:trial_onboarding_issues)
......
...@@ -66,6 +66,8 @@ class SubscriptionsController < ApplicationController ...@@ -66,6 +66,8 @@ class SubscriptionsController < ApplicationController
edit_subscriptions_group_path(group.path, plan_id: plan_id, quantity: quantity, new_user: params[:new_user]) edit_subscriptions_group_path(group.path, plan_id: plan_id, quantity: quantity, new_user: params[:new_user])
end end
experiment(:force_company_trial, user: current_user).track(:create_subscription, namespace: group, user: current_user)
response[:data] = { location: redirect_location } response[:data] = { location: redirect_location }
end end
......
...@@ -45,6 +45,8 @@ class TrialsController < ApplicationController ...@@ -45,6 +45,8 @@ class TrialsController < ApplicationController
record_experiment_conversion_event(:remove_known_trial_form_fields) record_experiment_conversion_event(:remove_known_trial_form_fields)
record_experiment_conversion_event(:trial_onboarding_issues) record_experiment_conversion_event(:trial_onboarding_issues)
experiment(:force_company_trial, user: current_user).track(:create_trial, namespace: @namespace, user: current_user, label: 'trials_controller') if @namespace.created_at > 24.hours.ago
if discover_group_security_flow? if discover_group_security_flow?
redirect_trial_user_to_feature_experiment_flow redirect_trial_user_to_feature_experiment_flow
else else
......
...@@ -273,6 +273,16 @@ RSpec.describe Registrations::GroupsController do ...@@ -273,6 +273,16 @@ RSpec.describe Registrations::GroupsController do
context 'with separate invite page' do context 'with separate invite page' do
it { is_expected.to redirect_to(new_users_sign_up_group_invite_path(group_id: group.id, trial: true)) } it { is_expected.to redirect_to(new_users_sign_up_group_invite_path(group_id: group.id, trial: true)) }
end end
it 'tracks for the force_company_trial experiment', :experiment do
wrapped_experiment(experiment(:force_company_trial)) do |e|
expect(e.context.value).to include(user: user)
expect(e).to receive(:track).with(:create_group, namespace: an_instance_of(Group), user: user)
expect(e).to receive(:track).with(:create_trial, namespace: an_instance_of(Group), user: user, label: 'registrations_groups_controller')
end
subject
end
end end
context 'when failing to create a lead and apply trial' do context 'when failing to create a lead and apply trial' do
...@@ -306,6 +316,16 @@ RSpec.describe Registrations::GroupsController do ...@@ -306,6 +316,16 @@ RSpec.describe Registrations::GroupsController do
subject subject
end end
it 'selectivly tracks for the force_company_trial experiment', :experiment do
wrapped_experiment(experiment(:force_company_trial)) do |e|
expect(e.context.value).to include(user: user)
expect(e).to receive(:track).with(:create_group, namespace: an_instance_of(Group))
expect(e).not_to receive(:track).with(:create_trial, namespace: an_instance_of(Group))
end
subject
end
end end
end end
end end
......
...@@ -97,6 +97,14 @@ RSpec.describe Registrations::ProjectsController do ...@@ -97,6 +97,14 @@ RSpec.describe Registrations::ProjectsController do
subject subject
end end
it 'tracks an event for the force_company_trial experiment', :experiment do
expect(experiment(:force_company_trial)).to track(:create_project, namespace: namespace, project: an_instance_of(Project), user: user)
.with_context(user: user)
.on_next_instance
subject
end
it 'tracks learn gitlab experiments' do it 'tracks learn gitlab experiments' do
allow_next_instance_of(::Projects::CreateService) do |service| allow_next_instance_of(::Projects::CreateService) do |service|
allow(service).to receive(:execute).and_return(first_project) allow(service).to receive(:execute).and_return(first_project)
......
...@@ -229,6 +229,16 @@ RSpec.describe Registrations::WelcomeController do ...@@ -229,6 +229,16 @@ RSpec.describe Registrations::WelcomeController do
allow(controller.helpers).to receive(:signup_onboarding_enabled?).and_return(true) allow(controller.helpers).to receive(:signup_onboarding_enabled?).and_return(true)
end end
context 'and force_company_trial experiment is candidate' do
let(:setup_for_company) { 'true' }
before do
stub_experiments(force_company_trial: :candidate)
end
it { is_expected.to redirect_to new_users_sign_up_group_path(trial: true) }
end
it { is_expected.to redirect_to new_users_sign_up_group_path } it { is_expected.to redirect_to new_users_sign_up_group_path }
context 'when in subscription flow' do context 'when in subscription flow' do
......
...@@ -315,6 +315,12 @@ RSpec.describe SubscriptionsController do ...@@ -315,6 +315,12 @@ RSpec.describe SubscriptionsController do
expect(response.body).to eq({ location: "/#{selected_group.path}?plan_id=#{plan_id}&purchased_quantity=#{quantity}" }.to_json) expect(response.body).to eq({ location: "/#{selected_group.path}?plan_id=#{plan_id}&purchased_quantity=#{quantity}" }.to_json)
end end
it 'tracks for the force_company_trial experiment', :experiment do
expect(experiment(:force_company_trial)).to track(:create_subscription, namespace: selected_group, user: user).with_context(user: user).on_next_instance
subject
end
end end
context 'when the selected group is ineligible for a new subscription' do context 'when the selected group is ineligible for a new subscription' do
......
...@@ -185,7 +185,7 @@ RSpec.describe TrialsController do ...@@ -185,7 +185,7 @@ RSpec.describe TrialsController do
it_behaves_like 'an authenticated endpoint' it_behaves_like 'an authenticated endpoint'
it_behaves_like 'a dot-com only feature' it_behaves_like 'a dot-com only feature'
context 'on success' do context 'on success', :experiment do
let(:apply_trial_result) { true } let(:apply_trial_result) { true }
it { is_expected.to redirect_to("/#{namespace.path}?trial=true") } it { is_expected.to redirect_to("/#{namespace.path}?trial=true") }
...@@ -194,6 +194,7 @@ RSpec.describe TrialsController do ...@@ -194,6 +194,7 @@ RSpec.describe TrialsController do
expect(controller).to receive(:record_experiment_user).with(:trial_onboarding_issues, namespace_id: namespace.id) expect(controller).to receive(:record_experiment_user).with(:trial_onboarding_issues, namespace_id: namespace.id)
expect(controller).to receive(:record_experiment_conversion_event).with(:remove_known_trial_form_fields) expect(controller).to receive(:record_experiment_conversion_event).with(:remove_known_trial_form_fields)
expect(controller).to receive(:record_experiment_conversion_event).with(:trial_onboarding_issues) expect(controller).to receive(:record_experiment_conversion_event).with(:trial_onboarding_issues)
expect(experiment(:force_company_trial)).to track(:create_trial, namespace: namespace, user: user, label: 'trials_controller').with_context(user: user).on_next_instance
subject subject
end end
...@@ -235,6 +236,16 @@ RSpec.describe TrialsController do ...@@ -235,6 +236,16 @@ RSpec.describe TrialsController do
expect { subject }.to change { Group.count }.by(1) expect { subject }.to change { Group.count }.by(1)
end end
end end
context 'with an old namespace' do
it 'does not track for the force_company_trial experiment' do
namespace.update!(created_at: 2.days.ago)
expect(controller).not_to receive(:experiment).with(:force_company_trial, user: user)
subject
end
end
end end
context 'on failure' do context 'on failure' do
......
...@@ -5,8 +5,12 @@ require 'spec_helper' ...@@ -5,8 +5,12 @@ require 'spec_helper'
RSpec.describe 'User sees new onboarding flow', :js do RSpec.describe 'User sees new onboarding flow', :js do
include Select2Helper include Select2Helper
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:trial_fields) { ['Company name', 'Number of employees', 'How many employees will use Gitlab?', 'Telephone number', 'Country'] }
let(:experiments) { {} }
before do before do
stub_experiments(experiments)
allow(Gitlab).to receive(:com?).and_return(true) allow(Gitlab).to receive(:com?).and_return(true)
sign_in(user) sign_in(user)
visit users_sign_up_welcome_path visit users_sign_up_welcome_path
...@@ -19,6 +23,14 @@ RSpec.describe 'User sees new onboarding flow', :js do ...@@ -19,6 +23,14 @@ RSpec.describe 'User sees new onboarding flow', :js do
expect(page).to have_content('GitLab Ultimate trial (optional)') expect(page).to have_content('GitLab Ultimate trial (optional)')
end end
context 'when force_company_trial experiment is candidate' do
let(:experiments) { { force_company_trial: :candidate } }
it 'shows the trial fields' do
trial_fields.each { |field| expect(page).to have_content(field) }
end
end
it 'shows the expected behavior with no trial chosen', :aggregate_failures do it 'shows the expected behavior with no trial chosen', :aggregate_failures do
fill_in 'group_name', with: 'test' fill_in 'group_name', with: 'test'
...@@ -29,16 +41,15 @@ RSpec.describe 'User sees new onboarding flow', :js do ...@@ -29,16 +41,15 @@ RSpec.describe 'User sees new onboarding flow', :js do
end end
it 'shows the expected behavior with trial chosen' do it 'shows the expected behavior with trial chosen' do
fields = ['Company name', 'Number of employees', 'How many employees will use Gitlab?', 'Telephone number', 'Country']
fill_in 'group_name', with: 'test' fill_in 'group_name', with: 'test'
# fields initially invisible # fields initially invisible
fields.each { |field| expect(page).not_to have_content(field) } trial_fields.each { |field| expect(page).not_to have_content(field) }
# fields become visible with trial toggle # fields become visible with trial toggle
click_button class: 'gl-toggle' click_button class: 'gl-toggle'
fields.each { |field| expect(page).to have_content(field) } trial_fields.each { |field| expect(page).to have_content(field) }
# fields are required # fields are required
click_on 'Create group' click_on 'Create group'
...@@ -48,12 +59,12 @@ RSpec.describe 'User sees new onboarding flow', :js do ...@@ -48,12 +59,12 @@ RSpec.describe 'User sees new onboarding flow', :js do
# make fields invisible again # make fields invisible again
click_button class: 'gl-toggle' click_button class: 'gl-toggle'
fields.each { |field| expect(page).not_to have_content(field) } trial_fields.each { |field| expect(page).not_to have_content(field) }
# make fields visible again # make fields visible again
click_button class: 'gl-toggle' click_button class: 'gl-toggle'
fields.each { |field| expect(page).to have_content(field) } trial_fields.each { |field| expect(page).to have_content(field) }
# submit the trial form # submit the trial form
fill_in 'company_name', with: 'GitLab' fill_in 'company_name', with: 'GitLab'
......
...@@ -65,7 +65,15 @@ RSpec.describe 'view group invites' do ...@@ -65,7 +65,15 @@ RSpec.describe 'view group invites' do
hide_trial_activation_banner: true)) hide_trial_activation_banner: true))
end end
context 'when inviting members' do context 'when inviting members', :experiment do
it 'tracks for the force_company_trial experiment' do
expect(experiment(:force_company_trial)).to track(:create_invite, namespace: group, user: user)
.with_context(user: user)
.on_next_instance
post_request
end
context 'without valid emails in the params' do context 'without valid emails in the params' do
it 'no invites generated by default' do it 'no invites generated by default' do
post_request post_request
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ForceCompanyTrialExperiment, :experiment do
subject { described_class.new(current_user: user) }
let(:user) { create(:user, setup_for_company: setup_for_company) }
let(:setup_for_company) { true }
context 'when a user is setup_for_company' do
it 'is not excluded' do
expect(subject).not_to exclude(user: user)
end
end
context 'when a user is not setup_for_company' do
let(:setup_for_company) { nil }
it 'is excluded' do
expect(subject).to exclude(user: user)
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