2016-06-30 15:34:19 +00:00
|
|
|
# Specifications for behavior common to all objects with executable attributes.
|
|
|
|
# It takes a `issuable_type`, and expect an `issuable`.
|
|
|
|
|
2017-05-31 05:50:53 +00:00
|
|
|
shared_examples 'issuable record that supports quick actions in its description and notes' do |issuable_type|
|
|
|
|
include QuickActionsHelpers
|
2016-09-08 11:08:44 +00:00
|
|
|
|
2016-08-09 15:51:40 +00:00
|
|
|
let(:master) { create(:user) }
|
2017-08-01 18:51:52 +00:00
|
|
|
let(:project) do
|
|
|
|
case issuable_type
|
|
|
|
when :merge_request
|
|
|
|
create(:project, :public, :repository)
|
|
|
|
when :issue
|
2017-08-02 19:55:11 +00:00
|
|
|
create(:project, :public)
|
2017-08-01 18:51:52 +00:00
|
|
|
end
|
|
|
|
end
|
2016-06-30 15:34:19 +00:00
|
|
|
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
|
|
|
|
let!(:label_bug) { create(:label, project: project, title: 'bug') }
|
|
|
|
let!(:label_feature) { create(:label, project: project, title: 'feature') }
|
|
|
|
let(:new_url_opts) { {} }
|
|
|
|
|
|
|
|
before do
|
2016-08-09 15:51:40 +00:00
|
|
|
project.team << [master, :master]
|
2017-06-21 23:44:10 +00:00
|
|
|
|
2017-07-21 23:59:25 +00:00
|
|
|
gitlab_sign_in(master)
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
|
2016-09-08 11:08:44 +00:00
|
|
|
after do
|
|
|
|
# Ensure all outstanding Ajax requests are complete to avoid database deadlocks
|
2017-05-17 18:25:13 +00:00
|
|
|
wait_for_requests
|
2016-09-08 11:08:44 +00:00
|
|
|
end
|
|
|
|
|
2017-05-03 20:51:28 +00:00
|
|
|
describe "new #{issuable_type}", js: true do
|
2016-06-30 15:34:19 +00:00
|
|
|
context 'with commands in the description' do
|
|
|
|
it "creates the #{issuable_type} and interpret commands accordingly" do
|
2017-06-13 22:12:31 +00:00
|
|
|
case issuable_type
|
|
|
|
when :merge_request
|
|
|
|
visit public_send("namespace_project_new_merge_request_path", project.namespace, project, new_url_opts)
|
|
|
|
when :issue
|
|
|
|
visit public_send("new_namespace_project_issue_path", project.namespace, project, new_url_opts)
|
|
|
|
end
|
2016-06-30 15:34:19 +00:00
|
|
|
fill_in "#{issuable_type}_title", with: 'bug 345'
|
|
|
|
fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug\n/milestone %\"ASAP\""
|
|
|
|
click_button "Submit #{issuable_type}".humanize
|
|
|
|
|
|
|
|
issuable = project.public_send(issuable_type.to_s.pluralize).first
|
|
|
|
|
2016-08-17 00:59:55 +00:00
|
|
|
expect(issuable.description).to eq "bug description"
|
2016-06-30 15:34:19 +00:00
|
|
|
expect(issuable.labels).to eq [label_bug]
|
|
|
|
expect(issuable.milestone).to eq milestone
|
|
|
|
expect(page).to have_content 'bug 345'
|
|
|
|
expect(page).to have_content 'bug description'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-03 23:09:30 +00:00
|
|
|
describe "note on #{issuable_type}", js: true do
|
2016-06-30 15:34:19 +00:00
|
|
|
before do
|
|
|
|
visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with a note containing commands' do
|
|
|
|
it 'creates a note without the commands and interpret the commands accordingly' do
|
2017-07-21 21:07:59 +00:00
|
|
|
assignee = create(:user, username: 'bob')
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("Awesome!\n/assign @bob\n/label ~bug\n/milestone %\"ASAP\"")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).to have_content 'Awesome!'
|
|
|
|
expect(page).not_to have_content '/assign @bob'
|
|
|
|
expect(page).not_to have_content '/label ~bug'
|
|
|
|
expect(page).not_to have_content '/milestone %"ASAP"'
|
|
|
|
|
2017-05-17 18:25:13 +00:00
|
|
|
wait_for_requests
|
2016-06-30 15:34:19 +00:00
|
|
|
issuable.reload
|
|
|
|
note = issuable.notes.user.first
|
|
|
|
|
2016-08-17 00:59:55 +00:00
|
|
|
expect(note.note).to eq "Awesome!"
|
2017-05-04 12:11:15 +00:00
|
|
|
expect(issuable.assignees).to eq [assignee]
|
2016-06-30 15:34:19 +00:00
|
|
|
expect(issuable.labels).to eq [label_bug]
|
|
|
|
expect(issuable.milestone).to eq milestone
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with a note containing only commands' do
|
|
|
|
it 'does not create a note but interpret the commands accordingly' do
|
2017-07-21 21:07:59 +00:00
|
|
|
assignee = create(:user, username: 'bob')
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/assign @bob\n/label ~bug\n/milestone %\"ASAP\"")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/assign @bob'
|
|
|
|
expect(page).not_to have_content '/label ~bug'
|
|
|
|
expect(page).not_to have_content '/milestone %"ASAP"'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
issuable.reload
|
|
|
|
|
|
|
|
expect(issuable.notes.user).to be_empty
|
2017-05-04 12:11:15 +00:00
|
|
|
expect(issuable.assignees).to eq [assignee]
|
2016-06-30 15:34:19 +00:00
|
|
|
expect(issuable.labels).to eq [label_bug]
|
|
|
|
expect(issuable.milestone).to eq milestone
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-09 15:51:40 +00:00
|
|
|
context "with a note closing the #{issuable_type}" do
|
|
|
|
before do
|
|
|
|
expect(issuable).to be_open
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when current user can close #{issuable_type}" do
|
|
|
|
it "closes the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/close")
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/close'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(issuable.reload).to be_closed
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when current user cannot close #{issuable_type}" do
|
|
|
|
before do
|
2017-07-21 21:07:59 +00:00
|
|
|
guest = create(:user)
|
|
|
|
project.add_guest(guest)
|
|
|
|
|
2017-07-21 23:59:25 +00:00
|
|
|
gitlab_sign_out
|
|
|
|
gitlab_sign_in(guest)
|
2016-08-09 15:51:40 +00:00
|
|
|
visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not close the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/close")
|
2016-08-09 15:51:40 +00:00
|
|
|
|
2017-07-21 21:10:56 +00:00
|
|
|
expect(page).to have_content '/close'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).not_to have_content 'Commands applied'
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(issuable).to be_open
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a note reopening the #{issuable_type}" do
|
|
|
|
before do
|
|
|
|
issuable.close
|
|
|
|
expect(issuable).to be_closed
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when current user can reopen #{issuable_type}" do
|
|
|
|
it "reopens the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/reopen")
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/reopen'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(issuable.reload).to be_open
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when current user cannot reopen #{issuable_type}" do
|
|
|
|
before do
|
2017-07-21 21:07:59 +00:00
|
|
|
guest = create(:user)
|
|
|
|
project.add_guest(guest)
|
|
|
|
|
2017-07-21 23:59:25 +00:00
|
|
|
gitlab_sign_out
|
|
|
|
gitlab_sign_in(guest)
|
2016-08-09 15:51:40 +00:00
|
|
|
visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not reopen the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/reopen")
|
2016-08-09 15:51:40 +00:00
|
|
|
|
2017-07-21 21:10:56 +00:00
|
|
|
expect(page).to have_content '/reopen'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).not_to have_content 'Commands applied'
|
2016-08-09 15:51:40 +00:00
|
|
|
|
|
|
|
expect(issuable).to be_closed
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-09 18:54:18 +00:00
|
|
|
context "with a note changing the #{issuable_type}'s title" do
|
|
|
|
context "when current user can change title of #{issuable_type}" do
|
|
|
|
it "reopens the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/title Awesome new title")
|
2016-08-09 18:54:18 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/title'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-08-09 18:54:18 +00:00
|
|
|
|
|
|
|
expect(issuable.reload.title).to eq 'Awesome new title'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when current user cannot change title of #{issuable_type}" do
|
|
|
|
before do
|
2017-07-21 21:07:59 +00:00
|
|
|
guest = create(:user)
|
|
|
|
project.add_guest(guest)
|
|
|
|
|
2017-07-21 23:59:25 +00:00
|
|
|
gitlab_sign_out
|
|
|
|
gitlab_sign_in(guest)
|
2016-08-09 18:54:18 +00:00
|
|
|
visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not reopen the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/title Awesome new title")
|
2016-08-09 18:54:18 +00:00
|
|
|
|
2017-07-21 21:10:56 +00:00
|
|
|
expect(page).to have_content '/title'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).not_to have_content 'Commands applied'
|
2016-08-09 18:54:18 +00:00
|
|
|
|
|
|
|
expect(issuable.reload.title).not_to eq 'Awesome new title'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-30 15:34:19 +00:00
|
|
|
context "with a note marking the #{issuable_type} as todo" do
|
|
|
|
it "creates a new todo for the #{issuable_type}" do
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/todo")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/todo'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-08-09 15:51:40 +00:00
|
|
|
todos = TodosFinder.new(master).execute
|
2016-06-30 15:34:19 +00:00
|
|
|
todo = todos.first
|
|
|
|
|
|
|
|
expect(todos.size).to eq 1
|
|
|
|
expect(todo).to be_pending
|
|
|
|
expect(todo.target).to eq issuable
|
2016-08-09 15:51:40 +00:00
|
|
|
expect(todo.author).to eq master
|
|
|
|
expect(todo.user).to eq master
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a note marking the #{issuable_type} as done" do
|
|
|
|
before do
|
2016-08-09 15:51:40 +00:00
|
|
|
TodoService.new.mark_todo(issuable, master)
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it "creates a new todo for the #{issuable_type}" do
|
2016-08-09 15:51:40 +00:00
|
|
|
todos = TodosFinder.new(master).execute
|
2016-06-30 15:34:19 +00:00
|
|
|
todo = todos.first
|
|
|
|
|
|
|
|
expect(todos.size).to eq 1
|
|
|
|
expect(todos.first).to be_pending
|
|
|
|
expect(todo.target).to eq issuable
|
2016-08-09 15:51:40 +00:00
|
|
|
expect(todo.author).to eq master
|
|
|
|
expect(todo.user).to eq master
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/done")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/done'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(todo.reload).to be_done
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a note subscribing to the #{issuable_type}" do
|
|
|
|
it "creates a new todo for the #{issuable_type}" do
|
2016-11-04 18:19:08 +00:00
|
|
|
expect(issuable.subscribed?(master, project)).to be_falsy
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/subscribe")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/subscribe'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-11-04 18:19:08 +00:00
|
|
|
expect(issuable.subscribed?(master, project)).to be_truthy
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with a note unsubscribing to the #{issuable_type} as done" do
|
|
|
|
before do
|
2016-11-04 18:19:08 +00:00
|
|
|
issuable.subscribe(master, project)
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it "creates a new todo for the #{issuable_type}" do
|
2016-11-04 18:19:08 +00:00
|
|
|
expect(issuable.subscribed?(master, project)).to be_truthy
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-09-08 03:54:08 +00:00
|
|
|
write_note("/unsubscribe")
|
2016-06-30 15:34:19 +00:00
|
|
|
|
|
|
|
expect(page).not_to have_content '/unsubscribe'
|
2016-12-15 19:54:43 +00:00
|
|
|
expect(page).to have_content 'Commands applied'
|
2016-06-30 15:34:19 +00:00
|
|
|
|
2016-11-04 18:19:08 +00:00
|
|
|
expect(issuable.subscribed?(master, project)).to be_falsy
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
|
|
|
end
|
2017-08-06 22:12:13 +00:00
|
|
|
|
|
|
|
context "with a note assigning the #{issuable_type} to the current user" do
|
|
|
|
it "assigns the #{issuable_type} to the current user" do
|
|
|
|
write_note("/assign me")
|
|
|
|
|
|
|
|
expect(page).not_to have_content '/assign me'
|
|
|
|
expect(page).to have_content 'Commands applied'
|
|
|
|
|
|
|
|
expect(issuable.reload.assignees).to eq [master]
|
|
|
|
end
|
|
|
|
end
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|
2016-11-16 11:09:09 +00:00
|
|
|
|
2017-07-21 23:59:25 +00:00
|
|
|
describe "preview of note on #{issuable_type}", js: true do
|
2017-05-31 05:50:53 +00:00
|
|
|
it 'removes quick actions from note and explains them' do
|
2017-07-21 21:07:59 +00:00
|
|
|
create(:user, username: 'bob')
|
|
|
|
|
2016-11-16 11:09:09 +00:00
|
|
|
visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable)
|
|
|
|
|
|
|
|
page.within('.js-main-target-form') do
|
|
|
|
fill_in 'note[note]', with: "Awesome!\n/assign @bob "
|
|
|
|
click_on 'Preview'
|
|
|
|
|
|
|
|
expect(page).to have_content 'Awesome!'
|
|
|
|
expect(page).not_to have_content '/assign @bob'
|
|
|
|
expect(page).to have_content 'Assigns @bob.'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-06-30 15:34:19 +00:00
|
|
|
end
|