diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-03 03:07:15 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-03 03:07:15 +0300 |
commit | 25ba0c04e90a470bfdf3fe3a5b044a73157565d2 (patch) | |
tree | 9589a405ba956edeaa6d92a4fedbd3a1b422c793 /spec | |
parent | 3a72ac775065b61bbdb285a8f4f6f152ccb4db49 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
8 files changed, 342 insertions, 7 deletions
diff --git a/spec/models/issue_email_participant_spec.rb b/spec/models/issue_email_participant_spec.rb index 8ddc9a5f478..760af974275 100644 --- a/spec/models/issue_email_participant_spec.rb +++ b/spec/models/issue_email_participant_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe IssueEmailParticipant do +RSpec.describe IssueEmailParticipant, feature_category: :service_desk do describe "Associations" do it { is_expected.to belong_to(:issue) } end @@ -27,4 +27,18 @@ RSpec.describe IssueEmailParticipant do expect(subject).to be_invalid end end + + describe 'Scopes' do + describe '.with_emails' do + let!(:participant) { create(:issue_email_participant, email: 'user@example.com') } + let!(:participant1) { create(:issue_email_participant, email: 'user1@example.com') } + let!(:participant2) { create(:issue_email_participant, email: 'user2@example.com') } + + it 'returns only participant with matching emails' do + expect(described_class.with_emails([participant.email, participant1.email])).to match_array( + [participant, participant1] + ) + end + end + end end diff --git a/spec/requests/api/graphql/organizations/organizations_query_spec.rb b/spec/requests/api/graphql/organizations/organizations_query_spec.rb new file mode 100644 index 00000000000..12d81ed7412 --- /dev/null +++ b/spec/requests/api/graphql/organizations/organizations_query_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'getting organizations information', feature_category: :cell do + include GraphqlHelpers + + let_it_be(:user) { create(:user) } + + let(:query) { graphql_query_for(:organizations, organizations_fields) } + let(:organizations) { graphql_data_at(:organizations, :nodes) } + let(:organizations_fields) do + <<~FIELDS + nodes { + id + path + } + FIELDS + end + + before_all { create_list(:organization, 3) } + + subject(:request_organization) { post_graphql(query, current_user: current_user) } + + context 'without authenticated user' do + let(:current_user) { nil } + + it_behaves_like 'a working graphql query' do + before do + request_organization + end + end + end + + context 'with authenticated user' do + let(:current_user) { user } + + it_behaves_like 'a working graphql query' do + before do + request_organization + end + end + + it_behaves_like 'sorted paginated query' do + include_context 'no sort argument' + + let(:first_param) { 2 } + let(:data_path) { [:organizations] } + let(:all_records) { Organizations::Organization.order(id: :desc).map { |o| global_id_of(o).to_s } } + end + + def pagination_query(params) + graphql_query_for(:organizations, params, "#{page_info} nodes { id }") + end + end +end diff --git a/spec/services/issue_email_participants/create_service_spec.rb b/spec/services/issue_email_participants/create_service_spec.rb index fcfdeeb08f3..dc8d5a6ea74 100644 --- a/spec/services/issue_email_participants/create_service_spec.rb +++ b/spec/services/issue_email_participants/create_service_spec.rb @@ -41,8 +41,8 @@ RSpec.describe IssueEmailParticipants::CreateService, feature_category: :service let(:expected_emails) { emails } let(:error_feature_flag) { "Feature flag issue_email_participants is not enabled for this project." } - let(:error_underprivileged) { _("You don't have permission to add email participants.") } - let(:error_no_participants) do + let(:error_underprivileged) { _("You don't have permission to manage email participants.") } + let(:error_no_participants_added) do _("No email participants were added. Either none were provided, or they already exist.") end @@ -58,7 +58,7 @@ RSpec.describe IssueEmailParticipants::CreateService, feature_category: :service end context 'when no emails are provided' do - let(:error_message) { error_no_participants } + let(:error_message) { error_no_participants_added } it_behaves_like 'a failed service execution' end @@ -69,7 +69,7 @@ RSpec.describe IssueEmailParticipants::CreateService, feature_category: :service it_behaves_like 'a successful service execution' context 'when email is already a participant of the issue' do - let(:error_message) { error_no_participants } + let(:error_message) { error_no_participants_added } before do issue.issue_email_participants.create!(email: emails.first) @@ -89,7 +89,7 @@ RSpec.describe IssueEmailParticipants::CreateService, feature_category: :service end let(:emails) { ['over-max@example.com'] } - let(:error_message) { error_no_participants } + let(:error_message) { error_no_participants_added } it_behaves_like 'a failed service execution' diff --git a/spec/services/issue_email_participants/destroy_service_spec.rb b/spec/services/issue_email_participants/destroy_service_spec.rb new file mode 100644 index 00000000000..70e09bb8d3b --- /dev/null +++ b/spec/services/issue_email_participants/destroy_service_spec.rb @@ -0,0 +1,147 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe IssueEmailParticipants::DestroyService, feature_category: :service_desk do + shared_examples 'a successful service execution' do + it 'removes participants', :aggregate_failures do + expect(response).to be_success + + issue.reset + note = issue.notes.last + expect(note.system?).to be true + expect(note.author).to eq(user) + + participants_emails = issue.email_participants_emails_downcase + + expected_emails.each do |email| + expect(participants_emails).not_to include(email) + expect(response.message).to include(email) + expect(note.note).to include(email) + end + end + end + + shared_examples 'a failed service execution' do + it 'returns error ServiceResponse with message', :aggregate_failures do + expect(response).to be_error + expect(response.message).to eq(error_message) + end + end + + describe '#execute' do + let_it_be_with_reload(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be_with_reload(:issue) { create(:issue, project: project) } + + let(:emails) { nil } + let(:service) { described_class.new(target: issue, current_user: user, emails: emails) } + let(:expected_emails) { emails } + + let(:error_feature_flag) { "Feature flag issue_email_participants is not enabled for this project." } + let(:error_underprivileged) { _("You don't have permission to manage email participants.") } + let(:error_no_participants_removed) do + _("No email participants were removed. Either none were provided, or they don't exist.") + end + + subject(:response) { service.execute } + + context 'when the user is not a project member' do + let(:error_message) { error_underprivileged } + + it_behaves_like 'a failed service execution' + end + + context 'when user has reporter role in project' do + before_all do + project.add_reporter(user) + end + + context 'when no emails are provided' do + let(:error_message) { error_no_participants_removed } + + it_behaves_like 'a failed service execution' + end + + context 'when one email is provided' do + let(:emails) { ['user@example.com'] } + let(:error_message) { error_no_participants_removed } + + it_behaves_like 'a failed service execution' + + context 'when email is a participant of the issue' do + before do + issue.issue_email_participants.create!(email: 'user@example.com') + end + + it_behaves_like 'a successful service execution' + + context 'when email is formatted in a different case' do + let(:emails) { ['USER@example.com'] } + let(:expected_emails) { emails.map(&:downcase) } + let(:error_message) { error_no_participants_removed } + + it_behaves_like 'a successful service execution' + end + end + end + + context 'when multiple emails are provided' do + let(:emails) { ['user@example.com', 'user2@example.com'] } + let(:error_message) { error_no_participants_removed } + + it_behaves_like 'a failed service execution' + + context 'when duplicate email provided' do + let(:emails) { ['user@example.com', 'user@example.com'] } + let(:expected_emails) { emails[...-1] } + + it_behaves_like 'a failed service execution' + end + + context 'when one email is a participant of the issue' do + let(:expected_emails) { emails[...-1] } + + before do + issue.issue_email_participants.create!(email: emails.first) + end + + it_behaves_like 'a successful service execution' + end + + context 'when both emails are a participant of the issue' do + before do + emails.each do |email| + issue.issue_email_participants.create!(email: email) + end + end + + it_behaves_like 'a successful service execution' + end + end + + context 'when more than the allowed number of emails are provided' do + let(:emails) { (1..7).map { |i| "user#{i}@example.com" } } + let(:expected_emails) { emails[...-1] } + + before do + emails.each do |email| + issue.issue_email_participants.create!(email: email) + end + end + + it_behaves_like 'a successful service execution' + end + end + + context 'when feature flag issue_email_participants is disabled' do + let(:error_message) { error_feature_flag } + + before do + stub_feature_flags(issue_email_participants: false) + end + + it_behaves_like 'a failed service execution' + end + end +end diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index e96a7c7fc5c..e04f14e752f 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -2324,7 +2324,7 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning end end - context 'invite_email command' do + describe 'invite_email command' do let_it_be(:issuable) { issue } it_behaves_like 'failed command', "No email participants were added. Either none were provided, or they already exist." do @@ -2454,6 +2454,102 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning end end + describe 'remove_email command' do + let_it_be_with_reload(:issuable) { issue } + + it 'is not part of the available commands' do + expect(service.available_commands(issuable)).not_to include(a_hash_including(name: :remove_email)) + end + + context 'with existing email participant' do + let(:content) { '/remove_email user@example.com' } + + subject(:remove_email) { service.execute(content, issuable) } + + before do + issuable.issue_email_participants.create!(email: "user@example.com") + end + + it 'returns message' do + _, _, message = service.execute(content, issuable) + + expect(message).to eq('Removed user@example.com.') + end + + it 'removes 1 participant' do + expect { remove_email }.to change { issue.issue_email_participants.count }.by(-1) + end + + context 'with mixed case email' do + let(:content) { '/remove_email FirstLast@GitLab.com' } + + before do + issuable.issue_email_participants.create!(email: "FirstLast@GitLab.com") + end + + it 'returns correctly cased message' do + _, _, message = service.execute(content, issuable) + + expect(message).to eq('Removed FirstLast@GitLab.com.') + end + + it 'removes 1 participant' do + expect { remove_email }.to change { issue.issue_email_participants.count }.by(-1) + end + end + + context 'with invalid email' do + let(:content) { '/remove_email user@example.com bad_email' } + + it 'only removes valid emails' do + expect { remove_email }.to change { issue.issue_email_participants.count }.by(-1) + end + end + + context 'with non-existing email address' do + let(:content) { '/remove_email NonExistent@gitlab.com' } + + it 'returns message' do + _, _, message = service.execute(content, issuable) + + expect(message).to eq("No email participants were removed. Either none were provided, or they don't exist.") + end + end + + context 'with more than the max number of emails' do + let(:content) { '/remove_email user@example.com user1@example.com' } + + before do + stub_const("IssueEmailParticipants::DestroyService::MAX_NUMBER_OF_EMAILS", 1) + # user@example.com has already been added above + issuable.issue_email_participants.create!(email: "user1@example.com") + end + + it 'only removes the max allowed number of emails' do + expect { remove_email }.to change { issue.issue_email_participants.count }.by(-1) + end + end + end + + context 'with non-persisted issue' do + let(:issuable) { build(:issue) } + + it 'is not part of the available commands' do + expect(service.available_commands(issuable)).not_to include(a_hash_including(name: :remove_email)) + end + end + + context 'with feature flag disabled' do + before do + stub_feature_flags(issue_email_participants: false) + end + + it 'is not part of the available commands' do + expect(service.available_commands(issuable)).not_to include(a_hash_including(name: :remove_email)) + end + end + end + context 'severity command' do let_it_be_with_reload(:issuable) { create(:incident, project: project) } diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 1eb11c80264..8c11270d6fd 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -515,6 +515,18 @@ RSpec.describe SystemNoteService, feature_category: :shared do end end + describe '.email_participants' do + let(:body) { 'added user@example.com' } + + it 'calls IssuableService' do + expect_next_instance_of(::SystemNotes::IssuablesService) do |service| + expect(service).to receive(:email_participants).with(body) + end + + described_class.email_participants(noteable, project, author, body) + end + end + describe '.discussion_lock' do let(:issuable) { double } diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb index 0ba20ee5be1..2d7cbd30db8 100644 --- a/spec/services/system_notes/issuables_service_spec.rb +++ b/spec/services/system_notes/issuables_service_spec.rb @@ -770,6 +770,14 @@ RSpec.describe ::SystemNotes::IssuablesService, feature_category: :team_planning end end + describe '#email_participants' do + let(:body) { "added user@example.com" } + + subject(:system_note) { service.email_participants(body) } + + it { expect(system_note.note).to eq(body) } + end + describe '#discussion_lock' do subject { service.discussion_lock } diff --git a/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb b/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb index 6ab41d87f44..391336526e3 100644 --- a/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb +++ b/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb @@ -26,6 +26,8 @@ RSpec.shared_context 'with FOSS query type fields' do :milestone, :namespace, :note, + :organization, + :organizations, :package, :project, :projects, |