Commit caa4847e authored by Mark Chao's avatar Mark Chao

Merge branch...

Merge branch '262014-experiment-add-an-invite-team-members-cta-to-the-project-empty-state' into 'master'

Add invite members button the project empty state

See merge request gitlab-org/gitlab!49588
parents 6f360232 95e63965
......@@ -325,7 +325,11 @@ class ProjectsController < Projects::ApplicationController
if can?(current_user, :download_code, @project)
return render 'projects/no_repo' unless @project.repository_exists?
render 'projects/empty' if @project.empty_repo?
if @project.empty_repo?
record_experiment_user(:invite_members_empty_project_version_a)
render 'projects/empty'
end
else
if can?(current_user, :read_wiki, @project)
@wiki = @project.wiki
......
%h4.gl-mt-0.gl-mb-3{ data: { testid: 'invite-member-section',
track_label: 'invite_members_empty_project',
track_event: 'render' } }
= s_('InviteMember|Invite your team')
%p= s_('InviteMember|Add members to this project and start collaborating with your team.')
= link_to s_('InviteMember|Invite members'), project_project_members_path(@project, sort: :access_level_desc),
class: 'gl-button btn btn-success gl-mb-8 gl-xs-w-full',
data: { track_event: 'click_button', track_label: 'invite_members_empty_project' }
......@@ -6,6 +6,8 @@
= render "home_panel"
= render "invite_members" if experiment_enabled?(:invite_members_empty_project_version_a) && can_import_members?
%h4.gl-mt-0.gl-mb-3
= _('The repository for this project is empty')
......
......@@ -84,6 +84,9 @@ module Gitlab
},
trial_registration_with_social_signin: {
tracking_category: 'Growth::Conversion::Experiment::TrialRegistrationWithSocialSigning'
},
invite_members_empty_project_version_a: {
tracking_category: 'Growth::Expansion::Experiment::InviteMembersEmptyProjectVersionA'
}
}.freeze
......
......@@ -15207,12 +15207,21 @@ msgstr ""
msgid "InviteMembers|Invite team members"
msgstr ""
msgid "InviteMember|Add members to this project and start collaborating with your team."
msgstr ""
msgid "InviteMember|Invite Members (optional)"
msgstr ""
msgid "InviteMember|Invite another member"
msgstr ""
msgid "InviteMember|Invite members"
msgstr ""
msgid "InviteMember|Invite your team"
msgstr ""
msgid "InviteMember|Invited users will be added with developer level permissions. %{linkStart}View the documentation%{linkEnd} to see how to change this later."
msgstr ""
......
......@@ -6,15 +6,15 @@ RSpec.describe ProjectsController do
include ExternalAuthorizationServiceHelpers
include ProjectForksHelper
let(:project) { create(:project, service_desk_enabled: false) }
let(:public_project) { create(:project, :public) }
let(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, service_desk_enabled: false) }
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') }
let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') }
describe 'GET new' do
context 'with an authenticated user' do
let(:group) { create(:group) }
let_it_be(:group) { create(:group) }
before do
sign_in(user)
......@@ -68,7 +68,7 @@ RSpec.describe ProjectsController do
include DesignManagementTestHelpers
render_views
let(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) }
let_it_be(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) }
before do
enable_design_management
......@@ -227,10 +227,12 @@ RSpec.describe ProjectsController do
end
context "project with empty repo" do
let(:empty_project) { create(:project_empty_repo, :public) }
let_it_be(:empty_project) { create(:project_empty_repo, :public) }
before do
sign_in(user)
allow(controller).to receive(:record_experiment_user).with(:invite_members_empty_project_version_a)
end
User.project_views.keys.each do |project_view|
......@@ -241,15 +243,16 @@ RSpec.describe ProjectsController do
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
end
it "renders the empty project view" do
it "renders the empty project view and records the experiment user", :aggregate_failures do
expect(response).to render_template('empty')
expect(controller).to have_received(:record_experiment_user).with(:invite_members_empty_project_version_a)
end
end
end
end
context "project with broken repo" do
let(:empty_project) { create(:project_broken_repo, :public) }
let_it_be(:empty_project) { create(:project_broken_repo, :public) }
before do
sign_in(user)
......@@ -273,7 +276,7 @@ RSpec.describe ProjectsController do
end
context "rendering default project view" do
let(:public_project) { create(:project, :public, :repository) }
let_it_be(:public_project) { create(:project, :public, :repository) }
render_views
......@@ -397,8 +400,8 @@ RSpec.describe ProjectsController do
end
describe 'POST #archive' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
before do
sign_in(user)
......@@ -445,8 +448,8 @@ RSpec.describe ProjectsController do
end
describe 'POST #unarchive' do
let(:group) { create(:group) }
let(:project) { create(:project, :archived, group: group) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :archived, group: group) }
before do
sign_in(user)
......@@ -493,8 +496,8 @@ RSpec.describe ProjectsController do
end
describe '#housekeeping' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let(:housekeeping) { Projects::HousekeepingService.new(project) }
context 'when authenticated as owner' do
......@@ -666,13 +669,13 @@ RSpec.describe ProjectsController do
end
context 'hashed storage' do
let(:project) { create(:project, :repository) }
let_it_be(:project) { create(:project, :repository) }
it_behaves_like 'updating a project'
end
context 'legacy storage' do
let(:project) { create(:project, :repository, :legacy_storage) }
let_it_be(:project) { create(:project, :repository, :legacy_storage) }
it_behaves_like 'updating a project'
end
......@@ -745,9 +748,9 @@ RSpec.describe ProjectsController do
describe '#transfer', :enable_admin_mode do
render_views
let(:project) { create(:project, :repository) }
let(:admin) { create(:admin) }
let(:new_namespace) { create(:namespace) }
let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:admin) { create(:admin) }
let_it_be(:new_namespace) { create(:namespace) }
it 'updates namespace' do
sign_in(admin)
......@@ -791,7 +794,7 @@ RSpec.describe ProjectsController do
end
describe "#destroy", :enable_admin_mode do
let(:admin) { create(:admin) }
let_it_be(:admin) { create(:admin) }
it "redirects to the dashboard", :sidekiq_might_not_need_inline do
controller.instance_variable_set(:@project, project)
......@@ -971,7 +974,7 @@ RSpec.describe ProjectsController do
end
describe "GET refs" do
let(:project) { create(:project, :public, :repository) }
let_it_be(:project) { create(:project, :public, :repository) }
it 'gets a list of branches and tags' do
get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' }
......@@ -1043,7 +1046,7 @@ RSpec.describe ProjectsController do
end
context 'state filter on references' do
let(:issue) { create(:issue, :closed, project: public_project) }
let_it_be(:issue) { create(:issue, :closed, project: public_project) }
let(:merge_request) { create(:merge_request, :closed, target_project: public_project) }
it 'renders JSON body with state filter for issues' do
......@@ -1366,7 +1369,7 @@ RSpec.describe ProjectsController do
end
context 'private project with token authentication' do
let(:private_project) { create(:project, :private) }
let_it_be(:private_project) { create(:project, :private) }
it_behaves_like 'authenticates sessionless user', :show, :atom, ignore_incrementing: true do
before do
......@@ -1378,7 +1381,7 @@ RSpec.describe ProjectsController do
end
context 'public project with token authentication' do
let(:public_project) { create(:project, :public) }
let_it_be(:public_project) { create(:project, :public) }
it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
before do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Show > Developer views empty project instructions' do
let(:project) { create(:project, :empty_repo) }
let(:developer) { create(:user) }
before do
project.add_developer(developer)
sign_in(developer)
end
it 'displays "git clone" instructions' do
visit project_path(project)
expect(page).to have_content("git clone")
end
end
......@@ -122,13 +122,11 @@ RSpec.describe 'Projects > Show > User sees Git instructions' do
context 'when project is not empty' do
let_it_be(:project) { create(:project, :public, :repository) }
before do
visit(project_path(project))
end
context 'when not signed in' do
before do
allow(Gitlab.config.gitlab).to receive(:host).and_return('www.example.com')
visit(project_path(project))
end
include_examples 'shows details of non empty project'
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/empty' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { ProjectPresenter.new(create(:project, :empty_repo), current_user: user) }
before do
allow(view).to receive(:experiment_enabled?).and_return(true)
allow(view).to receive(:current_user).and_return(user)
assign(:project, project)
end
context 'when user can push code on the project' do
before do
allow(view).to receive(:can?).with(user, :push_code, project).and_return(true)
end
it 'displays "git clone" instructions' do
render
expect(rendered).to have_content("git clone")
end
end
context 'when user can not push code on the project' do
before do
allow(view).to receive(:can?).with(user, :push_code, project).and_return(false)
end
it 'does not display "git clone" instructions' do
render
expect(rendered).not_to have_content("git clone")
end
end
describe 'invite_members_empty_project_version_a experiment' do
let(:can_import_members) { true }
before do
allow(view).to receive(:can_import_members?).and_return(can_import_members)
end
shared_examples_for 'no invite member info' do
it 'does not show invite member info' do
render
expect(rendered).not_to have_content('Invite your team')
end
end
context 'when experiment is enabled' do
it 'shows invite members info', :aggregate_failures do
render
expect(rendered).to have_selector('[data-track-event=render]')
expect(rendered).to have_selector('[data-track-label=invite_members_empty_project]', count: 2)
expect(rendered).to have_content('Invite your team')
expect(rendered).to have_content('Add members to this project and start collaborating with your team.')
expect(rendered).to have_link('Invite members', href: project_project_members_path(project, sort: :access_level_desc))
expect(rendered).to have_selector('[data-track-event=click_button]')
end
context 'when user does not have permissions to invite members' do
let(:can_import_members) { false }
it_behaves_like 'no invite member info'
end
end
context 'when experiment is not enabled' do
before do
allow(view).to receive(:experiment_enabled?)
.with(:invite_members_empty_project_version_a).and_return(false)
end
it_behaves_like 'no invite member info'
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