2016-07-27 11:57:48 -04:00
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
feature 'Diff notes resolve', feature: true, js: true do
|
|
|
|
let(:user) { create(:user) }
|
|
|
|
let(:project) { create(:project, :public) }
|
|
|
|
let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") }
|
|
|
|
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request) }
|
|
|
|
let(:path) { "files/ruby/popen.rb" }
|
|
|
|
let(:position) do
|
|
|
|
Gitlab::Diff::Position.new(
|
|
|
|
old_path: path,
|
|
|
|
new_path: path,
|
|
|
|
old_line: nil,
|
|
|
|
new_line: 9,
|
|
|
|
diff_refs: merge_request.diff_refs
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2016-07-29 10:50:58 -04:00
|
|
|
context 'no discussions' do
|
|
|
|
before do
|
|
|
|
project.team << [user, :master]
|
2017-06-21 19:44:10 -04:00
|
|
|
sign_in user
|
2016-07-29 10:50:58 -04:00
|
|
|
note.destroy
|
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'displays no discussion resolved data' do
|
|
|
|
expect(page).not_to have_content('discussion resolved')
|
|
|
|
expect(page).not_to have_selector('.discussion-next-btn')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-07-27 11:57:48 -04:00
|
|
|
context 'as authorized user' do
|
|
|
|
before do
|
|
|
|
project.team << [user, :master]
|
2017-06-21 19:44:10 -04:00
|
|
|
sign_in user
|
2016-07-27 11:57:48 -04:00
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'single discussion' do
|
|
|
|
it 'shows text with how many discussions' do
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark a note as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
find('.line-resolve-btn').click
|
|
|
|
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
2016-07-29 08:31:32 -04:00
|
|
|
expect(find('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}")
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.diff-content' do
|
|
|
|
expect(page).to have_selector('.btn', text: 'Unresolve discussion')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark discussion as resolved' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to unresolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
click_button 'Unresolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'hides resolved discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
visit_merge_request
|
|
|
|
|
|
|
|
expect(page).to have_selector('.discussion-body', visible: false)
|
|
|
|
end
|
|
|
|
|
2016-07-29 10:03:58 -04:00
|
|
|
it 'allows user to resolve from reply form without a comment' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to unresolve from reply form without a comment' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
2016-08-01 05:06:31 -04:00
|
|
|
sleep 1
|
2016-07-29 10:03:58 -04:00
|
|
|
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
2016-08-01 05:06:31 -04:00
|
|
|
click_button 'Unresolve discussion'
|
2016-07-29 10:03:58 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
2016-08-01 05:06:31 -04:00
|
|
|
expect(page).not_to have_selector('.line-resolve-btn.is-active')
|
2016-07-29 10:03:58 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-07-27 11:57:48 -04:00
|
|
|
it 'allows user to comment & resolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
|
|
|
find('.js-note-text').set 'testing'
|
|
|
|
|
|
|
|
click_button 'Comment & resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to comment & unresolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
|
|
|
find('.js-note-text').set 'testing'
|
|
|
|
|
|
|
|
click_button 'Comment & unresolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to quickly scroll to next unresolved discussion' do
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
page.find('.discussion-next-btn').click
|
|
|
|
end
|
|
|
|
|
2016-07-27 13:34:04 -04:00
|
|
|
expect(page.evaluate_script("$('body').scrollTop()")).to be > 0
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'hides jump to next button when all resolved' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(page).to have_selector('.discussion-next-btn', visible: false)
|
|
|
|
end
|
2016-07-27 13:34:04 -04:00
|
|
|
|
|
|
|
it 'updates updated text after resolving note' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
find('.line-resolve-btn').click
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(page).to have_content("Resolved by #{user.name}")
|
|
|
|
end
|
2016-07-29 10:22:26 -04:00
|
|
|
|
|
|
|
it 'hides jump to next discussion button' do
|
|
|
|
page.within '.discussion-reply-holder' do
|
|
|
|
expect(page).not_to have_selector('.discussion-next-btn')
|
|
|
|
end
|
|
|
|
end
|
2016-07-27 13:34:04 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'multiple notes' do
|
|
|
|
before do
|
2017-03-31 17:52:38 -04:00
|
|
|
create(:diff_note_on_merge_request, project: project, noteable: merge_request, in_reply_to: note)
|
2016-10-27 12:58:32 -04:00
|
|
|
visit_merge_request
|
2016-07-27 13:34:04 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not mark discussion as resolved when resolving single note' do
|
2016-10-27 12:58:32 -04:00
|
|
|
page.first '.diff-content .note' do
|
2016-07-27 13:34:04 -04:00
|
|
|
first('.line-resolve-btn').click
|
2017-04-11 12:41:57 -04:00
|
|
|
|
|
|
|
expect(page).to have_selector('.note-action-button .loading')
|
2016-07-29 08:31:32 -04:00
|
|
|
expect(first('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}")
|
2016-07-27 13:34:04 -04:00
|
|
|
end
|
|
|
|
|
2016-11-23 03:31:37 -05:00
|
|
|
expect(page).to have_content('Last updated')
|
2016-07-27 13:34:04 -04:00
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'resolves discussion' do
|
|
|
|
page.all('.note').each do |note|
|
2016-10-27 12:58:32 -04:00
|
|
|
note.all('.line-resolve-btn').each do |button|
|
|
|
|
button.click
|
|
|
|
end
|
2016-07-27 13:34:04 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
expect(page).to have_content('Resolved by')
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'muliple discussions' do
|
|
|
|
before do
|
|
|
|
create(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request)
|
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows text with how many discussions' do
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/2 discussions resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark a single note as resolved' do
|
|
|
|
click_button('Resolve discussion', match: :first)
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/2 discussions resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark all notes as resolved' do
|
|
|
|
page.all('.line-resolve-btn').each do |btn|
|
|
|
|
btn.click
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('2/2 discussions resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user user to mark all discussions as resolved' do
|
|
|
|
page.all('.discussion-reply-holder').each do |reply_holder|
|
|
|
|
page.within reply_holder do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('2/2 discussions resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to quickly scroll to next unresolved discussion' do
|
|
|
|
page.within first('.discussion-reply-holder') do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
2017-05-12 16:14:55 -04:00
|
|
|
page.find('.discussion-next-btn').trigger('click')
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
2016-07-27 13:34:04 -04:00
|
|
|
expect(page.evaluate_script("$('body').scrollTop()")).to be > 0
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'updates updated text after resolving note' do
|
|
|
|
page.within first('.diff-content .note') do
|
|
|
|
find('.line-resolve-btn').click
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(page).to have_content("Resolved by #{user.name}")
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
2016-07-29 10:22:26 -04:00
|
|
|
|
|
|
|
it 'shows jump to next discussion button' do
|
|
|
|
page.all('.discussion-reply-holder').each do |holder|
|
|
|
|
expect(holder).to have_selector('.discussion-next-btn')
|
|
|
|
end
|
|
|
|
end
|
2016-10-27 12:58:32 -04:00
|
|
|
|
2016-08-16 12:17:47 -04:00
|
|
|
it 'displays next discussion even if hidden' do
|
|
|
|
page.all('.note-discussion').each do |discussion|
|
|
|
|
page.within discussion do
|
2017-03-14 01:02:30 -04:00
|
|
|
click_button 'Toggle discussion'
|
2016-08-16 12:17:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within('.issuable-discussion #notes') do
|
|
|
|
expect(page).not_to have_selector('.btn', text: 'Resolve discussion')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
page.find('.discussion-next-btn').click
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(find('.discussion-with-resolve-btn')).to have_selector('.btn', text: 'Resolve discussion')
|
|
|
|
end
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'changes tab' do
|
|
|
|
it 'shows text with how many discussions' do
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark a note as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
find('.line-resolve-btn').click
|
|
|
|
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.diff-content' do
|
|
|
|
expect(page).to have_selector('.btn', text: 'Unresolve discussion')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark discussion as resolved' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to unresolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
click_button 'Unresolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to comment & resolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
|
|
|
find('.js-note-text').set 'testing'
|
|
|
|
|
|
|
|
click_button 'Comment & resolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to comment & unresolve discussion' do
|
|
|
|
page.within '.diff-content' do
|
|
|
|
click_button 'Resolve discussion'
|
|
|
|
|
|
|
|
click_button 'Reply...'
|
|
|
|
|
|
|
|
find('.js-note-text').set 'testing'
|
|
|
|
|
|
|
|
click_button 'Comment & unresolve discussion'
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'as a guest' do
|
|
|
|
let(:guest) { create(:user) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
project.team << [guest, :guest]
|
2017-06-21 19:44:10 -04:00
|
|
|
sign_in guest
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'someone elses merge request' do
|
|
|
|
before do
|
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not allow user to mark note as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
2016-07-29 06:52:08 -04:00
|
|
|
expect(page).not_to have_selector('.line-resolve-btn')
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not allow user to mark discussion as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
expect(page).not_to have_selector('.btn', text: 'Resolve discussion')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'guest users merge request' do
|
|
|
|
before do
|
|
|
|
mr = create(:merge_request_with_diffs, source_project: project, source_branch: 'markdown', author: guest, title: "Bug")
|
|
|
|
create(:diff_note_on_merge_request, project: project, noteable: mr)
|
|
|
|
visit_merge_request(mr)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows user to mark a note as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
find('.line-resolve-btn').click
|
|
|
|
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.diff-content' do
|
|
|
|
expect(page).to have_selector('.btn', text: 'Unresolve discussion')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('1/1 discussion resolved')
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'unauthorized user' do
|
2016-07-29 11:00:25 -04:00
|
|
|
context 'no resolved comments' do
|
|
|
|
before do
|
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not allow user to mark note as resolved' do
|
|
|
|
page.within '.diff-content .note' do
|
|
|
|
expect(page).not_to have_selector('.line-resolve-btn')
|
|
|
|
end
|
|
|
|
|
|
|
|
page.within '.line-resolve-all-container' do
|
|
|
|
expect(page).to have_content('0/1 discussion resolved')
|
|
|
|
end
|
|
|
|
end
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
2016-07-29 11:00:25 -04:00
|
|
|
context 'resolved comment' do
|
|
|
|
before do
|
|
|
|
note.resolve!(user)
|
|
|
|
visit_merge_request
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'shows resolved icon' do
|
|
|
|
expect(page).to have_content '1/1 discussion resolved'
|
|
|
|
|
2017-03-14 01:02:30 -04:00
|
|
|
click_button 'Toggle discussion'
|
2016-07-29 11:00:25 -04:00
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-active')
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
|
2016-07-29 11:00:25 -04:00
|
|
|
it 'does not allow user to click resolve button' do
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-disabled')
|
2017-03-14 01:02:30 -04:00
|
|
|
click_button 'Toggle discussion'
|
2016-07-29 11:00:25 -04:00
|
|
|
|
|
|
|
expect(page).to have_selector('.line-resolve-btn.is-disabled')
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def visit_merge_request(mr = nil)
|
|
|
|
mr = mr || merge_request
|
2017-07-06 12:20:50 -04:00
|
|
|
visit project_merge_request_path(mr.project, mr)
|
2016-07-27 11:57:48 -04:00
|
|
|
end
|
|
|
|
end
|