diff options
Diffstat (limited to 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb')
-rw-r--r-- | spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb new file mode 100644 index 00000000000..439c068471b --- /dev/null +++ b/spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb @@ -0,0 +1,273 @@ +# frozen_string_literal: true + +shared_examples 'issuable quick actions' do + QuickAction = Struct.new(:action_text, :expectation, :before_action, keyword_init: true) do + # Pass a block as :before_action if + # issuable state needs to be changed before + # the quick action is executed. + def call_before_action + before_action.call if before_action + end + + def skip_access_check + action_text["/todo"] || + action_text["/done"] || + action_text["/subscribe"] || + action_text["/shrug"] || + action_text["/tableflip"] + end + end + + # Quick actions shared by issues and merge requests + let(:issuable_quick_actions) do + [ + QuickAction.new( + action_text: "/subscribe", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable).to be_subscribed(note_author, issuable.project) + else + expect(noteable).not_to be_subscribed(note_author, issuable.project) + end + } + ), + QuickAction.new( + action_text: "/unsubscribe", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable).not_to be_subscribed(note_author, issuable.project) + } + ), + QuickAction.new( + action_text: "/todo", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.todos.count == 1).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/done", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.todos.last.done?).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/close", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.closed?).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/reopen", + before_action: -> { + issuable.close + }, + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.open?).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/assign @#{user.username}", + expectation: ->(noteable, can_use_quick_action) { + if noteable.allows_multiple_assignees? + expect(noteable.assignees == [old_assignee, user]).to eq(can_use_quick_action) + else + expect(noteable.assignees == [user]).to eq(can_use_quick_action) + end + } + ), + QuickAction.new( + action_text: "/unassign", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.assignees).to be_empty + else + expect(noteable.assignees).not_to be_empty + end + } + ), + QuickAction.new( + action_text: "/title new title", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.title == "new title").to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/lock", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.discussion_locked?).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/unlock", + before_action: -> { + issuable.update(discussion_locked: true) + }, + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable).not_to be_discussion_locked + else + expect(noteable).to be_discussion_locked + end + } + ), + QuickAction.new( + action_text: "/milestone %\"sprint\"", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.milestone == milestone).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/remove_milestone", + before_action: -> { + issuable.update(milestone_id: milestone.id) + }, + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.milestone_id).to be_nil + else + expect(noteable.milestone_id).to eq(milestone.id) + end + } + ), + QuickAction.new( + action_text: "/label ~feature", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.labels&.last&.id == feature_label.id).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/unlabel", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.labels).to be_empty + else + expect(noteable.labels).not_to be_empty + end + } + ), + QuickAction.new( + action_text: "/award :100:", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.award_emoji.last.name).to eq("100") + else + expect(noteable.award_emoji).to be_empty + end + } + ), + QuickAction.new( + action_text: "/estimate 1d 2h 3m", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.time_estimate == 36180).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/remove_estimate", + before_action: -> { + issuable.update(time_estimate: 30000) + }, + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.time_estimate).to be_zero + else + expect(noteable.time_estimate).to eq(30000) + end + } + ), + QuickAction.new( + action_text: "/spend 1d 2h 3m", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.total_time_spent == 36180).to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/remove_time_spent", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.total_time_spent == 0) + else + expect(noteable.timelogs).to be_empty + end + } + ), + QuickAction.new( + action_text: "/shrug oops", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.notes&.last&.note == "HELLO\noops ¯\\_(ツ)_/¯\nWORLD").to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/tableflip oops", + expectation: ->(noteable, can_use_quick_action) { + expect(noteable.notes&.last&.note == "HELLO\noops (╯°□°)╯︵ ┻━┻\nWORLD").to eq(can_use_quick_action) + } + ), + QuickAction.new( + action_text: "/copy_metadata #{issue_2.to_reference}", + expectation: ->(noteable, can_use_quick_action) { + if can_use_quick_action + expect(noteable.labels).to eq(issue_2.labels) + expect(noteable.milestone).to eq(issue_2.milestone) + else + expect(noteable.labels).not_to eq(issue_2.labels) + expect(noteable.milestone).not_to eq(issue_2.milestone) + end + } + ) + ] + end + + let(:old_assignee) { create(:user) } + + before do + project.add_developer(old_assignee) + issuable.update(assignees: [old_assignee]) + end + + context 'when user can update issuable' do + set(:developer) { create(:user) } + let(:note_author) { developer } + + before do + project.add_developer(developer) + end + + it 'saves the note and updates the issue' do + quick_actions.each do |quick_action| + note_text = %(HELLO\n#{quick_action.action_text}\nWORLD) + quick_action.call_before_action + + note = described_class.new(project, developer, note_params.merge(note: note_text)).execute + noteable = note.noteable + + # shrug and tablefip quick actions modifies the note text + # on these cases we need to skip this assertion + if !quick_action.action_text["shrug"] && !quick_action.action_text["tableflip"] + expect(note.note).to eq "HELLO\nWORLD" + end + + quick_action.expectation.call(noteable, true) + end + end + end + + context 'when user cannot update issuable' do + set(:non_member) { create(:user) } + let(:note_author) { non_member } + + it 'applies commands that user can execute' do + quick_actions.each do |quick_action| + note_text = %(HELLO\n#{quick_action.action_text}\nWORLD) + quick_action.call_before_action + + note = described_class.new(project, non_member, note_params.merge(note: note_text)).execute + noteable = note.noteable + + if quick_action.skip_access_check + quick_action.expectation.call(noteable, true) + else + quick_action.expectation.call(noteable, false) + end + end + end + end +end |