Commit 5078efb2 authored by Alex Buijs's avatar Alex Buijs

Add combined registration to trial registration flow

This adds the combined registration (group and project creation
in one page) to the trial registration flow.

Changelog: changed
parent 53314815
......@@ -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