Merge branch '12910-personal-snippets-notes' into 'master'
Support comments for personal snippets Closes #12910 See merge request !11090
This commit is contained in:
commit
d4733aa025
|
@ -65,6 +65,15 @@ module NotesActions
|
|||
|
||||
private
|
||||
|
||||
def note_html(note)
|
||||
render_to_string(
|
||||
"shared/notes/_note",
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: { note: note }
|
||||
)
|
||||
end
|
||||
|
||||
def note_json(note)
|
||||
attrs = {
|
||||
commands_changes: note.commands_changes
|
||||
|
@ -98,6 +107,41 @@ module NotesActions
|
|||
attrs
|
||||
end
|
||||
|
||||
def diff_discussion_html(discussion)
|
||||
return unless discussion.diff_discussion?
|
||||
|
||||
if params[:view] == 'parallel'
|
||||
template = "discussions/_parallel_diff_discussion"
|
||||
locals =
|
||||
if params[:line_type] == 'old'
|
||||
{ discussions_left: [discussion], discussions_right: nil }
|
||||
else
|
||||
{ discussions_left: nil, discussions_right: [discussion] }
|
||||
end
|
||||
else
|
||||
template = "discussions/_diff_discussion"
|
||||
locals = { discussions: [discussion] }
|
||||
end
|
||||
|
||||
render_to_string(
|
||||
template,
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: locals
|
||||
)
|
||||
end
|
||||
|
||||
def discussion_html(discussion)
|
||||
return if discussion.individual_note?
|
||||
|
||||
render_to_string(
|
||||
"discussions/_discussion",
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: { discussion: discussion }
|
||||
)
|
||||
end
|
||||
|
||||
def authorize_admin_note!
|
||||
return access_denied! unless can?(current_user, :admin_note, note)
|
||||
end
|
||||
|
|
|
@ -62,50 +62,6 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
end
|
||||
alias_method :awardable, :note
|
||||
|
||||
def note_html(note)
|
||||
render_to_string(
|
||||
"shared/notes/_note",
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: { note: note }
|
||||
)
|
||||
end
|
||||
|
||||
def discussion_html(discussion)
|
||||
return if discussion.individual_note?
|
||||
|
||||
render_to_string(
|
||||
"discussions/_discussion",
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: { discussion: discussion }
|
||||
)
|
||||
end
|
||||
|
||||
def diff_discussion_html(discussion)
|
||||
return unless discussion.diff_discussion?
|
||||
|
||||
if params[:view] == 'parallel'
|
||||
template = "discussions/_parallel_diff_discussion"
|
||||
locals =
|
||||
if params[:line_type] == 'old'
|
||||
{ discussions_left: [discussion], discussions_right: nil }
|
||||
else
|
||||
{ discussions_left: nil, discussions_right: [discussion] }
|
||||
end
|
||||
else
|
||||
template = "discussions/_diff_discussion"
|
||||
locals = { discussions: [discussion] }
|
||||
end
|
||||
|
||||
render_to_string(
|
||||
template,
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: locals
|
||||
)
|
||||
end
|
||||
|
||||
def finder_params
|
||||
params.merge(last_fetched_at: last_fetched_at)
|
||||
end
|
||||
|
|
|
@ -13,15 +13,6 @@ class Snippets::NotesController < ApplicationController
|
|||
end
|
||||
alias_method :awardable, :note
|
||||
|
||||
def note_html(note)
|
||||
render_to_string(
|
||||
"shared/notes/_note",
|
||||
layout: false,
|
||||
formats: [:html],
|
||||
locals: { note: note }
|
||||
)
|
||||
end
|
||||
|
||||
def project
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -64,6 +64,7 @@ class SnippetsController < ApplicationController
|
|||
blob = @snippet.blob
|
||||
override_max_blob_size(blob)
|
||||
|
||||
@note = Note.new(noteable: @snippet)
|
||||
@noteable = @snippet
|
||||
|
||||
@discussions = @snippet.discussions
|
||||
|
|
|
@ -123,7 +123,11 @@ module GitlabRoutingHelper
|
|||
end
|
||||
|
||||
def preview_markdown_path(project, *args)
|
||||
preview_markdown_namespace_project_path(project.namespace, project, *args)
|
||||
if @snippet.is_a?(PersonalSnippet)
|
||||
preview_markdown_snippet_path(@snippet)
|
||||
else
|
||||
preview_markdown_namespace_project_path(project.namespace, project, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_subscription_path(entity, *args)
|
||||
|
|
|
@ -76,4 +76,47 @@ module NotesHelper
|
|||
namespace_project_commit_path(discussion.project.namespace, discussion.project, discussion.noteable, anchor: anchor)
|
||||
end
|
||||
end
|
||||
|
||||
def notes_url
|
||||
if @snippet.is_a?(PersonalSnippet)
|
||||
snippet_notes_path(@snippet)
|
||||
else
|
||||
namespace_project_noteable_notes_path(
|
||||
namespace_id: @project.namespace,
|
||||
project_id: @project,
|
||||
target_id: @noteable.id,
|
||||
target_type: @noteable.class.name.underscore
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def note_url(note)
|
||||
if note.noteable.is_a?(PersonalSnippet)
|
||||
snippet_note_path(note.noteable, note)
|
||||
else
|
||||
namespace_project_note_path(@project.namespace, @project, note)
|
||||
end
|
||||
end
|
||||
|
||||
def form_resources
|
||||
if @snippet.is_a?(PersonalSnippet)
|
||||
[@note]
|
||||
else
|
||||
[@project.namespace.becomes(Namespace), @project, @note]
|
||||
end
|
||||
end
|
||||
|
||||
def new_form_url
|
||||
return nil unless @snippet.is_a?(PersonalSnippet)
|
||||
|
||||
snippet_notes_path(@snippet)
|
||||
end
|
||||
|
||||
def can_create_note?
|
||||
if @snippet.is_a?(PersonalSnippet)
|
||||
can?(current_user, :comment_personal_snippet, @snippet)
|
||||
else
|
||||
can?(current_user, :create_note, @project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,8 @@ module Notes
|
|||
def execute
|
||||
in_reply_to_discussion_id = params.delete(:in_reply_to_discussion_id)
|
||||
|
||||
if project && in_reply_to_discussion_id.present?
|
||||
discussion = project.notes.find_discussion(in_reply_to_discussion_id)
|
||||
if in_reply_to_discussion_id.present?
|
||||
discussion = find_discussion(in_reply_to_discussion_id)
|
||||
|
||||
unless discussion
|
||||
note = Note.new
|
||||
|
@ -21,5 +21,19 @@ module Notes
|
|||
|
||||
note
|
||||
end
|
||||
|
||||
def find_discussion(discussion_id)
|
||||
if project
|
||||
project.notes.find_discussion(discussion_id)
|
||||
else
|
||||
# only PersonalSnippets can have discussions without project association
|
||||
discussion = Note.find_discussion(discussion_id)
|
||||
noteable = discussion.noteable
|
||||
|
||||
return nil unless noteable.is_a?(PersonalSnippet) && can?(current_user, :comment_personal_snippet, noteable)
|
||||
|
||||
discussion
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
- header_title "Snippets", snippets_path
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
- if @snippet&.persisted? && current_user
|
||||
:javascript
|
||||
window.uploads_path = "#{upload_path('personal_snippet', @snippet)}";
|
||||
window.preview_markdown_path = "#{preview_markdown_snippet_path(@snippet)}";
|
||||
|
||||
= render template: "layouts/application"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
.block-connector
|
||||
= render "projects/diffs/diffs", diffs: @diffs, environment: @environment
|
||||
|
||||
= render "projects/notes/notes_with_form"
|
||||
= render "shared/notes/notes_with_form"
|
||||
- if can_collaborate_with_project?
|
||||
- %w(revert cherry-pick).each do |type|
|
||||
= render "projects/commit/change", type: type, commit: @commit, title: @commit.title
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {no_turbolink: true, original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
|
||||
|
||||
#notes
|
||||
= render 'projects/notes/notes_with_form'
|
||||
= render 'shared/notes/notes_with_form'
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
%button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { project_path: "#{project_path(@merge_request.project)}" } }
|
||||
{{ buttonText }}
|
||||
|
||||
#notes= render "projects/notes/notes_with_form"
|
||||
#notes= render "shared/notes/notes_with_form"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
.col-sm-10
|
||||
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project) } do
|
||||
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: 'Write milestone description...'
|
||||
= render 'projects/notes/hints'
|
||||
= render 'shared/notes/hints'
|
||||
.clearfix
|
||||
.error-alert
|
||||
= render "shared/milestones/form_dates", f: f
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.original-note-content.hidden{ data: { post_url: namespace_project_note_path(@project.namespace, @project, note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore } }
|
||||
#{note.note}
|
||||
%textarea.hidden.js-task-list-field.original-task-list{ data: {update_url: namespace_project_note_path(@project.namespace, @project, note) } }= note.note
|
|
@ -13,7 +13,7 @@
|
|||
= form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal common-note-form release-form js-quick-submit' }) do |f|
|
||||
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
|
||||
= render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here..."
|
||||
= render 'projects/notes/hints'
|
||||
= render 'shared/notes/hints'
|
||||
.error-alert
|
||||
.prepend-top-default
|
||||
= f.submit 'Save changes', class: 'btn btn-save'
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
.row-content-block.top-block.content-component-block
|
||||
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
|
||||
|
||||
#notes= render "projects/notes/notes_with_form"
|
||||
#notes= render "shared/notes/notes_with_form"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
.col-sm-10
|
||||
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
|
||||
= render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here..."
|
||||
= render 'projects/notes/hints'
|
||||
= render 'shared/notes/hints'
|
||||
.help-block Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page.
|
||||
.form-actions
|
||||
= button_tag 'Create tag', class: 'btn btn-create', tabindex: 3
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
.col-sm-10
|
||||
= render layout: 'projects/md_preview', locals: { url: namespace_project_wiki_preview_markdown_path(@project.namespace, @project, @page.slug) } do
|
||||
= render 'projects/zen', f: f, attr: :content, classes: 'note-textarea', placeholder: 'Write your content or drag files here...'
|
||||
= render 'projects/notes/hints'
|
||||
= render 'shared/notes/hints'
|
||||
|
||||
.clearfix
|
||||
.error-alert
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
classes: 'note-textarea',
|
||||
placeholder: "Write a comment or drag your files here...",
|
||||
supports_slash_commands: supports_slash_commands
|
||||
= render 'projects/notes/hints', supports_slash_commands: supports_slash_commands
|
||||
= render 'shared/notes/hints', supports_slash_commands: supports_slash_commands
|
||||
.clearfix
|
||||
.error-alert
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.original-note-content.hidden{ data: { post_url: note_url(note), target_id: note.noteable.id, target_type: note.noteable.class.name.underscore } }
|
||||
#{note.note}
|
||||
%textarea.hidden.js-task-list-field.original-task-list{ data: {update_url: note_url(note) } }= note.note
|
|
@ -4,7 +4,7 @@
|
|||
= hidden_field_tag :target_type, '', class: 'js-form-target-type'
|
||||
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(project), referenced_users: true } do
|
||||
= render 'projects/zen', attr: 'note[note]', classes: 'note-textarea js-note-text js-task-list-field', placeholder: "Write a comment or drag your files here..."
|
||||
= render 'projects/notes/hints'
|
||||
= render 'shared/notes/hints'
|
||||
|
||||
.note-form-actions.clearfix
|
||||
.settings-message.note-edit-warning.js-finish-edit-warning
|
|
@ -4,7 +4,7 @@
|
|||
- else
|
||||
- preview_url = preview_markdown_path(@project)
|
||||
|
||||
= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new-note js-new-note-form js-quick-submit common-note-form", "data-noteable-iid" => @note.noteable.try(:iid), }, authenticity_token: true do |f|
|
||||
= form_for form_resources, url: new_form_url, remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new-note js-new-note-form js-quick-submit common-note-form", "data-noteable-iid" => @note.noteable.try(:iid), }, authenticity_token: true do |f|
|
||||
= hidden_field_tag :view, diff_view
|
||||
= hidden_field_tag :line_type
|
||||
= hidden_field_tag :merge_request_diff_head_sha, @note.noteable.try(:diff_head_sha)
|
||||
|
@ -28,11 +28,11 @@
|
|||
classes: 'note-textarea js-note-text',
|
||||
placeholder: "Write a comment or drag your files here...",
|
||||
supports_slash_commands: supports_slash_commands
|
||||
= render 'projects/notes/hints', supports_slash_commands: supports_slash_commands
|
||||
= render 'shared/notes/hints', supports_slash_commands: supports_slash_commands
|
||||
.error-alert
|
||||
|
||||
.note-form-actions.clearfix
|
||||
= render partial: 'projects/notes/comment_button'
|
||||
= render partial: 'shared/notes/comment_button'
|
||||
|
||||
= yield(:note_actions)
|
||||
|
|
@ -42,10 +42,7 @@
|
|||
= note.redacted_note_html
|
||||
= edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago', include_author: true)
|
||||
- if note_editable
|
||||
- if note.for_personal_snippet?
|
||||
= render 'snippets/notes/edit', note: note
|
||||
- else
|
||||
= render 'projects/notes/edit', note: note
|
||||
= render 'shared/notes/edit', note: note
|
||||
.note-awards
|
||||
= render 'award_emoji/awards_block', awardable: note, inline: false
|
||||
- if note.system
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
%ul#notes-list.notes.main-notes-list.timeline
|
||||
= render "shared/notes/notes"
|
||||
|
||||
= render 'projects/notes/edit_form', project: @project
|
||||
= render 'shared/notes/edit_form', project: @project
|
||||
|
||||
%ul.notes.notes-form.timeline
|
||||
%li.timeline-entry
|
||||
.flash-container.timeline-content
|
||||
|
||||
- if can? current_user, :create_note, @project
|
||||
- if can_create_note?
|
||||
.timeline-icon.hidden-xs.hidden-sm
|
||||
%a.author_link{ href: user_path(current_user) }
|
||||
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
|
||||
.timeline-content.timeline-content-form
|
||||
= render "projects/notes/form", view: diff_view
|
||||
= render "shared/notes/form", view: diff_view
|
||||
- elsif !current_user
|
||||
.disabled-comment.text-center
|
||||
.disabled-comment-text.inline
|
||||
|
@ -23,4 +23,4 @@
|
|||
to post a comment
|
||||
|
||||
:javascript
|
||||
var notes = new Notes("#{namespace_project_noteable_notes_path(namespace_id: @project.namespace, project_id: @project, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}")
|
||||
var notes = new Notes("#{notes_url}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}")
|
|
@ -1,2 +0,0 @@
|
|||
%ul#notes-list.notes.main-notes-list.timeline
|
||||
= render "projects/notes/notes"
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
= render 'shared/snippets/header'
|
||||
|
||||
%article.file-holder.snippet-file-content
|
||||
= render 'shared/snippets/blob'
|
||||
.personal-snippets
|
||||
%article.file-holder.snippet-file-content
|
||||
= render 'shared/snippets/blob'
|
||||
|
||||
.row-content-block.top-block.content-component-block
|
||||
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
|
||||
.row-content-block.top-block.content-component-block
|
||||
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
|
||||
|
||||
%ul#notes-list.notes.main-notes-list.timeline
|
||||
#notes= render 'shared/notes/notes'
|
||||
#notes= render "shared/notes/notes_with_form"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Support comments for personal snippets
|
||||
merge_request:
|
||||
author:
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'projects/notes/_form' do
|
||||
describe 'shared/notes/_form' do
|
||||
include Devise::Test::ControllerHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
Loading…
Reference in New Issue