273 lines
8.7 KiB
Ruby
273 lines
8.7 KiB
Ruby
# 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
|