diff options
Diffstat (limited to 'spec/support/shared_examples/models')
7 files changed, 237 insertions, 152 deletions
diff --git a/spec/support/shared_examples/models/application_setting_shared_examples.rb b/spec/support/shared_examples/models/application_setting_shared_examples.rb index 92fd4363134..60a02d85a1e 100644 --- a/spec/support/shared_examples/models/application_setting_shared_examples.rb +++ b/spec/support/shared_examples/models/application_setting_shared_examples.rb @@ -289,6 +289,7 @@ RSpec.shared_examples 'application settings examples' do describe '#pick_repository_storage' do before do + allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w(default backup)) allow(setting).to receive(:repository_storages_weighted).and_return({ 'default' => 20, 'backup' => 80 }) end @@ -304,15 +305,19 @@ RSpec.shared_examples 'application settings examples' do describe '#normalized_repository_storage_weights' do using RSpec::Parameterized::TableSyntax - where(:storages, :normalized) do - { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 } - { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 } - { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 } - { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 } + where(:config_storages, :storages, :normalized) do + %w(default backup) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 } + %w(default backup) | { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 } + %w(default backup) | { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 } + %w(default backup) | { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 } + %w(default) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0 } + %w(default) | { 'default' => 100, 'backup' => 100 } | { 'default' => 1.0 } + %w(default) | { 'default' => 20, 'backup' => 80 } | { 'default' => 1.0 } end with_them do before do + allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(config_storages) allow(setting).to receive(:repository_storages_weighted).and_return(storages) end diff --git a/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb b/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb new file mode 100644 index 00000000000..766aeac9476 --- /dev/null +++ b/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'list_preferences_for user' do |list_factory, list_id_attribute| + subject { create(list_factory) } # rubocop:disable Rails/SaveBang + + let_it_be(:user) { create(:user) } + + describe '#preferences_for' do + context 'when user is nil' do + it 'returns not persisted preferences' do + preferences = subject.preferences_for(nil) + + expect(preferences).not_to be_persisted + expect(preferences[list_id_attribute]).to eq(subject.id) + expect(preferences.user_id).to be_nil + end + end + + context 'when a user preference already exists' do + before do + subject.update_preferences_for(user, collapsed: true) + end + + it 'loads preference for user' do + preferences = subject.preferences_for(user) + + expect(preferences).to be_persisted + expect(preferences.collapsed).to eq(true) + end + end + + context 'when preferences for user does not exist' do + it 'returns not persisted preferences' do + preferences = subject.preferences_for(user) + + expect(preferences).not_to be_persisted + expect(preferences.user_id).to eq(user.id) + expect(preferences.public_send(list_id_attribute)).to eq(subject.id) + end + end + end + + describe '#update_preferences_for' do + context 'when user is present' do + context 'when there are no preferences for user' do + it 'creates new user preferences' do + expect { subject.update_preferences_for(user, collapsed: true) }.to change { subject.preferences.count }.by(1) + expect(subject.preferences_for(user).collapsed).to eq(true) + end + end + + context 'when there are preferences for user' do + it 'updates user preferences' do + subject.update_preferences_for(user, collapsed: false) + + expect { subject.update_preferences_for(user, collapsed: true) }.not_to change { subject.preferences.count } + expect(subject.preferences_for(user).collapsed).to eq(true) + end + end + + context 'when user is nil' do + it 'does not create user preferences' do + expect { subject.update_preferences_for(nil, collapsed: true) }.not_to change { subject.preferences.count } + end + end + end + end +end diff --git a/spec/support/shared_examples/models/chat_service_shared_examples.rb b/spec/support/shared_examples/models/chat_service_shared_examples.rb index ad237ad9f49..59e249bb865 100644 --- a/spec/support/shared_examples/models/chat_service_shared_examples.rb +++ b/spec/support/shared_examples/models/chat_service_shared_examples.rb @@ -53,9 +53,13 @@ RSpec.shared_examples "chat service" do |service_name| end it "calls #{service_name} API" do - subject.execute(sample_data) + result = subject.execute(sample_data) - expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once + expect(result).to be(true) + expect(WebMock).to have_requested(:post, webhook_url).once.with { |req| + json_body = Gitlab::Json.parse(req.body).with_indifferent_access + expect(json_body).to include(payload) + } end end @@ -67,7 +71,8 @@ RSpec.shared_examples "chat service" do |service_name| it "does not call #{service_name} API" do result = subject.execute(sample_data) - expect(result).to be_falsy + expect(result).to be(false) + expect(WebMock).not_to have_requested(:post, webhook_url) end end diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb index f91e4bd8cf7..68142e667a4 100644 --- a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb @@ -18,7 +18,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type| context 'with a project' do it_behaves_like 'AtomicInternalId' do let(:internal_id_attribute) { :iid } - let(:instance) { build(timebox_type, *timebox_args, project: build(:project), group: nil) } + let(:instance) { build(timebox_type, *timebox_args, project: create(:project), group: nil) } let(:scope) { :project } let(:scope_attrs) { { project: instance.project } } let(:usage) { timebox_table_name } @@ -28,7 +28,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type| context 'with a group' do it_behaves_like 'AtomicInternalId' do let(:internal_id_attribute) { :iid } - let(:instance) { build(timebox_type, *timebox_args, project: nil, group: build(:group)) } + let(:instance) { build(timebox_type, *timebox_args, project: nil, group: create(:group)) } let(:scope) { :group } let(:scope_attrs) { { namespace: instance.group } } let(:usage) { timebox_table_name } diff --git a/spec/support/shared_examples/models/email_format_shared_examples.rb b/spec/support/shared_examples/models/email_format_shared_examples.rb index a8115e440a4..77ded168637 100644 --- a/spec/support/shared_examples/models/email_format_shared_examples.rb +++ b/spec/support/shared_examples/models/email_format_shared_examples.rb @@ -6,7 +6,7 @@ # Note: You have access to `email_value` which is the email address value # being currently tested). -RSpec.shared_examples 'an object with email-formated attributes' do |*attributes| +RSpec.shared_examples 'an object with email-formatted attributes' do |*attributes| attributes.each do |attribute| describe "specifically its :#{attribute} attribute" do %w[ @@ -45,7 +45,7 @@ RSpec.shared_examples 'an object with email-formated attributes' do |*attributes end end -RSpec.shared_examples 'an object with RFC3696 compliant email-formated attributes' do |*attributes| +RSpec.shared_examples 'an object with RFC3696 compliant email-formatted attributes' do |*attributes| attributes.each do |attribute| describe "specifically its :#{attribute} attribute" do %w[ diff --git a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb index a1867e1ce39..71a76121d38 100644 --- a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb +++ b/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb @@ -7,7 +7,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name| let(:webhook_url) { 'https://example.gitlab.com' } def execute_with_options(options) - receive(:new).with(webhook_url, options.merge(http_client: SlackService::Notifier::HTTPClient)) + receive(:new).with(webhook_url, options.merge(http_client: SlackMattermost::Notifier::HTTPClient)) .and_return(double(:slack_service).as_null_object) end @@ -66,193 +66,180 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name| end describe "#execute" do - let(:user) { create(:user) } - let(:project) { create(:project, :repository, :wiki_repo) } - let(:username) { 'slack_username' } - let(:channel) { 'slack_channel' } - let(:issue_service_options) { { title: 'Awesome issue', description: 'please fix' } } + let_it_be(:project) { create(:project, :repository, :wiki_repo) } + let_it_be(:user) { create(:user) } - let(:data) do - Gitlab::DataBuilder::Push.build_sample(project, user) - end + let(:chat_service) { described_class.new( { project: project, webhook: webhook_url, branches_to_be_notified: 'all' }.merge(chat_service_params)) } + let(:chat_service_params) { {} } + let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } let!(:stubbed_resolved_hostname) do stub_full_request(webhook_url, method: :post).request_pattern.uri_pattern.to_s end - before do - allow(chat_service).to receive_messages( - project: project, - project_id: project.id, - service_hook: true, - webhook: webhook_url - ) + subject(:execute_service) { chat_service.execute(data) } - issue_service = Issues::CreateService.new(project, user, issue_service_options) - @issue = issue_service.execute - @issues_sample_data = issue_service.hook_data(@issue, 'open') - - project.add_developer(user) - opts = { - title: 'Awesome merge_request', - description: 'please fix', - source_branch: 'feature', - target_branch: 'master' - } - merge_service = MergeRequests::CreateService.new(project, - user, opts) - @merge_request = merge_service.execute - @merge_sample_data = merge_service.hook_data(@merge_request, - 'open') - - opts = { - title: "Awesome wiki_page", - content: "Some text describing some thing or another", - format: "md", - message: "user created page: Awesome wiki_page" - } - - @wiki_page = create(:wiki_page, wiki: project.wiki, **opts) - @wiki_page_sample_data = Gitlab::DataBuilder::WikiPage.build(@wiki_page, user, 'create') - end - - it "calls #{service_name} API for push events" do - chat_service.execute(data) - - expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once - end + shared_examples 'calls the service API with the event message' do |event_message| + specify do + expect_next_instance_of(Slack::Messenger) do |messenger| + expect(messenger).to receive(:ping).with(event_message, anything).and_call_original + end - it "calls #{service_name} API for issue events" do - chat_service.execute(@issues_sample_data) + execute_service - expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once + expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once + end end - it "calls #{service_name} API for merge requests events" do - chat_service.execute(@merge_sample_data) + context 'with username for slack configured' do + let(:chat_service_params) { { username: 'slack_username' } } + + it 'uses the username as an option' do + expect(Slack::Messenger).to execute_with_options(username: 'slack_username') - expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once + execute_service + end end - it "calls #{service_name} API for wiki page events" do - chat_service.execute(@wiki_page_sample_data) + context 'push events' do + let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) } - expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once - end + it_behaves_like 'calls the service API with the event message', /pushed to branch/ - it "calls #{service_name} API for deployment events" do - deployment_event_data = { object_kind: 'deployment' } + context 'with event channel' do + let(:chat_service_params) { { push_channel: 'random' } } - chat_service.execute(deployment_event_data) + it 'uses the right channel for push event' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) - expect(WebMock).to have_requested(:post, stubbed_resolved_hostname).once + execute_service + end + end end - it 'uses the username as an option for slack when configured' do - allow(chat_service).to receive(:username).and_return(username) - - expect(Slack::Messenger).to execute_with_options(username: username) + context 'tag_push events' do + let(:oldrev) { Gitlab::Git::BLANK_SHA } + let(:newrev) { '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b' } # gitlab-test: git rev-parse refs/tags/v1.1.0 + let(:ref) { 'refs/tags/v1.1.0' } + let(:data) { Git::TagHooksService.new(project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref }).send(:push_data) } - chat_service.execute(data) + it_behaves_like 'calls the service API with the event message', /pushed new tag/ end - it 'uses the channel as an option when it is configured' do - allow(chat_service).to receive(:channel).and_return(channel) - expect(Slack::Messenger).to execute_with_options(channel: [channel]) - chat_service.execute(data) - end + context 'issue events' do + let_it_be(:issue) { create(:issue) } + let(:data) { issue.to_hook_data(user) } - context "event channels" do - it "uses the right channel for push event" do - chat_service.update!(push_channel: "random") + it_behaves_like 'calls the service API with the event message', /Issue (.*?) opened by/ - expect(Slack::Messenger).to execute_with_options(channel: ['random']) + context 'whith event channel' do + let(:chat_service_params) { { issue_channel: 'random' } } - chat_service.execute(data) - end + it 'uses the right channel for issue event' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) - it "uses the right channel for merge request event" do - chat_service.update!(merge_request_channel: "random") + execute_service + end - expect(Slack::Messenger).to execute_with_options(channel: ['random']) + context 'for confidential issues' do + before_all do + issue.update!(confidential: true) + end - chat_service.execute(@merge_sample_data) - end + it 'falls back to issue channel' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) + + execute_service + end - it "uses the right channel for issue event" do - chat_service.update!(issue_channel: "random") + context 'and confidential_issue_channel is defined' do + let(:chat_service_params) { { issue_channel: 'random', confidential_issue_channel: 'confidential' } } - expect(Slack::Messenger).to execute_with_options(channel: ['random']) + it 'uses the confidential issue channel when it is defined' do + expect(Slack::Messenger).to execute_with_options(channel: ['confidential']) - chat_service.execute(@issues_sample_data) + execute_service + end + end + end end + end + + context 'merge request events' do + let_it_be(:merge_request) { create(:merge_request) } + let(:data) { merge_request.to_hook_data(user) } - context 'for confidential issues' do - let(:issue_service_options) { { title: 'Secret', confidential: true } } + it_behaves_like 'calls the service API with the event message', /opened merge request/ - it "uses confidential issue channel" do - chat_service.update!(confidential_issue_channel: 'confidential') + context 'with event channel' do + let(:chat_service_params) { { merge_request_channel: 'random' } } - expect(Slack::Messenger).to execute_with_options(channel: ['confidential']) + it 'uses the right channel for merge request event' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) - chat_service.execute(@issues_sample_data) + execute_service end + end + end + + context 'wiki page events' do + let_it_be(:wiki_page) { create(:wiki_page, wiki: project.wiki, message: 'user created page: Awesome wiki_page') } + let(:data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') } - it 'falls back to issue channel' do - chat_service.update!(issue_channel: 'fallback_channel') + it_behaves_like 'calls the service API with the event message', / created (.*?)wikis\/(.*?)|wiki page> in/ - expect(Slack::Messenger).to execute_with_options(channel: ['fallback_channel']) + context 'with event channel' do + let(:chat_service_params) { { wiki_page_channel: 'random' } } - chat_service.execute(@issues_sample_data) + it 'uses the right channel for wiki event' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) + + execute_service end end + end - it "uses the right channel for wiki event" do - chat_service.update!(wiki_page_channel: "random") - - expect(Slack::Messenger).to execute_with_options(channel: ['random']) + context 'deployment events' do + let_it_be(:deployment) { create(:deployment) } + let(:data) { Gitlab::DataBuilder::Deployment.build(deployment) } - chat_service.execute(@wiki_page_sample_data) - end + it_behaves_like 'calls the service API with the event message', /Deploy to (.*?) created/ + end - context "note event" do - let(:issue_note) do - create(:note_on_issue, project: project, note: "issue note") - end + context 'note event' do + let_it_be(:issue_note) { create(:note_on_issue, project: project, note: "issue note") } + let(:data) { Gitlab::DataBuilder::Note.build(issue_note, user) } - it "uses the right channel" do - chat_service.update!(note_channel: "random") + it_behaves_like 'calls the service API with the event message', /commented on issue/ - note_data = Gitlab::DataBuilder::Note.build(issue_note, user) + context 'with event channel' do + let(:chat_service_params) { { note_channel: 'random' } } + it 'uses the right channel' do expect(Slack::Messenger).to execute_with_options(channel: ['random']) - chat_service.execute(note_data) + execute_service end context 'for confidential notes' do - before do - issue_note.noteable.update!(confidential: true) + before_all do + issue_note.update!(confidential: true) end - it "uses confidential channel" do - chat_service.update!(confidential_note_channel: "confidential") - - note_data = Gitlab::DataBuilder::Note.build(issue_note, user) - - expect(Slack::Messenger).to execute_with_options(channel: ['confidential']) + it 'falls back to note channel' do + expect(Slack::Messenger).to execute_with_options(channel: ['random']) - chat_service.execute(note_data) + execute_service end - it 'falls back to note channel' do - chat_service.update!(note_channel: "fallback_channel") - - note_data = Gitlab::DataBuilder::Note.build(issue_note, user) + context 'and confidential_note_channel is defined' do + let(:chat_service_params) { { note_channel: 'random', confidential_note_channel: 'confidential' } } - expect(Slack::Messenger).to execute_with_options(channel: ['fallback_channel']) + it 'uses confidential channel' do + expect(Slack::Messenger).to execute_with_options(channel: ['confidential']) - chat_service.execute(note_data) + execute_service + end end end end diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb index 89d30688b5c..abc6e3ecce8 100644 --- a/spec/support/shared_examples/models/wiki_shared_examples.rb +++ b/spec/support/shared_examples/models/wiki_shared_examples.rb @@ -354,27 +354,47 @@ RSpec.shared_examples 'wiki model' do subject.repository.create_file(user, 'image.png', image, branch_name: subject.default_branch, message: 'add image') end - it 'returns the latest version of the file if it exists' do - file = subject.find_file('image.png') + shared_examples 'find_file results' do + it 'returns the latest version of the file if it exists' do + file = subject.find_file('image.png') - expect(file.mime_type).to eq('image/png') - end + expect(file.mime_type).to eq('image/png') + end + + it 'returns nil if the page does not exist' do + expect(subject.find_file('non-existent')).to eq(nil) + end + + it 'returns a Gitlab::Git::WikiFile instance' do + file = subject.find_file('image.png') + + expect(file).to be_a Gitlab::Git::WikiFile + end - it 'returns nil if the page does not exist' do - expect(subject.find_file('non-existent')).to eq(nil) + it 'returns the whole file' do + file = subject.find_file('image.png') + image.rewind + + expect(file.raw_data.b).to eq(image.read.b) + end end - it 'returns a Gitlab::Git::WikiFile instance' do - file = subject.find_file('image.png') + it_behaves_like 'find_file results' + + context 'when load_content is disabled' do + it 'includes the file data in the Gitlab::Git::WikiFile' do + file = subject.find_file('image.png', load_content: false) - expect(file).to be_a Gitlab::Git::WikiFile + expect(file.raw_data).to be_empty + end end - it 'returns the whole file' do - file = subject.find_file('image.png') - image.rewind + context 'when feature flag :gitaly_find_file is disabled' do + before do + stub_feature_flags(gitaly_find_file: false) + end - expect(file.raw_data.b).to eq(image.read.b) + it_behaves_like 'find_file results' end end |