Commit 4fd8951c authored by Alper Akgun's avatar Alper Akgun

Merge branch 'add-combined-registration-to-trial-registration' into 'master'

Add combined registration to trial registration flow

See merge request gitlab-org/gitlab!79437
parents 2bd808a1 5078efb2
......@@ -32,7 +32,7 @@ export default {
directives: {
autofocusonshow,
},
inject: ['user', 'submitPath'],
inject: ['user', 'submitPath', 'onboarding'],
data() {
return this.user;
},
......@@ -68,6 +68,7 @@ export default {
<template>
<gl-form :action="submitPath" method="post" @submit="onSubmit">
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
<input :value="onboarding" type="hidden" name="onboarding" />
<div class="gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-mt-5">
<gl-form-group
:label="$options.i18n.firstNameLabel"
......
......@@ -14,6 +14,7 @@ export const initTrialCreateLeadForm = () => {
country,
state,
phoneNumber,
onboarding,
} = el.dataset;
return new Vue({
......@@ -29,6 +30,7 @@ export const initTrialCreateLeadForm = () => {
state: state || '',
phoneNumber,
},
onboarding,
submitPath,
},
render(createElement) {
......
# frozen_string_literal: true
module Registrations::ApplyTrial
extend ActiveSupport::Concern
included do
private
def apply_trial
apply_trial_params = {
uid: current_user.id,
trial_user: params.permit(:glm_source, :glm_content).merge({
namespace_id: @group.id,
gitlab_com_trial: true,
sync_to_gl: true
})
}
result = GitlabSubscriptions::ApplyTrialService.new.execute(apply_trial_params)
flash.now[:alert] = result&.dig(:errors) unless result&.dig(:success)
result&.dig(:success)
end
end
end
......@@ -25,7 +25,7 @@ module Registrations::CreateProject
end
def learn_gitlab_project_name
helpers.in_trial_onboarding_flow? ? s_('Learn GitLab - Ultimate trial') : s_('Learn GitLab')
helpers.in_trial_onboarding_flow? ? LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL : LearnGitlab::Project::PROJECT_NAME
end
def project_params
......
......@@ -3,6 +3,7 @@
module Registrations
class GroupsController < ApplicationController
include Registrations::CreateGroup
include Registrations::ApplyTrial
include ::Gitlab::Utils::StrongMemoize
include OneTrustCSP
......@@ -95,21 +96,5 @@ module Registrations
result&.dig(:success)
end
def apply_trial
apply_trial_params = {
uid: current_user.id,
trial_user: params.permit(:glm_source, :glm_content).merge({
namespace_id: @group.id,
gitlab_com_trial: true,
sync_to_gl: true
})
}
result = GitlabSubscriptions::ApplyTrialService.new.execute(apply_trial_params)
flash[:alert] = result&.dig(:errors) unless result&.dig(:success)
result&.dig(:success)
end
end
end
......@@ -4,6 +4,7 @@ module Registrations
class GroupsProjectsController < ApplicationController
include Registrations::CreateProject
include Registrations::CreateGroup
include Registrations::ApplyTrial
include OneTrustCSP
skip_before_action :require_verification, only: :new
......@@ -35,30 +36,30 @@ module Registrations
if @group.persisted?
if @group.previously_new_record?
combined_registration_experiment.track(:create_group, namespace: @group)
helpers.require_verification_experiment.record_conversion(@group)
unless apply_trial_when_in_trial_flow
@project = Project.new(project_params) # #new requires a Project
return render :new
end
end
@project = ::Projects::CreateService.new(current_user, project_params).execute
if @project.saved?
combined_registration_experiment.track(:create_project, namespace: @project.namespace)
@learn_gitlab_project = create_learn_gitlab_project
create_learn_gitlab_project
store_location
redirect_path = continuous_onboarding_getting_started_users_sign_up_welcome_path(project_id: @project.id)
if helpers.registration_verification_enabled?
redirect_to new_users_sign_up_verification_path(url_params.merge(combined: true))
elsif helpers.in_trial_onboarding_flow?
redirect_to trial_getting_started_users_sign_up_welcome_path(url_params)
store_location_for(:user, redirect_path)
redirect_to new_users_sign_up_verification_path(project_id: @project.id, offer_trial: offer_trial?)
elsif offer_trial?
store_location_for(:user, redirect_path)
redirect_to new_trial_path
else
success_url = continuous_onboarding_getting_started_users_sign_up_welcome_path(url_params)
if current_user.setup_for_company
success_url = new_trial_path
end
helpers.require_verification_experiment.record_conversion(@group)
redirect_to success_url
redirect_to redirect_path
end
else
render :new
......@@ -71,7 +72,7 @@ module Registrations
def import
@group = Groups::CreateService.new(current_user, modified_group_params).execute
if @group.persisted?
if @group.persisted? && apply_trial_when_in_trial_flow
combined_registration_experiment.track(:create_group, namespace: @group)
helpers.require_verification_experiment.record_conversion(@group)
......@@ -103,19 +104,12 @@ module Registrations
modifed_group_params
end
def store_location
if current_user.setup_for_company && !helpers.in_trial_onboarding_flow?
success_url = continuous_onboarding_getting_started_users_sign_up_welcome_path(url_params)
store_location_for(:user, success_url)
end
def offer_trial?
current_user.setup_for_company && !helpers.in_trial_onboarding_flow? && !params[:skip_trial].present?
end
def url_params
if helpers.in_trial_onboarding_flow?
{ learn_gitlab_project_id: @learn_gitlab_project.id }
else
{ project_id: @project.id }
end
def apply_trial_when_in_trial_flow
!helpers.in_trial_onboarding_flow? || apply_trial
end
end
end
......@@ -11,6 +11,7 @@ class TrialRegistrationsController < RegistrationsController
before_action :check_if_gl_com_or_dev
before_action :set_redirect_url, only: [:new]
before_action :add_onboarding_parameter_to_redirect_url, only: :create
before_action only: [:new] do
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
......@@ -42,6 +43,16 @@ class TrialRegistrationsController < RegistrationsController
end
end
def add_onboarding_parameter_to_redirect_url
stored_url = stored_location_for(:user)
return unless stored_url.present?
redirect_uri = URI.parse(stored_url)
new_query = URI.decode_www_form(String(redirect_uri.query)) << ['onboarding', true]
redirect_uri.query = URI.encode_www_form(new_query)
store_location_for(:user, redirect_uri.to_s)
end
def sign_up_params
if params[:user]
params.require(:user).permit(:first_name, :last_name, :username, :email, :password, :skip_confirmation, :email_opted_in)
......
......@@ -36,8 +36,8 @@ class TrialsController < ApplicationController
render(:new) && return unless @result[:success]
if EE::TrialHelper::TRIAL_ONBOARDING_SOURCE_URLS.include?(params[:glm_source])
redirect_to(new_users_sign_up_group_path(url_params.merge(trial_onboarding_flow: true)))
if params[:onboarding] == 'true'
redirect_to(new_users_sign_up_groups_project_path(url_params.merge(trial_onboarding_flow: true)))
elsif @namespace = helpers.only_trialable_group_namespace
params[:namespace_id] = @namespace.id
apply_trial_and_redirect
......@@ -73,7 +73,11 @@ class TrialsController < ApplicationController
end
def skip
redirect_to stored_location_or_provided_path(dashboard_projects_path)
if params[:onboarding] == 'true'
redirect_to new_users_sign_up_groups_project_path(skip_trial: true)
else
redirect_to stored_location_or_provided_path(dashboard_projects_path)
end
end
protected
......
......@@ -21,7 +21,7 @@ module EE
def registration_verification_data
url = if params[:learn_gitlab_project_id].present?
trial_getting_started_users_sign_up_welcome_path(params.slice(:learn_gitlab_project_id).permit!)
elsif params[:combined].present? && current_user.setup_for_company
elsif params[:offer_trial] == 'true'
new_trial_path
elsif params[:project_id].present?
continuous_onboarding_getting_started_users_sign_up_welcome_path(params.slice(:project_id).permit!)
......
......@@ -20,7 +20,8 @@ module EE
submit_path: create_lead_trials_path(glm_params),
first_name: current_user.first_name,
last_name: current_user.last_name,
company_name: current_user.organization
company_name: current_user.organization,
onboarding: params[:onboarding]
}.merge(params.slice(:first_name, :last_name, :company_name, :company_size, :phone_number, :country, :state).to_unsafe_h.symbolize_keys)
end
......
- @html_class = "subscriptions-layout-html"
- @hide_flash = true
- page_title _('Your GitLab group')
- form_params = { trial_onboarding_flow: params[:trial_onboarding_flow], glm_source: params[:glm_source], glm_content: params[:glm_content] }
- form_params = { trial_onboarding_flow: params[:trial_onboarding_flow], glm_source: params[:glm_source], glm_content: params[:glm_content], skip_trial: params[:skip_trial] }
- content_for :page_specific_javascripts do
= render "layouts/one_trust"
- if in_trial_onboarding_flow?
.row
.gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-mt-3
= render 'registrations/trial_is_activated_banner'
.row.gl-flex-grow-1
.gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
.new-project.gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-xs-w-full
- unless in_trial_onboarding_flow?
#progress-bar
%h2.gl-text-center= _('Create or import your first project')
%p.gl-text-center= _('Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more.')
......
......@@ -4,6 +4,6 @@
.gl-font-sm.gl-text-gray-700
= s_("Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'")
- else
= link_to s_('Trials|Skip Trial'), skip_trials_path, class: 'block py-2 js-skip-trial'
= link_to s_('Trials|Skip Trial'), skip_trials_path(params.permit(:onboarding)), class: 'block py-2 js-skip-trial'
.gl-font-sm.gl-text-gray-700
= s_("Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'")
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Registrations::GroupsProjectsController, :experiment do
include AfterNextHelpers
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
......@@ -141,6 +143,12 @@ RSpec.describe Registrations::GroupsProjectsController, :experiment do
it { is_expected.to render_template(:new) }
end
context 'with signup onboarding not enabled' do
let(:dev_env_or_com) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
context "when group can be created but the project can't" do
let(:project_params) { { name: '', path: '', visibility_level: Gitlab::VisibilityLevel::PRIVATE } }
......@@ -187,55 +195,130 @@ RSpec.describe Registrations::GroupsProjectsController, :experiment do
post_create
end
end
context 'it redirects' do
let_it_be(:project) { create(:project) }
context 'it redirects' do
let_it_be(:project) { create(:project) }
let(:success_path) { continuous_onboarding_getting_started_users_sign_up_welcome_path(project_id: project.id) }
before do
allow_next_instance_of(::Projects::CreateService) do |service|
allow(service).to receive(:execute).and_return(project)
end
end
it { is_expected.to redirect_to(success_path) }
context 'when the `registration_verification` experiment is enabled' do
before do
allow_next_instance_of(::Projects::CreateService) do |service|
allow(service).to receive(:execute).and_return(project)
end
stub_experiments(registration_verification: :candidate)
end
it { is_expected.to redirect_to(continuous_onboarding_getting_started_users_sign_up_welcome_path(project_id: project.id)) }
it 'is expected to store the success path and redirect to the verification page' do
expect(subject).to redirect_to(new_users_sign_up_verification_path(project_id: project.id))
expect(controller.stored_location_for(:user)).to eq(success_path)
end
end
context 'when setup_for_company is true' do
let_it_be(:user) { create(:user, setup_for_company: true) }
it 'is expected to store the success path and redirect to the new trial page' do
expect(subject).to redirect_to(new_trial_path)
expect(controller.stored_location_for(:user)).to eq(success_path)
end
context 'when the skip_trial param is set' do
let(:extra_params) { { skip_trial: true } }
it { is_expected.to redirect_to(success_path) }
end
context 'when the trial_onboarding_flow param is set' do
let(:extra_params) { { trial_onboarding_flow: true } }
before do
allow_next_instance_of(GitlabSubscriptions::ApplyTrialService) do |service|
allow(service).to receive(:execute).and_return({ success: true })
end
end
it { is_expected.to redirect_to(success_path) }
end
end
end
end
shared_context 'groups_projects projects concern' do
let_it_be(:project) { create(:project) }
let_it_be(:namespace) { create(:group) }
context 'when in the trial onboarding flow' do
let(:success) { true }
let(:extra_params) do
{ trial_onboarding_flow: true, glm_source: 'about.gitlab.com', glm_content: 'content' }
end
let(:group_params) { { name: 'Group name', path: 'group-path', visibility_level: "#{Gitlab::VisibilityLevel::PRIVATE}", setup_for_company: setup_for_company } }
let(:extra_params) { { group: group_params } }
let(:params) { { name: 'New project', path: 'project-path', visibility_level: Gitlab::VisibilityLevel::PRIVATE } }
let(:create_service) { double(:create_service) }
let(:apply_trial_params) do
{
uid: user.id,
trial_user: ActionController::Parameters.new(
{
glm_source: 'about.gitlab.com',
glm_content: 'content',
namespace_id: group.id,
gitlab_com_trial: true,
sync_to_gl: true
}
).permit!
}
end
before do
allow(controller).to receive(:record_experiment_user).and_call_original
allow(controller).to receive(:record_experiment_conversion_event).and_call_original
before do
allow_next_instance_of(::Groups::CreateService) do |service|
allow(service).to receive(:execute).and_return(group)
end
expect_next_instance_of(GitlabSubscriptions::ApplyTrialService) do |service|
expect(service).to receive(:execute).with(apply_trial_params).and_return({ success: success })
end
end
allow(Groups::CreateService).to receive(:new).and_call_original
allow(Groups::CreateService).to receive(:new).with(user, ActionController::Parameters.new(group_params.merge(create_event: true)).permit!).and_return(create_service)
allow(create_service).to receive(:execute).and_return(namespace)
it 'applies a trial' do
post_create
end
context 'when failing to apply trial' do
let(:success) { false }
it { is_expected.to render_template(:new) }
end
end
end
it_behaves_like "Registrations::ProjectsController POST #create" do
include_context 'groups_projects projects concern'
end
context 'learn gitlab project' do
using RSpec::Parameterized::TableSyntax
context 'when the user is setup_for_company: true it redirects to the new_trial_path' do
let(:setup_for_company) { true }
where(:trial, :project_name, :template) do
false | 'Learn GitLab' | described_class::LEARN_GITLAB_ULTIMATE_TEMPLATE
true | 'Learn GitLab - Ultimate trial' | described_class::LEARN_GITLAB_ULTIMATE_TEMPLATE
end
with_them do
let(:path) { Rails.root.join('vendor', 'project_templates', template) }
let(:expected_arguments) { { namespace_id: group.id, file: handle, name: project_name } }
let(:handle) { double }
let(:group_params) { { id: group.id } }
let(:extra_params) { { trial_onboarding_flow: trial } }
it_behaves_like "Registrations::ProjectsController POST #create" do
let_it_be(:first_project) { create(:project) }
before do
group.add_owner(user)
allow(File).to receive(:open).and_call_original
expect(File).to receive(:open).with(path).and_yield(handle)
end
let(:user) { create(:user, setup_for_company: setup_for_company) }
let(:success_path) { new_trial_path }
let(:stored_location_for) { continuous_onboarding_getting_started_users_sign_up_welcome_path(project_id: first_project.id) }
specify do
expect_next(::Projects::GitlabProjectsImportService, user, expected_arguments)
.to receive(:execute)
include_context 'groups_projects projects concern'
subject
end
end
end
end
end
......
......@@ -103,5 +103,14 @@ RSpec.describe TrialRegistrationsController do
expect(User.last.name).to eq("#{user_params[:first_name]} #{user_params[:last_name]}")
end
end
context 'applying the onboarding=true parameter' do
it 'adds the parameter' do
redirect_path = new_trial_path(glm_source: 'about.gitlab.com', glm_content: 'default-saas-trial')
controller.store_location_for(:user, redirect_path)
post_create
expect(controller.stored_location_for(:user)).to eq(redirect_path + '&onboarding=true')
end
end
end
end
......@@ -94,27 +94,11 @@ RSpec.describe TrialsController, :saas do
it { is_expected.to redirect_to(select_trials_url) }
context 'coming from about.gitlab.com' do
let(:post_params) { { glm_source: 'about.gitlab.com' } }
context 'when the onboarding=true parameter is set' do
let(:post_params) { { glm_source: 'about.gitlab.com', onboarding: true } }
it 'redirects to trial onboarding' do
is_expected.to redirect_to(new_users_sign_up_group_path(glm_source: 'about.gitlab.com', trial_onboarding_flow: true))
end
end
context 'coming from docs.gitlab.com' do
let(:post_params) { { glm_source: 'docs.gitlab.com' } }
it 'redirects to trial onboarding' do
is_expected.to redirect_to(new_users_sign_up_group_path(glm_source: 'docs.gitlab.com', trial_onboarding_flow: true))
end
end
context 'coming from learn.gitlab.com' do
let(:post_params) { { glm_source: 'learn.gitlab.com' } }
it 'redirects to trial onboarding' do
is_expected.to redirect_to(new_users_sign_up_group_path(glm_source: 'learn.gitlab.com', trial_onboarding_flow: true))
it 'redirects to the combined registration path' do
is_expected.to redirect_to(new_users_sign_up_groups_project_path(glm_source: 'about.gitlab.com', trial_onboarding_flow: true))
end
end
......@@ -611,7 +595,15 @@ RSpec.describe TrialsController, :saas do
end
describe '#skip' do
subject(:get_skip) { get :skip }
subject(:get_skip) { get :skip, params: params }
let(:params) { {} }
context 'when the onboarding=true parameter is set' do
let(:params) { { onboarding: true } }
it { is_expected.to redirect_to(new_users_sign_up_groups_project_path(skip_trial: true)) }
end
context 'when the user is `setup_for_company: true`' do
let(:user) { create(:user, setup_for_company: true) }
......
......@@ -23,6 +23,7 @@ describe('TrialCreateLeadForm', () => {
provide: {
submitPath: SUBMIT_PATH,
user: FORM_DATA,
onboarding: false,
},
});
};
......
......@@ -63,11 +63,9 @@ RSpec.describe EE::RegistrationsHelper do
describe '#registration_verification_data' do
before do
allow(helper).to receive(:params).and_return(ActionController::Parameters.new(params))
allow(helper).to receive(:current_user).and_return(build(:user, setup_for_company: setup_for_company))
allow(helper).to receive(:current_user).and_return(build(:user))
end
let(:setup_for_company) { false }
context 'with `learn_gitlab_project_id` parameter present' do
let(:params) { { learn_gitlab_project_id: 1 } }
......@@ -86,23 +84,12 @@ RSpec.describe EE::RegistrationsHelper do
end
end
context 'with `combined` parameter present' do
let(:params) { { combined: true } }
context 'with `offer_trial` parameter present' do
let(:params) { { offer_trial: 'true' } }
context 'when user is setting up for a company' do
let(:setup_for_company) { true }
it 'return expected data' do
expect(helper.registration_verification_data)
.to eq(next_step_url: helper.new_trial_path)
end
end
context 'when user is not setting up for a company' do
it 'return expected data' do
expect(helper.registration_verification_data)
.to eq(next_step_url: helper.root_path)
end
it 'return expected data' do
expect(helper.registration_verification_data)
.to eq(next_step_url: helper.new_trial_path)
end
end
......
......@@ -32,7 +32,7 @@ RSpec.describe EE::TrialHelper do
end
it 'provides expected form data' do
keys = extra_params.keys + [:submit_path]
keys = extra_params.keys + [:submit_path, :onboarding]
expect(helper.create_lead_form_data.keys.map(&:to_sym)).to match_array(keys)
end
......
......@@ -3,6 +3,7 @@
module LearnGitlab
class Project
PROJECT_NAME = 'Learn GitLab'
PROJECT_NAME_ULTIMATE_TRIAL = 'Learn GitLab - Ultimate trial'
BOARD_NAME = 'GitLab onboarding'
LABEL_NAME = 'Novice'
......@@ -15,7 +16,7 @@ module LearnGitlab
end
def project
@project ||= current_user.projects.find_by_name(PROJECT_NAME)
@project ||= current_user.projects.find_by_name([PROJECT_NAME, PROJECT_NAME_ULTIMATE_TRIAL])
end
def board
......
......@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe LearnGitlab::Project do
let_it_be(:current_user) { create(:user) }
let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME) }
let_it_be(:learn_gitlab_ultimate_trial_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL) }
let_it_be(:learn_gitlab_board) { create(:board, project: learn_gitlab_project, name: LearnGitlab::Project::BOARD_NAME) }
let_it_be(:learn_gitlab_label) { create(:label, project: learn_gitlab_project, name: LearnGitlab::Project::LABEL_NAME) }
......@@ -45,6 +46,12 @@ RSpec.describe LearnGitlab::Project do
subject { described_class.new(current_user).project }
it { is_expected.to eq learn_gitlab_project }
context 'when it is created during trial signup' do
let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL) }
it { is_expected.to eq learn_gitlab_project }
end
end
describe '.board' do
......
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