diff options
Diffstat (limited to 'spec/support/shared_examples/services')
10 files changed, 403 insertions, 16 deletions
diff --git a/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb index 1b7fe626aea..07a6353296d 100644 --- a/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb +++ b/spec/support/shared_examples/services/boards/lists_list_service_shared_examples.rb @@ -18,6 +18,10 @@ RSpec.shared_examples 'lists list service' do expect { service.execute(board) }.to change(board.lists, :count).by(1) end + it 'does not create a backlog list when create_default_lists is false' do + expect { service.execute(board, create_default_lists: false) }.not_to change(board.lists, :count) + end + it "returns board's lists" do expect(service.execute(board)).to eq [board.backlog_list, list, board.closed_list] end diff --git a/spec/support/shared_examples/services/measurable_service_shared_examples.rb b/spec/support/shared_examples/services/measurable_service_shared_examples.rb new file mode 100644 index 00000000000..206c25e49af --- /dev/null +++ b/spec/support/shared_examples/services/measurable_service_shared_examples.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'measurable service' do + context 'when measurement is enabled' do + let!(:measuring) { Gitlab::Utils::Measuring.new(base_log_data) } + + before do + stub_feature_flags(feature_flag => true) + end + + it 'measure service execution with Gitlab::Utils::Measuring', :aggregate_failures do + expect(Gitlab::Utils::Measuring).to receive(:new).with(base_log_data).and_return(measuring) + expect(measuring).to receive(:with_measuring).and_call_original + end + end + + context 'when measurement is disabled' do + it 'does not measure service execution' do + stub_feature_flags(feature_flag => false) + + expect(Gitlab::Utils::Measuring).not_to receive(:new) + end + end + + def feature_flag + "gitlab_service_measuring_#{described_class_name}" + end + + def described_class_name + described_class.name.underscore.tr('/', '_') + end +end diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb index 90fcac0e55c..5dd1badbefc 100644 --- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb +++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb @@ -23,7 +23,7 @@ RSpec.shared_examples 'valid dashboard service response for schema' do end RSpec.shared_examples 'valid dashboard service response' do - let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) } + let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) } it_behaves_like 'valid dashboard service response for schema' end @@ -38,7 +38,7 @@ RSpec.shared_examples 'caches the unprocessed dashboard for subsequent calls' do end RSpec.shared_examples 'valid embedded dashboard service response' do - let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) } + let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) } it_behaves_like 'valid dashboard service response for schema' end diff --git a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb index d6166ac8188..0e6ecf49cd0 100644 --- a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb +++ b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb @@ -47,9 +47,9 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| old_repository_path = repository.full_path - result = subject.execute('test_second_storage') + result = subject.execute - expect(result[:status]).to eq(:success) + expect(result).to be_success expect(project).not_to be_repository_read_only expect(project.repository_storage).to eq('test_second_storage') expect(gitlab_shell.repository_exists?('default', old_project_repository_path)).to be(false) @@ -62,7 +62,7 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| end it 'does not enqueue a GC run' do - expect { subject.execute('test_second_storage') } + expect { subject.execute } .not_to change(GitGarbageCollectWorker.jobs, :count) end end @@ -75,23 +75,25 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| it 'does not enqueue a GC run if housekeeping is disabled' do stub_application_setting(housekeeping_enabled: false) - expect { subject.execute('test_second_storage') } + expect { subject.execute } .not_to change(GitGarbageCollectWorker.jobs, :count) end it 'enqueues a GC run' do - expect { subject.execute('test_second_storage') } + expect { subject.execute } .to change(GitGarbageCollectWorker.jobs, :count).by(1) end end end context 'when the filesystems are the same' do + let(:destination) { project.repository_storage } + it 'bails out and does nothing' do - result = subject.execute(project.repository_storage) + result = subject.execute - expect(result[:status]).to eq(:error) - expect(result[:message]).to match(/SameFilesystemError/) + expect(result).to be_error + expect(result.message).to match(/SameFilesystemError/) end end @@ -114,9 +116,9 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| expect(GitlabShellWorker).not_to receive(:perform_async) - result = subject.execute('test_second_storage') + result = subject.execute - expect(result[:status]).to eq(:error) + expect(result).to be_error expect(project).not_to be_repository_read_only expect(project.repository_storage).to eq('default') end @@ -142,9 +144,9 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| expect(GitlabShellWorker).not_to receive(:perform_async) - result = subject.execute('test_second_storage') + result = subject.execute - expect(result[:status]).to eq(:error) + expect(result).to be_error expect(project).not_to be_repository_read_only expect(project.repository_storage).to eq('default') end diff --git a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb index 77f64e5e8f8..c5f84e205cf 100644 --- a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb +++ b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb @@ -4,7 +4,7 @@ shared_examples 'a milestone events creator' do let_it_be(:user) { create(:user) } let(:created_at_time) { Time.utc(2019, 12, 30) } - let(:service) { described_class.new(resource, user, created_at: created_at_time) } + let(:service) { described_class.new(resource, user, created_at: created_at_time, old_milestone: nil) } context 'when milestone is present' do let_it_be(:milestone) { create(:milestone) } @@ -25,10 +25,13 @@ shared_examples 'a milestone events creator' do resource.milestone = nil end + let(:old_milestone) { create(:milestone, project: resource.project) } + let(:service) { described_class.new(resource, user, created_at: created_at_time, old_milestone: old_milestone) } + it 'creates the expected event records' do expect { service.execute }.to change { ResourceMilestoneEvent.count }.by(1) - expect_event_record(ResourceMilestoneEvent.last, action: 'remove', milestone: nil, state: 'opened') + expect_event_record(ResourceMilestoneEvent.last, action: 'remove', milestone: old_milestone, state: 'opened') end end diff --git a/spec/support/shared_examples/services/snippets_shared_examples.rb b/spec/support/shared_examples/services/snippets_shared_examples.rb new file mode 100644 index 00000000000..51a4a8b1cd9 --- /dev/null +++ b/spec/support/shared_examples/services/snippets_shared_examples.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'snippets spam check is performed' do + shared_examples 'marked as spam' do + it 'marks a snippet as spam' do + expect(snippet).to be_spam + end + + it 'invalidates the snippet' do + expect(snippet).to be_invalid + end + + it 'creates a new spam_log' do + expect { snippet } + .to have_spam_log(title: snippet.title, noteable_type: snippet.class.name) + end + + it 'assigns a spam_log to an issue' do + expect(snippet.spam_log).to eq(SpamLog.last) + end + end + + let(:extra_opts) do + { visibility_level: Gitlab::VisibilityLevel::PUBLIC, request: double(:request, env: {}) } + end + + before do + expect_next_instance_of(Spam::AkismetService) do |akismet_service| + expect(akismet_service).to receive_messages(spam?: true) + end + end + + [true, false, nil].each do |allow_possible_spam| + context "when allow_possible_spam flag is #{allow_possible_spam.inspect}" do + before do + stub_feature_flags(allow_possible_spam: allow_possible_spam) unless allow_possible_spam.nil? + end + + it_behaves_like 'marked as spam' + end + end +end diff --git a/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb new file mode 100644 index 00000000000..71bdd46572f --- /dev/null +++ b/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'WikiPages::CreateService#execute' do |container_type| + let(:container) { create(container_type, :wiki_repo) } + let(:user) { create(:user) } + let(:page_title) { 'Title' } + + let(:opts) do + { + title: page_title, + content: 'Content for wiki page', + format: 'markdown' + } + end + + subject(:service) { described_class.new(container: container, current_user: user, params: opts) } + + it 'creates wiki page with valid attributes' do + page = service.execute + + expect(page).to be_valid + expect(page).to be_persisted + expect(page.title).to eq(opts[:title]) + expect(page.content).to eq(opts[:content]) + expect(page.format).to eq(opts[:format].to_sym) + end + + it 'executes webhooks' do + expect(service).to receive(:execute_hooks).once.with(WikiPage) + + service.execute + end + + it 'counts wiki page creation' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute }.to change { counter.read(:create) }.by 1 + end + + shared_examples 'correct event created' do + it 'creates appropriate events' do + # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904 + pending('group wiki support') if container_type == :group + + expect { service.execute }.to change { Event.count }.by 1 + + expect(Event.recent.first).to have_attributes( + action: Event::CREATED, + target: have_attributes(canonical_slug: page_title) + ) + end + end + + context 'the new page is at the top level' do + let(:page_title) { 'root-level-page' } + + include_examples 'correct event created' + end + + context 'the new page is in a subsection' do + let(:page_title) { 'subsection/page' } + + include_examples 'correct event created' + end + + context 'the feature is disabled' do + before do + stub_feature_flags(wiki_events: false) + end + + it 'does not record the activity' do + expect { service.execute }.not_to change(Event, :count) + end + end + + context 'when the options are bad' do + let(:page_title) { '' } + + it 'does not count a creation event' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute }.not_to change { counter.read(:create) } + end + + it 'does not record the activity' do + expect { service.execute }.not_to change(Event, :count) + end + + it 'reports the error' do + expect(service.execute).to be_invalid + .and have_attributes(errors: be_present) + end + end +end diff --git a/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb new file mode 100644 index 00000000000..62541eb3da9 --- /dev/null +++ b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'WikiPages::DestroyService#execute' do |container_type| + let(:container) { create(container_type) } + + let(:user) { create(:user) } + let(:page) { create(:wiki_page) } + + subject(:service) { described_class.new(container: container, current_user: user) } + + it 'executes webhooks' do + expect(service).to receive(:execute_hooks).once.with(page) + + service.execute(page) + end + + it 'increments the delete count' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute(page) }.to change { counter.read(:delete) }.by 1 + end + + it 'creates a new wiki page deletion event' do + # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904 + pending('group wiki support') if container_type == :group + + expect { service.execute(page) }.to change { Event.count }.by 1 + + expect(Event.recent.first).to have_attributes( + action: Event::DESTROYED, + target: have_attributes(canonical_slug: page.slug) + ) + end + + it 'does not increment the delete count if the deletion failed' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute(nil) }.not_to change { counter.read(:delete) } + end + + context 'the feature is disabled' do + before do + stub_feature_flags(wiki_events: false) + end + + it 'does not record the activity' do + expect { service.execute(page) }.not_to change(Event, :count) + end + end +end diff --git a/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb new file mode 100644 index 00000000000..0dfc99d043b --- /dev/null +++ b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'WikiPages::UpdateService#execute' do |container_type| + let(:container) { create(container_type, :wiki_repo) } + + let(:user) { create(:user) } + let(:page) { create(:wiki_page) } + let(:page_title) { 'New Title' } + + let(:opts) do + { + content: 'New content for wiki page', + format: 'markdown', + message: 'New wiki message', + title: page_title + } + end + + subject(:service) { described_class.new(container: container, current_user: user, params: opts) } + + it 'updates the wiki page' do + updated_page = service.execute(page) + + expect(updated_page).to be_valid + expect(updated_page.message).to eq(opts[:message]) + expect(updated_page.content).to eq(opts[:content]) + expect(updated_page.format).to eq(opts[:format].to_sym) + expect(updated_page.title).to eq(page_title) + end + + it 'executes webhooks' do + expect(service).to receive(:execute_hooks).once.with(WikiPage) + + service.execute(page) + end + + it 'counts edit events' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute page }.to change { counter.read(:update) }.by 1 + end + + shared_examples 'adds activity event' do + it 'adds a new wiki page activity event' do + # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/216904 + pending('group wiki support') if container_type == :group + + expect { service.execute(page) }.to change { Event.count }.by 1 + + expect(Event.recent.first).to have_attributes( + action: Event::UPDATED, + wiki_page: page, + target_title: page.title + ) + end + end + + context 'the page is at the top level' do + let(:page_title) { 'Top level page' } + + include_examples 'adds activity event' + end + + context 'the page is in a subsection' do + let(:page_title) { 'Subsection / secondary page' } + + include_examples 'adds activity event' + end + + context 'the feature is disabled' do + before do + stub_feature_flags(wiki_events: false) + end + + it 'does not record the activity' do + expect { service.execute(page) }.not_to change(Event, :count) + end + end + + context 'when the options are bad' do + let(:page_title) { '' } + + it 'does not count an edit event' do + counter = Gitlab::UsageDataCounters::WikiPageCounter + + expect { service.execute page }.not_to change { counter.read(:update) } + end + + it 'does not record the activity' do + expect { service.execute page }.not_to change(Event, :count) + end + + it 'reports the error' do + expect(service.execute(page)).to be_invalid + .and have_attributes(errors: be_present) + end + end +end diff --git a/spec/support/shared_examples/services/wikis/create_attachment_service_shared_examples.rb b/spec/support/shared_examples/services/wikis/create_attachment_service_shared_examples.rb new file mode 100644 index 00000000000..541e332e3a1 --- /dev/null +++ b/spec/support/shared_examples/services/wikis/create_attachment_service_shared_examples.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'Wikis::CreateAttachmentService#execute' do |container_type| + let(:container) { create(container_type, :wiki_repo) } + let(:wiki) { container.wiki } + + let(:user) { create(:user) } + let(:file_name) { 'filename.txt' } + let(:file_path_regex) { %r{#{described_class::ATTACHMENT_PATH}/\h{32}/#{file_name}} } + + let(:file_opts) do + { + file_name: file_name, + file_content: 'Content of attachment' + } + end + let(:opts) { file_opts } + + let(:service) { Wikis::CreateAttachmentService.new(container: container, current_user: user, params: opts) } + + subject(:service_execute) { service.execute[:result] } + + before do + container.add_developer(user) + end + + context 'creates branch if it does not exists' do + let(:branch_name) { 'new_branch' } + let(:opts) { file_opts.merge(branch_name: branch_name) } + + it do + expect(wiki.repository.branches).to be_empty + expect { service.execute }.to change { wiki.repository.branches.count }.by(1) + expect(wiki.repository.branches.first.name).to eq branch_name + end + end + + it 'adds file to the repository' do + expect(wiki.repository.ls_files('HEAD')).to be_empty + + service.execute + + files = wiki.repository.ls_files('HEAD') + expect(files.count).to eq 1 + expect(files.first).to match(file_path_regex) + end + + context 'returns' do + before do + allow(SecureRandom).to receive(:hex).and_return('fixed_hex') + + service_execute + end + + it 'returns related information', :aggregate_failures do + expect(service_execute[:file_name]).to eq file_name + expect(service_execute[:file_path]).to eq 'uploads/fixed_hex/filename.txt' + expect(service_execute[:branch]).to eq wiki.default_branch + expect(service_execute[:commit]).not_to be_empty + end + end +end |