Commit 2db9aae7 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'jswain_joining_team' into 'master'

Allow users to bypass the registration flow

See merge request gitlab-org/gitlab!72827
parents b5f31606 007ca183
......@@ -18,7 +18,7 @@ module Registrations
if result[:status] == :success
return redirect_to issues_dashboard_path(assignee_username: current_user.username) if show_tasks_to_be_done?
return redirect_to experiment(:combined_registration, user: current_user).redirect_path(trial_params) if show_signup_onboarding?
return redirect_to update_success_path if show_signup_onboarding?
members = current_user.members
......@@ -66,6 +66,7 @@ module Registrations
members.last.source.activity_path
end
# overridden in EE
def show_signup_onboarding?
false
end
......@@ -76,8 +77,12 @@ module Registrations
MemberTask.for_members(current_user.members).exists?
end
# overridden in EE
def trial_params
nil
end
# overridden in EE
def update_success_path
end
end
end
......
......@@ -24,9 +24,10 @@
.form-group.col-sm-12.js-other-role-group.hidden
= f.label :other_role, _('What is your job title? (optional)'), class: 'form-check-label gl-mb-3'
= f.text_field :other_role, class: 'form-control'
= render_if_exists "registrations/welcome/jobs_to_be_done", f: f
= render_if_exists "registrations/welcome/setup_for_company", f: f
= render_if_exists "registrations/welcome/joining_project"
= render 'devise/shared/email_opted_in', f: f
= render_if_exists "registrations/welcome/jobs_to_be_done", f: f
.row
.form-group.col-sm-12.gl-mb-0
- if partial_exists? "registrations/welcome/button"
......
---
name: bypass_registration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72827
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340560
milestone: '14.5'
type: experiment
group: group::adoption
default_enabled: false
import mountProgressBar from 'ee/registrations/projects/new';
import initProjectVisibilitySelector from '~/project_visibility';
import initProjectNew from '~/projects/project_new';
mountProgressBar();
initProjectVisibilitySelector();
initProjectNew.bindEvents();
import mountProgressBar from 'ee/registrations/welcome';
mountProgressBar();
import 'ee/registrations/welcome/other_role';
import 'ee/registrations/welcome/jobs_to_be_done';
import mountProgressBar from 'ee/registrations/welcome';
mountProgressBar();
import 'ee/registrations/welcome/other_role';
import 'ee/registrations/welcome/jobs_to_be_done';
const emailUpdatesForm = document.querySelector('.js-email-opt-in');
const setupForCompany = document.querySelector('.js-setup-for-company');
......
......@@ -8,7 +8,3 @@ export const STEPS = {
};
export const SUBSCRIPTON_FLOW_STEPS = [STEPS.yourProfile, STEPS.checkout, STEPS.yourGroup];
export const SIGNUP_ONBOARDING_FLOW_STEPS = [STEPS.yourProfile, STEPS.yourGroup, STEPS.yourProject];
export const COMBINED_SIGNUP_FLOW_STEPS = [STEPS.yourProfile, STEPS.yourProject];
import Vue from 'vue';
import mountVisibilityLevelDropdown from '~/groups/visibility_level';
import 'ee/pages/trials/country_select';
import ProgressBar from '../../components/progress_bar.vue';
import RegistrationTrialToggle from '../../components/registration_trial_toggle.vue';
import { STEPS, SIGNUP_ONBOARDING_FLOW_STEPS } from '../../constants';
function mountProgressBar() {
const el = document.getElementById('progress-bar');
if (!el) {
return null;
}
return new Vue({
el,
render(createElement) {
return createElement(ProgressBar, {
props: { steps: SIGNUP_ONBOARDING_FLOW_STEPS, currentStep: STEPS.yourGroup },
});
},
});
}
function toggleTrialForm(trial) {
const form = document.querySelector('.js-trial-form');
......@@ -61,7 +42,6 @@ function mountTrialToggle() {
}
export default () => {
mountProgressBar();
mountVisibilityLevelDropdown();
mountTrialToggle();
};
......@@ -2,7 +2,6 @@ import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import { bindHowToImport } from '~/projects/project_new';
import { displayGroupPath, displayProjectPath } from './path_display';
import mountProgressBar from './progress_bar';
import showTooltip from './show_tooltip';
const importButtonsSubmit = () => {
......@@ -35,7 +34,6 @@ const setAutofocus = () => {
const mobileTooltipOpts = () => (bp.getBreakpointSize() === 'xs' ? { placement: 'bottom' } : {});
export default () => {
mountProgressBar();
displayGroupPath('.js-group-path-source', '.js-group-path-display');
displayGroupPath('.js-import-group-path-source', '.js-import-group-path-display');
displayProjectPath('.js-project-path-source', '.js-project-path-display');
......
import Vue from 'vue';
import ProgressBar from '../../components/progress_bar.vue';
import { STEPS, COMBINED_SIGNUP_FLOW_STEPS } from '../../constants';
export default function mountProgressBar() {
const el = document.getElementById('progress-bar');
if (!el) {
return null;
}
return new Vue({
el,
render(createElement) {
return createElement(ProgressBar, {
props: { steps: COMBINED_SIGNUP_FLOW_STEPS, currentStep: STEPS.yourProject },
});
},
});
}
import Vue from 'vue';
import ProgressBar from '../../components/progress_bar.vue';
import { STEPS, SIGNUP_ONBOARDING_FLOW_STEPS } from '../../constants';
export default () => {
const el = document.getElementById('progress-bar');
if (!el) return null;
return new Vue({
el,
render(createElement) {
return createElement(ProgressBar, {
props: { steps: SIGNUP_ONBOARDING_FLOW_STEPS, currentStep: STEPS.yourProject },
});
},
});
};
import Vue from 'vue';
import 'ee/registrations/welcome/other_role';
import 'ee/registrations/welcome/jobs_to_be_done';
import { experiment } from '~/experimentation/utils';
import { parseBoolean } from '~/lib/utils/common_utils';
import ProgressBar from '../components/progress_bar.vue';
import {
STEPS,
SUBSCRIPTON_FLOW_STEPS,
SIGNUP_ONBOARDING_FLOW_STEPS,
COMBINED_SIGNUP_FLOW_STEPS,
} from '../constants';
export default () => {
const el = document.getElementById('progress-bar');
if (!el) return null;
const isInSubscriptionFlow = parseBoolean(el.dataset.isInSubscriptionFlow);
const isSignupOnboardingEnabled = parseBoolean(el.dataset.isSignupOnboardingEnabled);
let steps;
if (isInSubscriptionFlow) {
steps = SUBSCRIPTON_FLOW_STEPS;
} else if (isSignupOnboardingEnabled) {
experiment('combined_registration', {
use: () => {
steps = SIGNUP_ONBOARDING_FLOW_STEPS;
},
try: () => {
steps = COMBINED_SIGNUP_FLOW_STEPS;
},
});
}
return new Vue({
el,
render(createElement) {
return createElement(ProgressBar, {
props: { steps, currentStep: STEPS.yourProfile },
});
},
});
};
......@@ -95,6 +95,21 @@ module EE
def combined_registration_experiment
experiment(:combined_registration, user: current_user)
end
override :update_success_path
def update_success_path
if params[:joining_project] == 'true'
bypass_registration_event(:joining_project)
path_for_signed_in_user(current_user)
else
bypass_registration_event(:creating_project)
experiment(:combined_registration, user: current_user).redirect_path(trial_params)
end
end
def bypass_registration_event(event_name)
experiment(:bypass_registration, user: current_user).track(event_name, user: current_user)
end
end
end
end
......@@ -26,9 +26,19 @@ module EE
end
def registration_objective_options
localized_jobs_to_be_done_choices.merge(
joining_team: _('I’m joining my team who’s already on GitLab')
)
options = localized_jobs_to_be_done_choices.dup
experiment(:bypass_registration, user: current_user) do |e|
e.use do
options.merge(
joining_team: _('I’m joining my team who’s already on GitLab')
)
end
e.try do
options
end
e.run
end
end
end
end
- return unless Gitlab.dev_env_or_com?
- experiment(:bypass_registration, user: current_user) do |e|
- e.publish_to_database
- e.try do
.row
.form-group.col-sm-12
= label_tag :joining_project, _('What would you like to do?'), class: 'label-bold'
.form-check.gl-mb-2
= radio_button_tag :joining_project, false, false, required: true, class: 'form-check-input'
= label_tag :joining_project_false, class: 'form-check-label normal' do
= _('Create a new project')
.form-text.gl-text-gray-600
= _('House your files, plan your work, collaborate on code, and more.')
.form-check
= radio_button_tag :joining_project, true, false, required: true, class: 'form-check-input'
= label_tag :joining_project_true, class: 'form-check-label normal' do
= _('Join a project')
.form-text.gl-text-gray-600
= _('Join your team on GitLab and contribute to an existing project')
......@@ -129,6 +129,7 @@ RSpec.describe Registrations::WelcomeController do
describe '#update' do
let(:setup_for_company) { 'false' }
let(:email_opted_in) { '0' }
let(:joining_project) { 'false' }
subject(:update) do
patch :update, params: {
......@@ -137,7 +138,8 @@ RSpec.describe Registrations::WelcomeController do
setup_for_company: setup_for_company,
email_opted_in: email_opted_in,
registration_objective: 'code_storage'
}
},
joining_project: joining_project
}
end
......@@ -251,21 +253,43 @@ RSpec.describe Registrations::WelcomeController do
allow(controller.helpers).to receive(:signup_onboarding_enabled?).and_return(true)
end
context 'when combined_registration is candidate variant' do
before do
allow(controller).to receive(:experiment).and_call_original
stub_experiments(combined_registration: :candidate)
end
context 'when joining_project is "true"', :experiment do
let(:joining_project) { 'true' }
it { is_expected.to redirect_to dashboard_projects_path }
it 'creates a "joining_project" experiment track event' do
expect(experiment(:bypass_registration)).to track(:joining_project, user: user).on_next_instance
it { is_expected.to redirect_to new_users_sign_up_groups_project_path }
subject
end
end
it "doesn't call the force_company_trial experiment" do
expect(controller).not_to receive(:experiment).with(:force_company_trial, user: user)
context 'when joining_project is "false"', :experiment do
it 'creates a "creating_project" experiment track event' do
expect(experiment(:bypass_registration)).to track(:creating_project, user: user).on_next_instance
subject
end
end
context 'when joining_project is "false"' do
context 'when combined_registration is candidate variant' do
before do
allow(controller).to receive(:experiment).and_call_original
stub_experiments(combined_registration: :candidate)
end
it { is_expected.to redirect_to new_users_sign_up_groups_project_path }
it "doesn't call the force_company_trial experiment" do
expect(controller).not_to receive(:experiment).with(:force_company_trial, user: user)
subject
end
end
end
context 'and force_company_trial experiment is candidate' do
let(:setup_for_company) { 'true' }
......
......@@ -17,12 +17,6 @@ RSpec.describe 'Combined registration flow', :js do
expect(page).to have_content('Welcome to GitLab')
page.within('.bar') do
expect(page).to have_content('Your profile')
expect(page).to have_content('Your first project')
expect(page).not_to have_content('Your GitLab group')
end
choose 'My company or team'
click_on 'Continue'
end
......@@ -31,8 +25,6 @@ RSpec.describe 'Combined registration flow', :js do
let(:experiments) { { combined_registration: :candidate } }
it 'A user can create a group and project' do
expect(page).to have_content('Your first project')
page.within '.js-group-path-display' do
expect(page).to have_content('{group}')
end
......@@ -59,8 +51,6 @@ RSpec.describe 'Combined registration flow', :js do
end
it 'a user can create a group and import a project' do
expect(page).to have_content('Your first project')
click_on 'Import'
page.within '.js-import-group-path-display' do
......
......@@ -14,15 +14,11 @@ RSpec.describe 'User sees new onboarding flow', :js do
visit users_sign_up_welcome_path
expect(page).to have_content('Welcome to GitLab')
expect(page).to have_content('Your profile Your GitLab group Your first project')
expect(page).to have_css('li.current', text: 'Your profile')
choose 'Just me'
click_on 'Continue'
expect(page).to have_content('Create your group')
expect(page).to have_content('Your profile Your GitLab group Your first project')
expect(page).to have_css('li.current', text: 'Your GitLab group')
fill_in 'group_name', with: 'test'
......@@ -31,8 +27,6 @@ RSpec.describe 'User sees new onboarding flow', :js do
click_on 'Create group'
expect(page).to have_content('Create/import your first project')
expect(page).to have_content('Your profile Your GitLab group Your first project')
expect(page).to have_css('li.current', text: 'Your first project')
fill_in 'project_name', with: 'test'
......
......@@ -6,50 +6,21 @@ RSpec.describe 'Welcome screen', :js do
let_it_be(:user) { create(:user) }
context 'when on GitLab.com' do
let(:user_has_memberships) { false }
let(:in_subscription_flow) { false }
let(:in_trial_flow) { false }
before do
allow(Gitlab).to receive(:com?).and_return(true)
gitlab_sign_in(user)
allow_any_instance_of(EE::WelcomeHelper).to receive(:user_has_memberships?).and_return(user_has_memberships)
allow_any_instance_of(EE::WelcomeHelper).to receive(:in_subscription_flow?).and_return(in_subscription_flow)
allow_any_instance_of(EE::WelcomeHelper).to receive(:in_trial_flow?).and_return(in_trial_flow)
allow_any_instance_of(EE::WelcomeHelper).to receive(:user_has_memberships?).and_return(false)
allow_any_instance_of(EE::WelcomeHelper).to receive(:in_subscription_flow?).and_return(false)
allow_any_instance_of(EE::WelcomeHelper).to receive(:in_trial_flow?).and_return(false)
visit users_sign_up_welcome_path
end
it 'shows the welcome page with a progress bar' do
it 'shows the welcome page' do
expect(page).to have_content('Welcome to GitLab')
expect(page).to have_content('Your profile Your GitLab group Your first project')
expect(page).to have_content('Continue')
end
context 'when in the subscription flow' do
let(:in_subscription_flow) { true }
it 'shows the progress bar with the correct steps' do
expect(page).to have_content('Your profile Checkout Your GitLab group')
end
end
context 'when user has memberships' do
let(:user_has_memberships) { true }
it 'does not show the progress bar' do
expect(page).not_to have_content('Your profile')
end
end
context 'when in the trial flow' do
let(:in_trial_flow) { true }
it 'does not show the progress bar' do
expect(page).not_to have_content('Your profile')
end
end
it 'allows specifying other for jobs_to_be_done' do
expect(page).not_to have_content('Why are you signing up? (Optional)')
......@@ -86,18 +57,4 @@ RSpec.describe 'Welcome screen', :js do
end
end
end
context 'when not on GitLab.com' do
before do
allow(Gitlab).to receive(:com?).and_return(false)
gitlab_sign_in(user)
visit users_sign_up_welcome_path
end
it 'does not show the progress bar' do
expect(page).not_to have_content('Your profile')
expect(page).to have_content('Get started!')
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe EE::RegistrationsHelper do
include Devise::Test::ControllerHelpers
describe '#signup_username_data_attributes' do
it 'has expected attributes' do
expect(helper.signup_username_data_attributes.keys).to include(:api_path)
......@@ -21,5 +23,16 @@ RSpec.describe EE::RegistrationsHelper do
it '"other" is always the last option' do
expect(shuffled_options.last).to eq(['A different reason', 'other'])
end
context 'when the bypass_registration experiment is candidate', :experiment do
before do
stub_experiments({ bypass_registration: :candidate })
end
it "excludes the joining_team option" do
shuffled_option_values = shuffled_options.map { |item| item.last }
expect(shuffled_option_values).to contain_exactly(*UserDetail.registration_objectives.keys.reject {|k| k == "joining_team"})
end
end
end
end
......@@ -12,13 +12,16 @@ RSpec.describe 'registrations/welcome/show' do
allow(Gitlab).to receive(:com?).and_return(true)
end
describe 'forms and progress bar' do
describe 'forms and progress bar', :experiments do
let_it_be(:user_other_role_details_enabled) { false }
let(:experiments) { {} }
before do
allow(view).to receive(:redirect_path).and_return(redirect_path)
allow(view).to receive(:signup_onboarding_enabled?).and_return(signup_onboarding_enabled)
stub_feature_flags(user_other_role_details: user_other_role_details_enabled)
stub_experiments(experiments)
render
end
......@@ -51,6 +54,16 @@ RSpec.describe 'registrations/welcome/show' do
it { is_expected_to_have_progress_bar(status: show_progress_bar) }
context 'bypass_registration experiment' do
it { is_expected.not_to have_selector('#joining_project_true') }
context 'when in the candidate variant' do
let(:experiments) { { bypass_registration: :candidate } }
it { is_expected.to have_selector('#joining_project_true') }
end
end
context 'feature flag other_role_details is enabled' do
let_it_be(:user_other_role_details_enabled) { true }
......
......@@ -9607,6 +9607,9 @@ msgstr ""
msgid "Create a new issue"
msgstr ""
msgid "Create a new project"
msgstr ""
msgid "Create a new repository"
msgstr ""
......@@ -16995,6 +16998,9 @@ msgstr ""
msgid "Hour (UTC)"
msgstr ""
msgid "House your files, plan your work, collaborate on code, and more."
msgstr ""
msgid "Housekeeping"
msgstr ""
......@@ -19808,6 +19814,12 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
msgid "Join a project"
msgstr ""
msgid "Join your team on GitLab and contribute to an existing project"
msgstr ""
msgid "Joined %{time_ago}"
msgstr ""
......@@ -38542,6 +38554,9 @@ msgstr ""
msgid "What will you use this group for?"
msgstr ""
msgid "What would you like to do?"
msgstr ""
msgid "What's new"
msgstr ""
......
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