summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-22 21:10:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-22 21:10:06 +0000
commitc66b5f750f309b995529d63708b482bcc4e3d35c (patch)
tree1baa97efbc3a37828d763cf4ef4ef6668da864b7 /spec
parent9a14667521070786dbf3e61409a50ef6ef72e7ff (diff)
downloadgitlab-ce-c66b5f750f309b995529d63708b482bcc4e3d35c.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects_controller_spec.rb2
-rw-r--r--spec/helpers/invite_members_helper_spec.rb65
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb3
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb2
-rw-r--r--spec/models/snippet_repository_storage_move_spec.rb2
-rw-r--r--spec/requests/api/terraform/state_spec.rb37
-rw-r--r--spec/support/matchers/be_sorted.rb71
-rw-r--r--spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/workers/update_repository_move_shared_examples.rb39
-rw-r--r--spec/support_specs/matchers/be_sorted_spec.rb33
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb111
-rw-r--r--spec/workers/project_update_repository_storage_worker_spec.rb42
-rw-r--r--spec/workers/snippet_update_repository_storage_worker_spec.rb15
13 files changed, 346 insertions, 80 deletions
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index bd7ef3db8b6..51ac005883e 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -232,7 +232,7 @@ RSpec.describe ProjectsController do
before do
sign_in(user)
- allow(controller).to receive(:record_experiment_user).with(:invite_members_empty_project_version_a)
+ allow(controller).to receive(:record_experiment_user)
end
User.project_views.keys.each do |project_view|
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index d75b3c9f2e3..914d0931476 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -114,4 +114,69 @@ RSpec.describe InviteMembersHelper do
end
end
end
+
+ describe '#dropdown_invite_members_link' do
+ shared_examples_for 'dropdown invite members link' do
+ let(:link_regex) do
+ /data-track-event="click_link".*data-track-property="_track_property_".*Invite members/
+ end
+
+ before do
+ allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' }
+ allow(helper).to receive(:tracking_label).with(owner)
+ allow(helper).to receive(:current_user) { owner }
+ end
+
+ it 'records the experiment' do
+ allow(helper).to receive(:experiment_enabled?)
+
+ helper.dropdown_invite_members_link(form_model)
+
+ expect(helper).to have_received(:experiment_tracking_category_and_group)
+ .with(:invite_members_new_dropdown, subject: owner)
+ end
+
+ context 'with experiment enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { true }
+ end
+
+ it 'returns link' do
+ link = helper.dropdown_invite_members_link(form_model)
+
+ expect(link).to match(link_regex)
+ expect(link).to include(link_href)
+ expect(link).to include('gl-emoji')
+ end
+ end
+
+ context 'with no experiment enabled' do
+ before do
+ allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { false }
+ end
+
+ it 'returns link' do
+ link = helper.dropdown_invite_members_link(form_model)
+
+ expect(link).to match(link_regex)
+ expect(link).to include(link_href)
+ expect(link).not_to include('gl-emoji')
+ end
+ end
+ end
+
+ context 'with a project' do
+ let_it_be(:form_model) { project }
+ let(:link_href) { "href=\"#{project_project_members_path(form_model)}\"" }
+
+ it_behaves_like 'dropdown invite members link'
+ end
+
+ context 'with a group' do
+ let_it_be(:form_model) { create(:group) }
+ let(:link_href) { "href=\"#{group_group_members_path(form_model)}\"" }
+
+ it_behaves_like 'dropdown invite members link'
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
index f2ec4526464..b390d7c0c9f 100644
--- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb
@@ -46,7 +46,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'container_packages',
'tag_packages',
'snippets',
- 'code_review'
+ 'code_review',
+ 'terraform'
)
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4d12bb6bd8c..6a613cab999 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -1260,7 +1260,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.redis_hll_counters }
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
- let(:ineligible_total_categories) { %w[source_code testing ci_secrets_management incident_management_alerts snippets] }
+ let(:ineligible_total_categories) { %w[source_code testing ci_secrets_management incident_management_alerts snippets terraform] }
it 'has all known_events' do
expect(subject).to have_key(:redis_hll_counters)
diff --git a/spec/models/snippet_repository_storage_move_spec.rb b/spec/models/snippet_repository_storage_move_spec.rb
index c9feff0c22f..357951f8859 100644
--- a/spec/models/snippet_repository_storage_move_spec.rb
+++ b/spec/models/snippet_repository_storage_move_spec.rb
@@ -8,6 +8,6 @@ RSpec.describe SnippetRepositoryStorageMove, type: :model do
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
- let(:repository_storage_worker) { nil } # TODO set to SnippetUpdateRepositoryStorageWorker after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
+ let(:repository_storage_worker) { SnippetUpdateRepositoryStorageWorker }
end
end
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index 0fa088a641e..bfdb5458fd1 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -21,9 +21,36 @@ RSpec.describe API::Terraform::State do
stub_terraform_state_object_storage
end
+ shared_examples 'endpoint with unique user tracking' do
+ context 'without authentication' do
+ let(:auth_header) { basic_auth_header('bad', 'token') }
+
+ before do
+ stub_feature_flags(usage_data_p_terraform_state_api_unique_users: false)
+ end
+
+ it 'does not track unique event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ request
+ end
+ end
+
+ context 'with maintainer permissions' do
+ let(:current_user) { maintainer }
+
+ it_behaves_like 'tracking unique hll events', :usage_data_p_terraform_state_api_unique_users do
+ let(:target_id) { 'p_terraform_state_api_unique_users' }
+ let(:expected_type) { instance_of(Integer) }
+ end
+ end
+ end
+
describe 'GET /projects/:id/terraform/state/:name' do
subject(:request) { get api(state_path), headers: auth_header }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'without authentication' do
let(:auth_header) { basic_auth_header('bad', 'token') }
@@ -117,6 +144,8 @@ RSpec.describe API::Terraform::State do
subject(:request) { post api(state_path), headers: auth_header, as: :json, params: params }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'when terraform state with a given name is already present' do
context 'with maintainer permissions' do
let(:current_user) { maintainer }
@@ -219,6 +248,8 @@ RSpec.describe API::Terraform::State do
describe 'DELETE /projects/:id/terraform/state/:name' do
subject(:request) { delete api(state_path), headers: auth_header }
+ it_behaves_like 'endpoint with unique user tracking'
+
context 'with maintainer permissions' do
let(:current_user) { maintainer }
@@ -256,6 +287,8 @@ RSpec.describe API::Terraform::State do
subject(:request) { post api("#{state_path}/lock"), headers: auth_header, params: params }
+ it_behaves_like 'endpoint with unique user tracking'
+
it 'locks the terraform state' do
request
@@ -305,6 +338,10 @@ RSpec.describe API::Terraform::State do
subject(:request) { delete api("#{state_path}/lock"), headers: auth_header, params: params }
+ it_behaves_like 'endpoint with unique user tracking' do
+ let(:lock_id) { 'irrelevant to this test, just needs to be present' }
+ end
+
context 'with the correct lock id' do
let(:lock_id) { '123-456' }
diff --git a/spec/support/matchers/be_sorted.rb b/spec/support/matchers/be_sorted.rb
index 1455060fe71..b0ab93efbb2 100644
--- a/spec/support/matchers/be_sorted.rb
+++ b/spec/support/matchers/be_sorted.rb
@@ -4,18 +4,75 @@
#
# By default, this checks that the collection is sorted ascending
# but you can check order by specific field and order by passing
-# them, eg:
+# them, either as arguments, or using the fluent interface, eg:
#
# ```
+# # Usage examples:
+# expect(collection).to be_sorted
+# expect(collection).to be_sorted(:field)
# expect(collection).to be_sorted(:field, :desc)
+# expect(collection).to be_sorted.asc
+# expect(collection).to be_sorted.desc.by(&:field)
+# expect(collection).to be_sorted.by(&:field).desc
+# expect(collection).to be_sorted.by { |x| [x.foo, x.bar] }
# ```
-RSpec::Matchers.define :be_sorted do |by, order = :asc|
+RSpec::Matchers.define :be_sorted do |on = :itself, order = :asc|
+ def by(&block)
+ @comparator = block
+ self
+ end
+
+ def asc
+ @direction = :asc
+ self
+ end
+
+ def desc
+ @direction = :desc
+ self
+ end
+
+ def format_with(proc)
+ @format_with = proc
+ self
+ end
+
+ define_method :comparator do
+ @comparator || on
+ end
+
+ define_method :descending? do
+ (@direction || order.to_sym) == :desc
+ end
+
+ def order(items)
+ descending? ? items.reverse : items
+ end
+
+ def sort(items)
+ items.sort_by(&comparator)
+ end
+
match do |actual|
- next true unless actual.present? # emtpy collection is sorted
+ next true unless actual.present? # empty collection is sorted
+
+ actual = actual.to_a if actual.respond_to?(:to_a) && !actual.respond_to?(:sort_by)
+
+ @got = actual
+ @expected = order(sort(actual))
+
+ @expected == actual
+ end
+
+ def failure_message
+ "Expected #{show(@expected)}, got #{show(@got)}"
+ end
- actual
- .then { |collection| by ? collection.sort_by(&by) : collection.sort }
- .then { |sorted_collection| order.to_sym == :desc ? sorted_collection.reverse : sorted_collection }
- .then { |sorted_collection| sorted_collection == actual }
+ def show(things)
+ if @format_with
+ things.map(&@format_with)
+ else
+ things
+ end
end
end
diff --git a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
index 5a8388d01df..4c617f3ba46 100644
--- a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
@@ -63,7 +63,6 @@ RSpec.shared_examples 'handles repository moves' do
context 'and transits to scheduled' do
it 'triggers the corresponding repository storage worker' do
- skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id)
storage_move.schedule!
@@ -72,8 +71,7 @@ RSpec.shared_examples 'handles repository moves' do
end
context 'when the transition fails' do
- it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do
- skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
+ it 'does not trigger the corresponding repository storage worker and adds an error' do
allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(repository_storage_worker).not_to receive(:perform_async)
diff --git a/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb b/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb
new file mode 100644
index 00000000000..babd7cfbbeb
--- /dev/null
+++ b/spec/support/shared_examples/workers/update_repository_move_shared_examples.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'an update storage move worker' do
+ describe '#perform' do
+ let(:service) { double(:update_repository_storage_service) }
+
+ before do
+ allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
+ end
+
+ context 'without repository storage move' do
+ it 'calls the update repository storage service' do
+ expect(service_klass).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ expect do
+ subject.perform(container.id, 'test_second_storage')
+ end.to change(repository_storage_move_klass, :count).by(1)
+
+ storage_move = container.repository_storage_moves.last
+ expect(storage_move).to have_attributes(
+ source_storage_name: 'default',
+ destination_storage_name: 'test_second_storage'
+ )
+ end
+ end
+
+ context 'with repository storage move' do
+ it 'calls the update repository storage service' do
+ expect(service_klass).to receive(:new).and_return(service)
+ expect(service).to receive(:execute)
+
+ expect do
+ subject.perform(nil, nil, repository_storage_move.id)
+ end.not_to change(repository_storage_move_klass, :count)
+ end
+ end
+ end
+end
diff --git a/spec/support_specs/matchers/be_sorted_spec.rb b/spec/support_specs/matchers/be_sorted_spec.rb
new file mode 100644
index 00000000000..e62bc9b36b3
--- /dev/null
+++ b/spec/support_specs/matchers/be_sorted_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+load File.expand_path('../../../spec/support/matchers/be_sorted.rb', __dir__)
+
+RSpec.describe 'be_sorted' do
+ it 'matches empty collections, regardless of arguments' do
+ expect([])
+ .to be_sorted
+ .and be_sorted.asc
+ .and be_sorted.desc
+ .and be_sorted(:foo)
+ .and be_sorted(:bar)
+
+ expect([].to_set).to be_sorted
+ expect({}).to be_sorted
+ end
+
+ it 'matches in both directions' do
+ expect([1, 2, 3]).to be_sorted.asc
+ expect([3, 2, 1]).to be_sorted.desc
+ end
+
+ it 'can match on a projection' do
+ xs = [['a', 10], ['b', 7], ['c', 4]]
+
+ expect(xs).to be_sorted.asc.by(&:first)
+ expect(xs).to be_sorted(:first, :asc)
+ expect(xs).to be_sorted.desc.by(&:second)
+ expect(xs).to be_sorted(:second, :desc)
+ end
+end
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index cf33ec9884b..01892e72c97 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -3,10 +3,42 @@
require 'spec_helper'
RSpec.describe 'layouts/header/_new_dropdown' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
+
+ shared_examples_for 'invite member quick link' do
+ context 'when an experiment is active' do
+ before do
+ allow(Gitlab::Experimentation).to receive(:active?).and_return(true)
+ allow(view).to receive(:experiment_tracking_category_and_group)
+ allow(view).to receive(:tracking_label).with(user)
+ end
+
+ context 'with ability to invite members' do
+ it { is_expected.to have_link('Invite members', href: href) }
+
+ it 'records the experiment' do
+ subject
+
+ expect(view).to have_received(:experiment_tracking_category_and_group)
+ .with(:invite_members_new_dropdown, subject: user)
+ expect(view).to have_received(:tracking_label).with(user)
+ end
+ end
+
+ context 'without ability to invite members' do
+ let(:invite_member) { false }
+
+ it { is_expected.not_to have_link('Invite members') }
+ end
+ end
+
+ context 'when experiment is not active' do
+ it { is_expected.not_to have_link('Invite members') }
+ end
+ end
context 'group-specific links' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
before do
stub_current_user(user)
@@ -22,25 +54,39 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has a "New project" link' do
render
- expect(rendered).to have_link(
- 'New project',
- href: new_project_path(namespace_id: group.id)
- )
+ expect(rendered).to have_link('New project', href: new_project_path(namespace_id: group.id))
end
it 'has a "New subgroup" link' do
render
- expect(rendered).to have_link(
- 'New subgroup',
- href: new_group_path(parent_id: group.id)
- )
+ expect(rendered).to have_link('New subgroup', href: new_group_path(parent_id: group.id))
end
end
+
+ describe 'invite members quick link' do
+ let(:href) { group_group_members_path(group) }
+ let(:invite_member) { true }
+
+ before do
+ allow(view).to receive(:can?).with(user, :create_projects, group).and_return(true)
+ allow(view).to receive(:can?).with(user, :admin_group_member, group).and_return(invite_member)
+ allow(view).to receive(:can_import_members?).and_return(invite_member)
+ allow(view).to receive(:experiment_enabled?)
+ end
+
+ subject do
+ render
+
+ rendered
+ end
+
+ it_behaves_like 'invite member quick link'
+ end
end
context 'project-specific links' do
- let(:project) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:project) { create(:project, creator: user, namespace: user.namespace) }
before do
assign(:project, project)
@@ -54,33 +100,24 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has a "New issue" link' do
render
- expect(rendered).to have_link(
- 'New issue',
- href: new_project_issue_path(project)
- )
+ expect(rendered).to have_link('New issue', href: new_project_issue_path(project))
end
it 'has a "New merge request" link' do
render
- expect(rendered).to have_link(
- 'New merge request',
- href: project_new_merge_request_path(project)
- )
+ expect(rendered).to have_link('New merge request', href: project_new_merge_request_path(project))
end
it 'has a "New snippet" link' do
render
- expect(rendered).to have_link(
- 'New snippet',
- href: new_project_snippet_path(project)
- )
+ expect(rendered).to have_link('New snippet', href: new_project_snippet_path(project))
end
end
context 'as a Project guest' do
- let(:guest) { create(:user) }
+ let_it_be(:guest) { create(:user) }
before do
stub_current_user(guest)
@@ -96,12 +133,28 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has no "New snippet" link' do
render
- expect(rendered).not_to have_link(
- 'New snippet',
- href: new_project_snippet_path(project)
- )
+ expect(rendered).not_to have_link('New snippet', href: new_project_snippet_path(project))
end
end
+
+ describe 'invite members quick link' do
+ let(:invite_member) { true }
+ let(:href) { project_project_members_path(project) }
+
+ before do
+ allow(view).to receive(:can_import_members?).and_return(invite_member)
+ stub_current_user(user)
+ allow(view).to receive(:experiment_enabled?)
+ end
+
+ subject do
+ render
+
+ rendered
+ end
+
+ it_behaves_like 'invite member quick link'
+ end
end
context 'global links' do
@@ -128,7 +181,7 @@ RSpec.describe 'layouts/header/_new_dropdown' do
end
context 'when the user is not allowed to create snippets' do
- let(:user) { create(:user, :external)}
+ let(:user) { create(:user, :external) }
it 'has no "New snippet" link' do
render
diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb
index f75bb3d1642..490f1f5a2ad 100644
--- a/spec/workers/project_update_repository_storage_worker_spec.rb
+++ b/spec/workers/project_update_repository_storage_worker_spec.rb
@@ -3,45 +3,13 @@
require 'spec_helper'
RSpec.describe ProjectUpdateRepositoryStorageWorker do
- let(:project) { create(:project, :repository) }
-
subject { described_class.new }
- describe "#perform" do
- let(:service) { double(:update_repository_storage_service) }
-
- before do
- allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
- end
-
- context 'without repository storage move' do
- it "calls the update repository storage service" do
- expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service)
- expect(service).to receive(:execute)
-
- expect do
- subject.perform(project.id, 'test_second_storage')
- end.to change(ProjectRepositoryStorageMove, :count).by(1)
-
- storage_move = project.repository_storage_moves.last
- expect(storage_move).to have_attributes(
- source_storage_name: "default",
- destination_storage_name: "test_second_storage"
- )
- end
- end
-
- context 'with repository storage move' do
- let!(:repository_storage_move) { create(:project_repository_storage_move) }
-
- it "calls the update repository storage service" do
- expect(Projects::UpdateRepositoryStorageService).to receive(:new).and_return(service)
- expect(service).to receive(:execute)
+ it_behaves_like 'an update storage move worker' do
+ let_it_be_with_refind(:container) { create(:project, :repository) }
+ let_it_be(:repository_storage_move) { create(:project_repository_storage_move) }
- expect do
- subject.perform(nil, nil, repository_storage_move.id)
- end.not_to change(ProjectRepositoryStorageMove, :count)
- end
- end
+ let(:service_klass) { Projects::UpdateRepositoryStorageService }
+ let(:repository_storage_move_klass) { ProjectRepositoryStorageMove }
end
end
diff --git a/spec/workers/snippet_update_repository_storage_worker_spec.rb b/spec/workers/snippet_update_repository_storage_worker_spec.rb
new file mode 100644
index 00000000000..a48abe4abf7
--- /dev/null
+++ b/spec/workers/snippet_update_repository_storage_worker_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SnippetUpdateRepositoryStorageWorker do
+ subject { described_class.new }
+
+ it_behaves_like 'an update storage move worker' do
+ let_it_be_with_refind(:container) { create(:snippet, :repository) }
+ let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
+
+ let(:service_klass) { Snippets::UpdateRepositoryStorageService }
+ let(:repository_storage_move_klass) { SnippetRepositoryStorageMove }
+ end
+end