From e4f7b87ddb4ba83456871eb83b841192b1b56799 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Wed, 3 May 2017 10:48:01 +0200 Subject: Support comments for personal snippets --- spec/factories/notes.rb | 2 + .../snippets/notes_on_personal_snippets_spec.rb | 64 +++++++++++++++++- spec/helpers/notes_helper_spec.rb | 75 ++++++++++++++++++++++ spec/services/notes/build_service_spec.rb | 74 ++++++++++++++++++++- spec/views/projects/notes/_form.html.haml_spec.rb | 36 ----------- spec/views/shared/notes/_form.html.haml_spec.rb | 36 +++++++++++ 6 files changed, 248 insertions(+), 39 deletions(-) delete mode 100644 spec/views/projects/notes/_form.html.haml_spec.rb create mode 100644 spec/views/shared/notes/_form.html.haml_spec.rb (limited to 'spec') diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 44c3186d813..046974dcd6e 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -29,6 +29,8 @@ FactoryGirl.define do factory :discussion_note_on_commit, traits: [:on_commit], class: DiscussionNote + factory :discussion_note_on_personal_snippet, traits: [:on_personal_snippet], class: DiscussionNote + factory :legacy_diff_note_on_commit, traits: [:on_commit, :legacy_diff_note], class: LegacyDiffNote factory :legacy_diff_note_on_merge_request, traits: [:on_merge_request, :legacy_diff_note], class: LegacyDiffNote do diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb index c646039e0b1..957baac02eb 100644 --- a/spec/features/snippets/notes_on_personal_snippets_spec.rb +++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Comments on personal snippets', feature: true do +describe 'Comments on personal snippets', :js, feature: true do let!(:user) { create(:user) } let!(:snippet) { create(:personal_snippet, :public) } let!(:snippet_notes) do @@ -18,7 +18,7 @@ describe 'Comments on personal snippets', feature: true do subject { page } - context 'viewing the snippet detail page' do + context 'when viewing the snippet detail page' do it 'contains notes for a snippet with correct action icons' do expect(page).to have_selector('#notes-list li', count: 2) @@ -36,4 +36,64 @@ describe 'Comments on personal snippets', feature: true do end end end + + context 'when submitting a note' do + it 'shows a valid form' do + is_expected.to have_css('.js-main-target-form', visible: true, count: 1) + expect(find('.js-main-target-form .js-comment-button').value). + to eq('Comment') + + page.within('.js-main-target-form') do + expect(page).not_to have_link('Cancel') + end + end + + it 'previews a note' do + fill_in 'note[note]', with: 'This is **awesome**!' + find('.js-md-preview-button').click + + page.within('.new-note .md-preview') do + expect(page).to have_content('This is awesome!') + expect(page).to have_selector('strong') + end + end + + it 'creates a note' do + fill_in 'note[note]', with: 'This is **awesome**!' + click_button 'Comment' + + expect(find('div#notes')).to have_content('This is awesome!') + end + end + + context 'when editing a note' do + it 'changes the text' do + page.within("#notes-list li#note_#{snippet_notes[0].id}") do + click_on 'Edit comment' + end + + page.within('.current-note-edit-form') do + fill_in 'note[note]', with: 'new content' + find('.btn-save').click + end + + page.within("#notes-list li#note_#{snippet_notes[0].id}") do + expect(page).to have_css('.note_edited_ago') + expect(page).to have_content('new content') + expect(find('.note_edited_ago').text).to match(/less than a minute ago/) + end + end + end + + context 'when deleting a note' do + it 'removes the note from the snippet detail page' do + page.within("#notes-list li#note_#{snippet_notes[0].id}") do + click_on 'Remove comment' + end + + wait_for_ajax + + expect(page).not_to have_selector("#notes-list li#note_#{snippet_notes[0].id}") + end + end end diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb index 6c990f94175..099146678ae 100644 --- a/spec/helpers/notes_helper_spec.rb +++ b/spec/helpers/notes_helper_spec.rb @@ -175,4 +175,79 @@ describe NotesHelper do end end end + + describe '#notes_url' do + it 'return snippet notes path for personal snippet' do + @snippet = create(:personal_snippet) + + expect(helper.notes_url).to eq("/snippets/#{@snippet.id}/notes") + end + + it 'return project notes path for project snippet' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + @snippet = create(:project_snippet, project: @project) + @noteable = @snippet + + expect(helper.notes_url).to eq("/nm/test/noteable/project_snippet/#{@noteable.id}/notes") + end + + it 'return project notes path for other noteables' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + @noteable = create(:issue, project: @project) + + expect(helper.notes_url).to eq("/nm/test/noteable/issue/#{@noteable.id}/notes") + end + end + + describe '#note_url' do + it 'return snippet notes path for personal snippet' do + note = create(:note_on_personal_snippet) + + expect(helper.note_url(note)).to eq("/snippets/#{note.noteable.id}/notes/#{note.id}") + end + + it 'return project notes path for project snippet' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + note = create(:note_on_project_snippet, project: @project) + + expect(helper.note_url(note)).to eq("/nm/test/notes/#{note.id}") + end + + it 'return project notes path for other noteables' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + note = create(:note_on_issue, project: @project) + + expect(helper.note_url(note)).to eq("/nm/test/notes/#{note.id}") + end + end + + describe '#form_resurces' do + it 'returns note for personal snippet' do + @snippet = create(:personal_snippet) + @note = create(:note_on_personal_snippet) + + expect(helper.form_resources).to eq([@note]) + end + + it 'returns namespace, project and note for project snippet' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + @snippet = create(:project_snippet, project: @project) + @note = create(:note_on_personal_snippet) + + expect(helper.form_resources).to eq([@project.namespace, @project, @note]) + end + + it 'returns namespace, project and note path for other noteables' do + namespace = create(:namespace, path: 'nm') + @project = create(:empty_project, path: 'test', namespace: namespace) + @note = create(:note_on_issue, project: @project) + + expect(helper.form_resources).to eq([@project.namespace, @project, @note]) + end + end end diff --git a/spec/services/notes/build_service_spec.rb b/spec/services/notes/build_service_spec.rb index f9dd5541b10..133175769ca 100644 --- a/spec/services/notes/build_service_spec.rb +++ b/spec/services/notes/build_service_spec.rb @@ -29,10 +29,82 @@ describe Notes::BuildService, services: true do expect(new_note.errors[:base]).to include('Discussion to reply to cannot be found') end end + + context 'personal snippet note' do + def reply(note, user = nil) + user ||= create(:user) + + described_class.new(nil, + user, + note: 'Test', + in_reply_to_discussion_id: note.discussion_id).execute + end + + let(:snippet_author) { create(:user) } + + context 'when a snippet is public' do + it 'creates a reply note' do + snippet = create(:personal_snippet, :public) + note = create(:discussion_note_on_personal_snippet, noteable: snippet) + + new_note = reply(note) + + expect(new_note).to be_valid + expect(new_note.in_reply_to?(note)).to be_truthy + end + end + + context 'when a snippet is private' do + let(:snippet) { create(:personal_snippet, :private, author: snippet_author) } + let(:note) { create(:discussion_note_on_personal_snippet, noteable: snippet) } + + it 'creates a reply note when the author replies' do + new_note = reply(note, snippet_author) + + expect(new_note).to be_valid + expect(new_note.in_reply_to?(note)).to be_truthy + end + + it 'sets an error when another user replies' do + new_note = reply(note) + + expect(new_note.errors[:base]).to include('Discussion to reply to cannot be found') + end + end + + context 'when a snippet is internal' do + let(:snippet) { create(:personal_snippet, :internal, author: snippet_author) } + let(:note) { create(:discussion_note_on_personal_snippet, noteable: snippet) } + + it 'creates a reply note when the author replies' do + new_note = reply(note, snippet_author) + + expect(new_note).to be_valid + expect(new_note.in_reply_to?(note)).to be_truthy + end + + it 'creates a reply note when a regular user replies' do + new_note = reply(note) + + expect(new_note).to be_valid + expect(new_note.in_reply_to?(note)).to be_truthy + end + + it 'sets an error when an external user replies' do + new_note = reply(note, create(:user, :external)) + + expect(new_note.errors[:base]).to include('Discussion to reply to cannot be found') + end + end + end end it 'builds a note without saving it' do - new_note = described_class.new(project, author, noteable_type: note.noteable_type, noteable_id: note.noteable_id, note: 'Test').execute + new_note = described_class.new(project, + author, + noteable_type: note.noteable_type, + noteable_id: note.noteable_id, + note: 'Test').execute expect(new_note).to be_valid expect(new_note).not_to be_persisted end diff --git a/spec/views/projects/notes/_form.html.haml_spec.rb b/spec/views/projects/notes/_form.html.haml_spec.rb deleted file mode 100644 index a364f9bce92..00000000000 --- a/spec/views/projects/notes/_form.html.haml_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'spec_helper' - -describe 'projects/notes/_form' do - include Devise::Test::ControllerHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - - before do - project.team << [user, :master] - assign(:project, project) - assign(:note, note) - - allow(view).to receive(:current_user).and_return(user) - - render - end - - %w[issue merge_request].each do |noteable| - context "with a note on #{noteable}" do - let(:note) { build(:"note_on_#{noteable}", project: project) } - - it 'says that markdown and slash commands are supported' do - expect(rendered).to have_content('Markdown and slash commands are supported') - end - end - end - - context 'with a note on a commit' do - let(:note) { build(:note_on_commit, project: project) } - - it 'says that only markdown is supported, not slash commands' do - expect(rendered).to have_content('Markdown is supported') - end - end -end diff --git a/spec/views/shared/notes/_form.html.haml_spec.rb b/spec/views/shared/notes/_form.html.haml_spec.rb new file mode 100644 index 00000000000..d7d0a5bf56a --- /dev/null +++ b/spec/views/shared/notes/_form.html.haml_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe 'shared/notes/_form' do + include Devise::Test::ControllerHelpers + + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + + before do + project.team << [user, :master] + assign(:project, project) + assign(:note, note) + + allow(view).to receive(:current_user).and_return(user) + + render + end + + %w[issue merge_request].each do |noteable| + context "with a note on #{noteable}" do + let(:note) { build(:"note_on_#{noteable}", project: project) } + + it 'says that markdown and slash commands are supported' do + expect(rendered).to have_content('Markdown and slash commands are supported') + end + end + end + + context 'with a note on a commit' do + let(:note) { build(:note_on_commit, project: project) } + + it 'says that only markdown is supported, not slash commands' do + expect(rendered).to have_content('Markdown is supported') + end + end +end -- cgit v1.2.3