Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects_controller.rb6
-rw-r--r--app/views/projects/_invite_members.html.haml8
-rw-r--r--app/views/projects/empty.html.haml2
-rw-r--r--doc/administration/packages/container_registry.md6
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql5
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json10
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md5
-rw-r--r--lib/api/boards_responses.rb6
-rw-r--r--lib/gitlab/checks/push_check.rb10
-rw-r--r--lib/gitlab/deploy_key_access.rb4
-rw-r--r--lib/gitlab/experimentation.rb3
-rw-r--r--lib/gitlab/user_access.rb4
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/controllers/projects_controller_spec.rb53
-rw-r--r--spec/features/projects/show/developer_views_empty_project_instructions_spec.rb20
-rw-r--r--spec/features/projects/show/user_sees_git_instructions_spec.rb6
-rw-r--r--spec/fixtures/api/schemas/list.json2
-rw-r--r--spec/frontend_integration/ide/user_opens_file_spec.js4
-rw-r--r--spec/lib/gitlab/checks/push_check_spec.rb23
-rw-r--r--spec/lib/gitlab/deploy_key_access_spec.rb12
-rw-r--r--spec/lib/gitlab/user_access_spec.rb20
-rw-r--r--spec/views/projects/empty.html.haml_spec.rb82
22 files changed, 223 insertions, 77 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 3ceba5de7d3..ccc1a972a7d 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -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
diff --git a/app/views/projects/_invite_members.html.haml b/app/views/projects/_invite_members.html.haml
new file mode 100644
index 00000000000..ef030cabc93
--- /dev/null
+++ b/app/views/projects/_invite_members.html.haml
@@ -0,0 +1,8 @@
+%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' }
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 2e0bb3b8529..2936eff45df 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -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')
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 4a4c08ebffd..633129e98bd 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -101,7 +101,7 @@ If `auth` is not set up, users can pull Docker images without authentication.
There are two ways you can configure the Registry's external domain. Either:
- [Use the existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain).
- The Registry listens on a port and reuses GitLab's TLS certificate.
+ The Registry listens on a port and reuses the TLS certificate from GitLab.
- [Use a completely separate domain](#configure-container-registry-under-its-own-domain) with a new TLS certificate
for that domain.
@@ -612,8 +612,8 @@ You can use GitLab as an auth endpoint with an external container registry.
gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
```
- `gitlab_rails['registry_enabled'] = true` is needed to enable GitLab's
- Container Registry features and authentication endpoint. GitLab's bundled
+ `gitlab_rails['registry_enabled'] = true` is needed to enable GitLab
+ Container Registry features and authentication endpoint. The GitLab bundled
Container Registry service does not start, even with this enabled.
1. A certificate-key pair is required for GitLab and the external container
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index f065d985f0a..754f4d7cca3 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -2120,6 +2120,11 @@ input BoardListCreateInput {
clientMutationId: String
"""
+ Global ID of an existing iteration
+ """
+ iterationId: IterationID
+
+ """
Global ID of an existing label
"""
labelId: LabelID
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index b5ff3a42707..f0a99a7e522 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -5611,6 +5611,16 @@
"defaultValue": null
},
{
+ "name": "iterationId",
+ "description": "Global ID of an existing iteration",
+ "type": {
+ "kind": "SCALAR",
+ "name": "IterationID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "assigneeId",
"description": "Global ID of an existing user",
"type": {
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 3c8ffc8e8c4..213c8c4116a 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -51,10 +51,13 @@ To enforce confirmation of the email address used for new sign ups:
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4315) in GitLab 13.6.
-When the number of users reaches the user cap, any user who is added or requests access must be
+When the number of billable users reaches the user cap, any user who is added or requests access must be
[approved](../approving_users.md#approving-a-user) by an administrator before they can start using
their account.
+If an administrator increases or removes the user cap, the users in pending approval state will be
+automatically approved in a background job.
+
## Soft email confirmation
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47003) in GitLab 12.2.
diff --git a/lib/api/boards_responses.rb b/lib/api/boards_responses.rb
index b83fa32ff22..89355c84401 100644
--- a/lib/api/boards_responses.rb
+++ b/lib/api/boards_responses.rb
@@ -45,7 +45,7 @@ module API
def create_list
create_list_service =
- ::Boards::Lists::CreateService.new(board_parent, current_user, create_list_params)
+ ::Boards::Lists::CreateService.new(board_parent, current_user, declared_params.compact.with_indifferent_access)
response = create_list_service.execute(board)
@@ -56,10 +56,6 @@ module API
end
end
- def create_list_params
- params.slice(:label_id)
- end
-
def move_list(list)
move_list_service =
::Boards::Lists::MoveService.new(board_parent, current_user, { position: params[:position].to_i })
diff --git a/lib/gitlab/checks/push_check.rb b/lib/gitlab/checks/push_check.rb
index 0f0d8bb82ec..47aa25aae4c 100644
--- a/lib/gitlab/checks/push_check.rb
+++ b/lib/gitlab/checks/push_check.rb
@@ -14,17 +14,9 @@ module Gitlab
private
def can_push?
- user_access_can_push? ||
+ user_access.can_push_for_ref?(ref) ||
project.branch_allows_collaboration?(user_access.user, branch_name)
end
-
- def user_access_can_push?
- if Feature.enabled?(:deploy_keys_on_protected_branches, project)
- user_access.can_push_to_branch?(ref)
- else
- user_access.can_do_action?(:push_code)
- end
- end
end
end
end
diff --git a/lib/gitlab/deploy_key_access.rb b/lib/gitlab/deploy_key_access.rb
index 97fd6db407b..ca16582d2b4 100644
--- a/lib/gitlab/deploy_key_access.rb
+++ b/lib/gitlab/deploy_key_access.rb
@@ -8,6 +8,10 @@ module Gitlab
@container = container
end
+ def can_push_for_ref?(ref)
+ can_push_to_branch?(ref)
+ end
+
private
attr_reader :deploy_key
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index c9b7c4c949e..94523813662 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -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
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index eec89e1ab72..0af7ad6ec17 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -81,6 +81,10 @@ module Gitlab
end
end
+ def can_push_for_ref?(_)
+ can_do_action?(:push_code)
+ end
+
private
def can_push?
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c8907263de2..f0336bb3af6 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -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 ""
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 96015f7e830..bd7ef3db8b6 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -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
diff --git a/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb
deleted file mode 100644
index 8d239cb2cbf..00000000000
--- a/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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
diff --git a/spec/features/projects/show/user_sees_git_instructions_spec.rb b/spec/features/projects/show/user_sees_git_instructions_spec.rb
index 3b77fd7eebf..febdb70de86 100644
--- a/spec/features/projects/show/user_sees_git_instructions_spec.rb
+++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb
@@ -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'
diff --git a/spec/fixtures/api/schemas/list.json b/spec/fixtures/api/schemas/list.json
index f894ff584c8..65e140f9e28 100644
--- a/spec/fixtures/api/schemas/list.json
+++ b/spec/fixtures/api/schemas/list.json
@@ -10,7 +10,7 @@
"id": { "type": "integer" },
"list_type": {
"type": "string",
- "enum": ["backlog", "label", "closed"]
+ "enum": ["backlog", "label", "iteration", "closed"]
},
"label": {
"type": ["object", "null"],
diff --git a/spec/frontend_integration/ide/user_opens_file_spec.js b/spec/frontend_integration/ide/user_opens_file_spec.js
index 7fa6dcecc9e..98a73c7a029 100644
--- a/spec/frontend_integration/ide/user_opens_file_spec.js
+++ b/spec/frontend_integration/ide/user_opens_file_spec.js
@@ -3,7 +3,9 @@ import { screen } from '@testing-library/dom';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
-describe('IDE: User opens a file in the Web IDE', () => {
+// https://gitlab.com/gitlab-org/gitlab/-/issues/293654#note_466432769
+// eslint-disable-next-line jest/no-disabled-tests
+describe.skip('IDE: User opens a file in the Web IDE', () => {
useOverclockTimers();
let vm;
diff --git a/spec/lib/gitlab/checks/push_check_spec.rb b/spec/lib/gitlab/checks/push_check_spec.rb
index 3ec38ec83bb..262438256b4 100644
--- a/spec/lib/gitlab/checks/push_check_spec.rb
+++ b/spec/lib/gitlab/checks/push_check_spec.rb
@@ -12,11 +12,32 @@ RSpec.describe Gitlab::Checks::PushCheck do
context 'when the user is not allowed to push to the repo' do
it 'raises an error' do
- expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+ expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false)
expect(project).to receive(:branch_allows_collaboration?).with(user_access.user, 'master').and_return(false)
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to push code to this project.')
end
end
+
+ context 'when using a DeployKeyAccess instance' do
+ let(:deploy_key) { create(:deploy_key) }
+ let(:user_access) { Gitlab::DeployKeyAccess.new(deploy_key, container: project) }
+
+ context 'when the deploy key cannot push to the targetted branch' do
+ it 'raises an error' do
+ allow(user_access).to receive(:can_push_to_branch?).and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to push code to this project.')
+ end
+ end
+
+ context 'when the deploy key can push to the targetted branch' do
+ it 'is valid' do
+ allow(user_access).to receive(:can_push_to_branch?).and_return(true)
+
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/deploy_key_access_spec.rb b/spec/lib/gitlab/deploy_key_access_spec.rb
index 7989b427a85..e186e993d8f 100644
--- a/spec/lib/gitlab/deploy_key_access_spec.rb
+++ b/spec/lib/gitlab/deploy_key_access_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Gitlab::DeployKeyAccess do
end
end
- describe '#can_push_to_branch?' do
+ describe '#can_push_for_ref?' do
context 'push to a protected branch of this project via a deploy key' do
before do
create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
@@ -33,7 +33,7 @@ RSpec.describe Gitlab::DeployKeyAccess do
context 'when the project has active deploy key owned by this user' do
it 'returns true' do
- expect(access.can_push_to_branch?(protected_branch.name)).to be_truthy
+ expect(access.can_push_for_ref?(protected_branch.name)).to be_truthy
end
end
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::DeployKeyAccess do
let(:deploy_key) { create(:deploy_key, user: create(:user)) }
it 'returns false' do
- expect(access.can_push_to_branch?(protected_branch.name)).to be_falsey
+ expect(access.can_push_for_ref?(protected_branch.name)).to be_falsey
end
end
@@ -49,15 +49,15 @@ RSpec.describe Gitlab::DeployKeyAccess do
let(:another_branch) { create(:protected_branch, :no_one_can_push, name: 'another_branch', project: project) }
it 'returns false when trying to push to that other branch' do
- expect(access.can_push_to_branch?(another_branch.name)).to be_falsey
+ expect(access.can_push_for_ref?(another_branch.name)).to be_falsey
end
context 'and the deploy key added for the first protected branch is also added for this other branch' do
it 'returns true for both protected branches' do
create(:protected_branch_push_access_level, protected_branch: another_branch, deploy_key: deploy_key)
- expect(access.can_push_to_branch?(protected_branch.name)).to be_truthy
- expect(access.can_push_to_branch?(another_branch.name)).to be_truthy
+ expect(access.can_push_for_ref?(protected_branch.name)).to be_truthy
+ expect(access.can_push_for_ref?(another_branch.name)).to be_truthy
end
end
end
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index d6b1e3b2d4b..748a8336a25 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -310,4 +310,24 @@ RSpec.describe Gitlab::UserAccess do
end
end
end
+
+ describe '#can_push_for_ref?' do
+ let(:ref) { 'test_ref' }
+
+ context 'when user cannot push_code to a project repository (eg. as a guest)' do
+ it 'is false' do
+ project.add_user(user, :guest)
+
+ expect(access.can_push_for_ref?(ref)).to be_falsey
+ end
+ end
+
+ context 'when user can push_code to a project repository (eg. as a developer)' do
+ it 'is true' do
+ project.add_user(user, :developer)
+
+ expect(access.can_push_for_ref?(ref)).to be_truthy
+ end
+ end
+ end
end
diff --git a/spec/views/projects/empty.html.haml_spec.rb b/spec/views/projects/empty.html.haml_spec.rb
new file mode 100644
index 00000000000..de83722160e
--- /dev/null
+++ b/spec/views/projects/empty.html.haml_spec.rb
@@ -0,0 +1,82 @@
+# 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