Commit 2fb5ef0c authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'jejacks0n/jobs-to-be-done' into 'master'

Jobs to be done experiment in first mile -- asking for objective [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!60038
parents 39c7d5ba d2df1c25
...@@ -36,6 +36,10 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp ...@@ -36,6 +36,10 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
@excluded = true @excluded = true
end end
def control_behavior
# define a default nil control behavior so we can omit it when not needed
end
private private
def feature_flag_name def feature_flag_name
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
= f.text_field :other_role, class: 'form-control' = f.text_field :other_role, class: 'form-control'
= render_if_exists "registrations/welcome/setup_for_company", f: f = render_if_exists "registrations/welcome/setup_for_company", f: f
= render 'devise/shared/email_opted_in', f: f = render 'devise/shared/email_opted_in', f: f
= render_if_exists "registrations/welcome/jobs_to_be_done", f: f
.row .row
.form-group.col-sm-12.gl-mb-0 .form-group.col-sm-12.gl-mb-0
- if partial_exists? "registrations/welcome/button" - if partial_exists? "registrations/welcome/button"
......
---
name: jobs_to_be_done
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60038
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285564
milestone: '13.12'
type: experiment
group: group::adoption
default_enabled: false
import Vue from 'vue'; import Vue from 'vue';
import 'ee/registrations/welcome/other_role'; import 'ee/registrations/welcome/other_role';
import 'ee/registrations/welcome/jobs_to_be_done';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import ProgressBar from '../components/progress_bar.vue'; import ProgressBar from '../components/progress_bar.vue';
import { STEPS, SUBSCRIPTON_FLOW_STEPS, SIGNUP_ONBOARDING_FLOW_STEPS } from '../constants'; import { STEPS, SUBSCRIPTON_FLOW_STEPS, SIGNUP_ONBOARDING_FLOW_STEPS } from '../constants';
......
import { getExperimentContexts } from '~/experimentation/utils';
import Tracking from '~/tracking';
const select = document.querySelector('.js-jobs-to-be-done-dropdown');
if (select) {
Tracking.enableFormTracking(
{ fields: { whitelist: ['jobs_to_be_done', 'jobs_to_be_done_other'] } },
getExperimentContexts('jobs_to_be_done'),
);
select.addEventListener('change', () => {
const otherSelected = select.value === 'other';
document
.querySelector('.js-jobs-to-be-done-other-group')
.classList.toggle('hidden', !otherSelected);
});
}
...@@ -23,6 +23,8 @@ module Registrations ...@@ -23,6 +23,8 @@ module Registrations
@group = Groups::CreateService.new(current_user, group_params).execute @group = Groups::CreateService.new(current_user, group_params).execute
if @group.persisted? if @group.persisted?
experiment(:jobs_to_be_done, user: current_user)
.track(:create_group, namespace: @group)
create_successful_flow create_successful_flow
else else
render action: :new render action: :new
......
...@@ -33,6 +33,8 @@ module Registrations ...@@ -33,6 +33,8 @@ module Registrations
experiment(:registrations_group_invite, actor: current_user) experiment(:registrations_group_invite, actor: current_user)
.track(:signup_successful, property: @project.namespace_id.to_s) .track(:signup_successful, property: @project.namespace_id.to_s)
experiment(:jobs_to_be_done, user: current_user)
.track(:create_project, project: @project)
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)
......
- experiment(:jobs_to_be_done, user: current_user) do |e|
- e.try do
.row
.form-group.col-sm-12
= label_tag :jobs_to_be_done, _("I'm signing up for GitLab because:")
= select_tag :jobs_to_be_done,
options_for_select([_('I want to learn the basics of Git'),
_('I want to move my repository to GitLab from somewhere else'),
_('I want to explore GitLab to see if it’s worth switching to'),
_('I want to use GitLab CI with my existing repository'),
_('I’m joining my team who’s already on GitLab'),
[_('A different reason'), 'other']]),
include_blank: _('Please select...'), class: 'form-control js-jobs-to-be-done-dropdown'
.row
.form-group.col-sm-12.js-jobs-to-be-done-other-group.hidden
= label_tag :jobs_to_be_done_other, _('Why are you signing up? (Optional)')
= text_field_tag :jobs_to_be_done_other, '', class: 'form-control'
...@@ -137,6 +137,17 @@ RSpec.describe Registrations::GroupsController do ...@@ -137,6 +137,17 @@ RSpec.describe Registrations::GroupsController do
expect { subject }.to change { Group.count }.by(1) expect { subject }.to change { Group.count }.by(1)
end end
it 'tracks an event for the jobs_to_be_done experiment', :experiment do
stub_experiments(jobs_to_be_done: :candidate)
expect(experiment(:jobs_to_be_done)).to track(:create_group, namespace: an_instance_of(Group))
.on_next_instance
.for(:candidate)
.with_context(user: user)
subject
end
context 'when the trial onboarding is active - apply_trial_for_trial_onboarding_flow' do context 'when the trial onboarding is active - apply_trial_for_trial_onboarding_flow' do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:trial_onboarding_flow_params) { { trial_onboarding_flow: true, glm_source: 'about.gitlab.com', glm_content: 'content' } } let_it_be(:trial_onboarding_flow_params) { { trial_onboarding_flow: true, glm_source: 'about.gitlab.com', glm_content: 'content' } }
......
...@@ -84,6 +84,17 @@ RSpec.describe Registrations::ProjectsController do ...@@ -84,6 +84,17 @@ RSpec.describe Registrations::ProjectsController do
expect(namespace.projects.find_by_name(s_('Learn GitLab'))).to be_import_finished expect(namespace.projects.find_by_name(s_('Learn GitLab'))).to be_import_finished
end end
it 'tracks an event for the jobs_to_be_done experiment', :experiment do
stub_experiments(jobs_to_be_done: :candidate)
expect(experiment(:jobs_to_be_done)).to track(:create_project, project: an_instance_of(Project))
.on_next_instance
.for(:candidate)
.with_context(user: user)
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)
......
...@@ -5,12 +5,15 @@ require 'spec_helper' ...@@ -5,12 +5,15 @@ require 'spec_helper'
RSpec.describe 'Welcome screen', :js do RSpec.describe 'Welcome screen', :js do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:experiments) { {} }
context 'when on GitLab.com' do context 'when on GitLab.com' do
let(:user_has_memberships) { false } let(:user_has_memberships) { false }
let(:in_subscription_flow) { false } let(:in_subscription_flow) { false }
let(:in_trial_flow) { false } let(:in_trial_flow) { false }
before do before do
stub_experiments(experiments)
allow(Gitlab).to receive(:com?).and_return(true) allow(Gitlab).to receive(:com?).and_return(true)
gitlab_sign_in(user) 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(:user_has_memberships?).and_return(user_has_memberships)
...@@ -50,6 +53,20 @@ RSpec.describe 'Welcome screen', :js do ...@@ -50,6 +53,20 @@ RSpec.describe 'Welcome screen', :js do
end end
end end
context 'with the jobs_to_be_done experiment' do
let(:experiments) { { jobs_to_be_done: :candidate } }
it 'allows specifying other for the jobs_to_be_done experiment', :experiment do
expect(page).not_to have_content('Why are you signing up? (Optional)')
select 'A different reason', from: 'jobs_to_be_done'
expect(page).to have_content('Why are you signing up? (Optional)')
fill_in 'jobs_to_be_done_other', with: 'My reason'
end
end
context 'email opt in' do context 'email opt in' do
it 'does not show the email opt in checkbox when setting up for a company' do it 'does not show the email opt in checkbox when setting up for a company' do
expect(page).not_to have_selector('input[name="user[email_opted_in]', visible: true) expect(page).not_to have_selector('input[name="user[email_opted_in]', visible: true)
......
...@@ -6,8 +6,9 @@ RSpec.describe 'registrations/welcome/show' do ...@@ -6,8 +6,9 @@ RSpec.describe 'registrations/welcome/show' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
describe 'forms and progress bar' do describe 'forms and progress bar' do
let_it_be(:user) { User.new } let_it_be(:user) { create(:user) }
let_it_be(:user_other_role_details_enabled) { false } let_it_be(:user_other_role_details_enabled) { false }
let_it_be(:stubbed_experiments) { {} }
before do before do
allow(view).to receive(:current_user).and_return(user) allow(view).to receive(:current_user).and_return(user)
...@@ -15,6 +16,7 @@ RSpec.describe 'registrations/welcome/show' do ...@@ -15,6 +16,7 @@ RSpec.describe 'registrations/welcome/show' do
allow(view).to receive(:signup_onboarding_enabled?).and_return(signup_onboarding_enabled) allow(view).to receive(:signup_onboarding_enabled?).and_return(signup_onboarding_enabled)
allow(Gitlab).to receive(:com?).and_return(true) allow(Gitlab).to receive(:com?).and_return(true)
stub_feature_flags(user_other_role_details: user_other_role_details_enabled) stub_feature_flags(user_other_role_details: user_other_role_details_enabled)
stub_experiments(stubbed_experiments)
render render
end end
...@@ -55,6 +57,15 @@ RSpec.describe 'registrations/welcome/show' do ...@@ -55,6 +57,15 @@ RSpec.describe 'registrations/welcome/show' do
is_expected.to have_selector('input[type="text"][name="user[other_role]"]') is_expected.to have_selector('input[type="text"][name="user[other_role]"]')
end end
end end
context 'experiment(:jobs_to_be_done)' do
let_it_be(:stubbed_experiments) { { jobs_to_be_done: :candidate } }
it 'renders a select and text field for additional information' do
is_expected.to have_selector('select[name="jobs_to_be_done"]')
is_expected.to have_selector('input[name="jobs_to_be_done_other"]', visible: false)
end
end
end end
end end
......
...@@ -1394,6 +1394,9 @@ msgstr "" ...@@ -1394,6 +1394,9 @@ msgstr ""
msgid "A description is required" msgid "A description is required"
msgstr "" msgstr ""
msgid "A different reason"
msgstr ""
msgid "A file has been changed." msgid "A file has been changed."
msgstr "" msgstr ""
...@@ -16420,9 +16423,24 @@ msgstr "" ...@@ -16420,9 +16423,24 @@ msgstr ""
msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)" msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
msgstr "" msgstr ""
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
msgid "I want to learn the basics of Git"
msgstr ""
msgid "I want to move my repository to GitLab from somewhere else"
msgstr ""
msgid "I want to use GitLab CI with my existing repository"
msgstr ""
msgid "I'd like to receive updates about GitLab via email" msgid "I'd like to receive updates about GitLab via email"
msgstr "" msgstr ""
msgid "I'm signing up for GitLab because:"
msgstr ""
msgid "ID" msgid "ID"
msgstr "" msgstr ""
...@@ -18435,6 +18453,9 @@ msgstr "" ...@@ -18435,6 +18453,9 @@ msgstr ""
msgid "I’m familiar with the basics of DevOps." msgid "I’m familiar with the basics of DevOps."
msgstr "" msgstr ""
msgid "I’m joining my team who’s already on GitLab"
msgstr ""
msgid "I’m not familiar with the basics of DevOps." msgid "I’m not familiar with the basics of DevOps."
msgstr "" msgstr ""
...@@ -24535,6 +24556,9 @@ msgstr "" ...@@ -24535,6 +24556,9 @@ msgstr ""
msgid "Please select what should be included in each exported requirement." msgid "Please select what should be included in each exported requirement."
msgstr "" msgstr ""
msgid "Please select..."
msgstr ""
msgid "Please set a new password before proceeding." msgid "Please set a new password before proceeding."
msgstr "" msgstr ""
...@@ -36503,6 +36527,9 @@ msgstr "" ...@@ -36503,6 +36527,9 @@ msgstr ""
msgid "Who will be using this GitLab trial?" msgid "Who will be using this GitLab trial?"
msgstr "" msgstr ""
msgid "Why are you signing up? (Optional)"
msgstr ""
msgid "Wiki" msgid "Wiki"
msgstr "" msgstr ""
......
...@@ -25,6 +25,12 @@ RSpec.describe ApplicationExperiment, :experiment do ...@@ -25,6 +25,12 @@ RSpec.describe ApplicationExperiment, :experiment do
described_class.new('namespaced/stub') described_class.new('namespaced/stub')
end end
it "doesn't raise an exception without a defined control" do
# because we have a default behavior defined
expect { experiment('namespaced/stub') { } }.not_to raise_error
end
describe "enabled" do describe "enabled" do
before do before do
allow(subject).to receive(:enabled?).and_call_original allow(subject).to receive(:enabled?).and_call_original
......
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'registrations/welcome/show' do RSpec.describe 'registrations/welcome/show' do
let(:is_gitlab_com) { false } let(:is_gitlab_com) { false }
let_it_be(:user) { User.new } let_it_be(:user) { create(:user) }
before do before do
allow(view).to receive(:current_user).and_return(user) allow(view).to receive(:current_user).and_return(user)
......
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