Commit ab91f76e authored by Douwe Maan's avatar Douwe Maan

Add system note with link to diff comparison when MR discussion becomes outdated

parent 52527be4
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
.note-text { .note-text {
p:last-child { p:last-child {
margin-bottom: 0; margin-bottom: 0 !important;
} }
} }
......
...@@ -164,10 +164,6 @@ ...@@ -164,10 +164,6 @@
.discussion-body, .discussion-body,
.diff-file { .diff-file {
.notes .note {
padding: 10px 15px;
}
.discussion-reply-holder { .discussion-reply-holder {
background-color: $white-light; background-color: $white-light;
padding: 10px 16px; padding: 10px 16px;
......
...@@ -80,10 +80,6 @@ ul.notes { ...@@ -80,10 +80,6 @@ ul.notes {
&.timeline-entry { &.timeline-entry {
padding: 14px 10px; padding: 14px 10px;
} }
.system-note {
padding: 0;
}
} }
&.is-editing { &.is-editing {
...@@ -380,6 +376,10 @@ ul.notes { ...@@ -380,6 +376,10 @@ ul.notes {
padding-bottom: 5px; padding-bottom: 5px;
} }
.system-note .note-header-info {
padding-bottom: 0;
}
.note-headline-light { .note-headline-light {
display: inline; display: inline;
...@@ -582,6 +582,17 @@ ul.notes { ...@@ -582,6 +582,17 @@ ul.notes {
} }
} }
.discussion-body,
.diff-file {
.notes .note {
padding: 10px 15px;
&.system-note {
padding: 0;
}
}
}
.diff-file { .diff-file {
.is-over { .is-over {
.add-diff-note { .add-diff-note {
......
...@@ -17,7 +17,8 @@ module SystemNoteHelper ...@@ -17,7 +17,8 @@ module SystemNoteHelper
'visible' => 'icon_eye', 'visible' => 'icon_eye',
'milestone' => 'icon_clock_o', 'milestone' => 'icon_clock_o',
'discussion' => 'icon_comment_o', 'discussion' => 'icon_comment_o',
'moved' => 'icon_arrow_circle_o_right' 'moved' => 'icon_arrow_circle_o_right',
'outdated' => 'icon_edit'
}.freeze }.freeze
def icon_for_system_note(note) def icon_for_system_note(note)
......
...@@ -19,21 +19,9 @@ class DiffDiscussion < Discussion ...@@ -19,21 +19,9 @@ class DiffDiscussion < Discussion
def merge_request_version_params def merge_request_version_params
return unless for_merge_request? return unless for_merge_request?
return {} if active?
if active? noteable.version_params_for(position.diff_refs)
{}
else
diff_refs = position.diff_refs
if diff = noteable.merge_request_diff_for(diff_refs)
{ diff_id: diff.id }
elsif diff = noteable.merge_request_diff_for(diff_refs.head_sha)
{
diff_id: diff.id,
start_sha: diff_refs.start_sha
}
end
end
end end
def reply_attributes def reply_attributes
......
...@@ -8,6 +8,7 @@ class DiffNote < Note ...@@ -8,6 +8,7 @@ class DiffNote < Note
serialize :original_position, Gitlab::Diff::Position serialize :original_position, Gitlab::Diff::Position
serialize :position, Gitlab::Diff::Position serialize :position, Gitlab::Diff::Position
serialize :change_position, Gitlab::Diff::Position
validates :original_position, presence: true validates :original_position, presence: true
validates :position, presence: true validates :position, presence: true
...@@ -25,7 +26,7 @@ class DiffNote < Note ...@@ -25,7 +26,7 @@ class DiffNote < Note
DiffDiscussion DiffDiscussion
end end
%i(original_position position).each do |meth| %i(original_position position change_position).each do |meth|
define_method "#{meth}=" do |new_position| define_method "#{meth}=" do |new_position|
if new_position.is_a?(String) if new_position.is_a?(String)
new_position = JSON.parse(new_position) rescue nil new_position = JSON.parse(new_position) rescue nil
...@@ -36,6 +37,8 @@ class DiffNote < Note ...@@ -36,6 +37,8 @@ class DiffNote < Note
new_position = Gitlab::Diff::Position.new(new_position) new_position = Gitlab::Diff::Position.new(new_position)
end end
return if new_position == read_attribute(meth)
super(new_position) super(new_position)
end end
end end
...@@ -45,7 +48,7 @@ class DiffNote < Note ...@@ -45,7 +48,7 @@ class DiffNote < Note
end end
def diff_line def diff_line
@diff_line ||= diff_file.line_for_position(self.original_position) if diff_file @diff_line ||= diff_file&.line_for_position(self.original_position)
end end
def for_line?(line) def for_line?(line)
......
...@@ -416,13 +416,24 @@ class MergeRequest < ActiveRecord::Base ...@@ -416,13 +416,24 @@ class MergeRequest < ActiveRecord::Base
@merge_request_diffs_by_diff_refs_or_sha[diff_refs_or_sha] @merge_request_diffs_by_diff_refs_or_sha[diff_refs_or_sha]
end end
def version_params_for(diff_refs)
if diff = merge_request_diff_for(diff_refs)
{ diff_id: diff.id }
elsif diff = merge_request_diff_for(diff_refs.head_sha)
{
diff_id: diff.id,
start_sha: diff_refs.start_sha
}
end
end
def reload_diff_if_branch_changed def reload_diff_if_branch_changed
if source_branch_changed? || target_branch_changed? if source_branch_changed? || target_branch_changed?
reload_diff reload_diff
end end
end end
def reload_diff def reload_diff(current_user = nil)
return unless open? return unless open?
old_diff_refs = self.diff_refs old_diff_refs = self.diff_refs
...@@ -432,7 +443,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -432,7 +443,8 @@ class MergeRequest < ActiveRecord::Base
update_diff_notes_positions( update_diff_notes_positions(
old_diff_refs: old_diff_refs, old_diff_refs: old_diff_refs,
new_diff_refs: new_diff_refs new_diff_refs: new_diff_refs,
current_user: current_user
) )
end end
...@@ -861,7 +873,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -861,7 +873,7 @@ class MergeRequest < ActiveRecord::Base
diff_sha_refs && diff_sha_refs.complete? diff_sha_refs && diff_sha_refs.complete?
end end
def update_diff_notes_positions(old_diff_refs:, new_diff_refs:) def update_diff_notes_positions(old_diff_refs:, new_diff_refs:, current_user: nil)
return unless has_complete_diff_refs? return unless has_complete_diff_refs?
return if new_diff_refs == old_diff_refs return if new_diff_refs == old_diff_refs
...@@ -875,7 +887,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -875,7 +887,7 @@ class MergeRequest < ActiveRecord::Base
service = Notes::DiffPositionUpdateService.new( service = Notes::DiffPositionUpdateService.new(
self.project, self.project,
nil, current_user,
old_diff_refs: old_diff_refs, old_diff_refs: old_diff_refs,
new_diff_refs: new_diff_refs, new_diff_refs: new_diff_refs,
paths: paths paths: paths
......
...@@ -175,12 +175,11 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -175,12 +175,11 @@ class MergeRequestDiff < ActiveRecord::Base
self == merge_request.merge_request_diff self == merge_request.merge_request_diff
end end
def compare_with(sha, straight: true) def compare_with(sha)
# When compare merge request versions we want diff A..B instead of A...B # When compare merge request versions we want diff A..B instead of A...B
# so we handle cases when user does squash and rebase of the commits between versions. # so we handle cases when user does squash and rebase of the commits between versions.
# For this reason we set straight to true by default. # For this reason we set straight to true by default.
CompareService.new(project, head_commit_sha) CompareService.new(project, head_commit_sha).execute(project, sha, straight: true)
.execute(project, sha, straight: straight)
end end
def commits_count def commits_count
......
...@@ -121,16 +121,17 @@ class Note < ActiveRecord::Base ...@@ -121,16 +121,17 @@ class Note < ActiveRecord::Base
end end
def grouped_diff_discussions(diff_refs = nil) def grouped_diff_discussions(diff_refs = nil)
groups = {} groups = Hash.new { |h, k| h[k] = [] }
diff_notes.fresh.discussions.each do |discussion| diff_notes.fresh.discussions.each do |discussion|
line_code =
if discussion.active?(diff_refs) if discussion.active?(diff_refs)
discussions = groups[discussion.line_code] ||= [] discussion.line_code
elsif diff_refs && discussion.created_at_diff?(diff_refs) elsif diff_refs && discussion.created_at_diff?(diff_refs)
discussions = groups[discussion.original_line_code] ||= [] discussion.original_line_code
end end
discussions << discussion if discussions groups[line_code] << discussion if line_code
end end
groups groups
......
...@@ -2,6 +2,7 @@ class SystemNoteMetadata < ActiveRecord::Base ...@@ -2,6 +2,7 @@ class SystemNoteMetadata < ActiveRecord::Base
ICON_TYPES = %w[ ICON_TYPES = %w[
commit description merge confidential visible label assignee cross_reference commit description merge confidential visible label assignee cross_reference
title time_tracking branch milestone discussion task moved opened closed merged title time_tracking branch milestone discussion task moved opened closed merged
outdated
].freeze ].freeze
validates :note, presence: true validates :note, presence: true
......
...@@ -66,12 +66,12 @@ module MergeRequests ...@@ -66,12 +66,12 @@ module MergeRequests
filter_merge_requests(merge_requests).each do |merge_request| filter_merge_requests(merge_requests).each do |merge_request|
if merge_request.source_branch == @branch_name || force_push? if merge_request.source_branch == @branch_name || force_push?
merge_request.reload_diff merge_request.reload_diff(current_user)
else else
mr_commit_ids = merge_request.commits_sha mr_commit_ids = merge_request.commits_sha
push_commit_ids = @commits.map(&:id) push_commit_ids = @commits.map(&:id)
matches = mr_commit_ids & push_commit_ids matches = mr_commit_ids & push_commit_ids
merge_request.reload_diff if matches.any? merge_request.reload_diff(current_user) if matches.any?
end end
merge_request.mark_as_unchecked merge_request.mark_as_unchecked
......
...@@ -8,7 +8,7 @@ module MergeRequests ...@@ -8,7 +8,7 @@ module MergeRequests
create_note(merge_request) create_note(merge_request)
notification_service.reopen_mr(merge_request, current_user) notification_service.reopen_mr(merge_request, current_user)
execute_hooks(merge_request, 'reopen') execute_hooks(merge_request, 'reopen')
merge_request.reload_diff merge_request.reload_diff(current_user)
merge_request.mark_as_unchecked merge_request.mark_as_unchecked
end end
......
module Notes module Notes
class DiffPositionUpdateService < BaseService class DiffPositionUpdateService < BaseService
def execute(note) def execute(note)
new_position = tracer.trace(note.position) results = tracer.trace(note.position)
return unless results
# Don't update the position if the type doesn't match, since that means position = results[:position]
# the diff line commented on was changed, and the comment is now outdated outdated = results[:outdated]
old_position = note.position
if new_position &&
new_position != old_position &&
new_position.type == old_position.type
note.position = new_position if outdated
end note.change_position = position
note if note.persisted? && current_user
SystemNoteService.diff_discussion_outdated(note.to_discussion, project, current_user, position)
end
else
note.position = position
note.change_position = nil
end
end end
private private
def tracer def tracer
@tracer ||= Gitlab::Diff::PositionTracer.new( @tracer ||= Gitlab::Diff::PositionTracer.new(
repository: project.repository, project: project,
old_diff_refs: params[:old_diff_refs], old_diff_refs: params[:old_diff_refs],
new_diff_refs: params[:new_diff_refs], new_diff_refs: params[:new_diff_refs],
paths: params[:paths] paths: params[:paths]
......
...@@ -258,7 +258,7 @@ module SystemNoteService ...@@ -258,7 +258,7 @@ module SystemNoteService
create_note(NoteSummary.new(noteable, project, author, body, action: 'title')) create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
end end
def self.resolve_all_discussions(merge_request, project, author) def resolve_all_discussions(merge_request, project, author)
body = "resolved all discussions" body = "resolved all discussions"
create_note(NoteSummary.new(merge_request, project, author, body, action: 'discussion')) create_note(NoteSummary.new(merge_request, project, author, body, action: 'discussion'))
...@@ -274,6 +274,28 @@ module SystemNoteService ...@@ -274,6 +274,28 @@ module SystemNoteService
note note
end end
def diff_discussion_outdated(discussion, project, author, change_position)
merge_request = discussion.noteable
diff_refs = change_position.diff_refs
version_index = merge_request.merge_request_diffs.viewable.count
body = "changed this line in"
if version_params = merge_request.version_params_for(diff_refs)
line_code = change_position.line_code(project.repository)
url = url_helpers.diffs_namespace_project_merge_request_url(project.namespace, project, merge_request, version_params.merge(anchor: line_code))
body << " [version #{version_index} of the diff](#{url})"
else
body << " version #{version_index} of the diff"
end
note_attributes = discussion.reply_attributes.merge(project: project, author: author, note: body)
note = Note.create(note_attributes.merge(system: true))
note.system_note_metadata = SystemNoteMetadata.new(action: 'outdated')
note
end
# Called when the title of a Noteable is changed # Called when the title of a Noteable is changed
# #
# noteable - Noteable object that responds to `title` # noteable - Noteable object that responds to `title`
......
...@@ -32,10 +32,9 @@ ...@@ -32,10 +32,9 @@
- elsif discussion.diff_discussion? - elsif discussion.diff_discussion?
on on
= conditional_link_to url.present?, url do = conditional_link_to url.present?, url do
- if discussion.active? - unless discussion.active?
an old version of
the diff the diff
- else
an outdated diff
= time_ago_with_tooltip(discussion.created_at, placement: "bottom", html_class: "note-created-ago") = time_ago_with_tooltip(discussion.created_at, placement: "bottom", html_class: "note-created-ago")
= render "discussions/headline", discussion: discussion = render "discussions/headline", discussion: discussion
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
comparing two versions comparing two versions
- else - else
viewing an old version viewing an old version
of this merge request. of the diff.
.pull-right .pull-right
= link_to 'Show latest version', diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-sm' = link_to 'Show latest version', diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-sm'
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddChangePositionToNotes < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index", "remove_concurrent_index" or
# "add_column_with_default" you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
# any other changes should go in a separate migration.
# This ensures that upon failure _only_ the index creation or removing fails
# and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
# disable_ddl_transaction!
def change
add_column :notes, :change_position, :text
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170518231126) do ActiveRecord::Schema.define(version: 20170521184006) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -794,6 +794,7 @@ ActiveRecord::Schema.define(version: 20170518231126) do ...@@ -794,6 +794,7 @@ ActiveRecord::Schema.define(version: 20170518231126) do
t.string "discussion_id" t.string "discussion_id"
t.text "note_html" t.text "note_html"
t.integer "cached_markdown_version" t.integer "cached_markdown_version"
t.text "change_position"
end end
add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
......
...@@ -24,6 +24,14 @@ module Gitlab ...@@ -24,6 +24,14 @@ module Gitlab
@diff_files ||= @diffs.decorate! { |diff| decorate_diff!(diff) } @diff_files ||= @diffs.decorate! { |diff| decorate_diff!(diff) }
end end
def diff_file_with_old_path(old_path)
diff_files.find { |diff_file| diff_file.old_path == old_path }
end
def diff_file_with_new_path(new_path)
diff_files.find { |diff_file| diff_file.new_path == new_path }
end
private private
def decorate_diff!(diff) def decorate_diff!(diff)
......
...@@ -12,20 +12,26 @@ module Gitlab ...@@ -12,20 +12,26 @@ module Gitlab
attr_reader :head_sha attr_reader :head_sha
def initialize(attrs = {}) def initialize(attrs = {})
if diff_file = attrs[:diff_file]
attrs[:diff_refs] = diff_file.diff_refs
attrs[:old_path] = diff_file.old_path
attrs[:new_path] = diff_file.new_path
end
if diff_refs = attrs[:diff_refs]
attrs[:base_sha] = diff_refs.base_sha
attrs[:start_sha] = diff_refs.start_sha
attrs[:head_sha] = diff_refs.head_sha
end
@old_path = attrs[:old_path] @old_path = attrs[:old_path]
@new_path = attrs[:new_path] @new_path = attrs[:new_path]
@old_line = attrs[:old_line]
@new_line = attrs[:new_line]
if attrs[:diff_refs]
@base_sha = attrs[:diff_refs].base_sha
@start_sha = attrs[:diff_refs].start_sha
@head_sha = attrs[:diff_refs].head_sha
else
@base_sha = attrs[:base_sha] @base_sha = attrs[:base_sha]
@start_sha = attrs[:start_sha] @start_sha = attrs[:start_sha]
@head_sha = attrs[:head_sha] @head_sha = attrs[:head_sha]
end
@old_line = attrs[:old_line]
@new_line = attrs[:new_line]
end end
# `Gitlab::Diff::Position` objects are stored as serialized attributes in # `Gitlab::Diff::Position` objects are stored as serialized attributes in
...@@ -129,11 +135,11 @@ module Gitlab ...@@ -129,11 +135,11 @@ module Gitlab
end end
def diff_line(repository) def diff_line(repository)
@diff_line ||= diff_file(repository).line_for_position(self) @diff_line ||= diff_file(repository)&.line_for_position(self)
end end
def line_code(repository) def line_code(repository)
@line_code ||= diff_file(repository).line_code_for_position(self) @line_code ||= diff_file(repository)&.line_code_for_position(self)
end end
private private
......
This diff is collapsed.
...@@ -124,6 +124,8 @@ feature 'Merge Request versions', js: true, feature: true do ...@@ -124,6 +124,8 @@ feature 'Merge Request versions', js: true, feature: true do
diff_refs: merge_request_diff3.compare_with(merge_request_diff1.head_commit_sha).diff_refs diff_refs: merge_request_diff3.compare_with(merge_request_diff1.head_commit_sha).diff_refs
) )
outdated_diff_note = create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position) outdated_diff_note = create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position)
outdated_diff_note.position = outdated_diff_note.original_position
outdated_diff_note.save!
visit current_url visit current_url
wait_for_ajax wait_for_ajax
......
...@@ -48,7 +48,7 @@ describe DiffDiscussion, model: true do ...@@ -48,7 +48,7 @@ describe DiffDiscussion, model: true do
end end
it 'returns the diff ID for the version to show' do it 'returns the diff ID for the version to show' do
expect(diff_id: merge_request_diff1.id) expect(subject.merge_request_version_params).to eq(diff_id: merge_request_diff1.id)
end end
end end
...@@ -65,6 +65,11 @@ describe DiffDiscussion, model: true do ...@@ -65,6 +65,11 @@ describe DiffDiscussion, model: true do
let(:diff_note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, position: position) } let(:diff_note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, position: position) }
before do
diff_note.position = diff_note.original_position
diff_note.save!
end
it 'returns the diff ID and start sha of the versions to compare' do it 'returns the diff ID and start sha of the versions to compare' do
expect(subject.merge_request_version_params).to eq(diff_id: merge_request_diff3.id, start_sha: merge_request_diff1.head_commit_sha) expect(subject.merge_request_version_params).to eq(diff_id: merge_request_diff3.id, start_sha: merge_request_diff1.head_commit_sha)
end end
......
...@@ -1213,7 +1213,7 @@ describe MergeRequest, models: true do ...@@ -1213,7 +1213,7 @@ describe MergeRequest, models: true do
expect(Notes::DiffPositionUpdateService).to receive(:new).with( expect(Notes::DiffPositionUpdateService).to receive(:new).with(
subject.project, subject.project,
nil, subject.author,
old_diff_refs: old_diff_refs, old_diff_refs: old_diff_refs,
new_diff_refs: commit.diff_refs, new_diff_refs: commit.diff_refs,
paths: note.position.paths paths: note.position.paths
...@@ -1222,7 +1222,7 @@ describe MergeRequest, models: true do ...@@ -1222,7 +1222,7 @@ describe MergeRequest, models: true do
expect_any_instance_of(Notes::DiffPositionUpdateService).to receive(:execute).with(note) expect_any_instance_of(Notes::DiffPositionUpdateService).to receive(:execute).with(note)
expect_any_instance_of(DiffNote).to receive(:save).once expect_any_instance_of(DiffNote).to receive(:save).once
subject.reload_diff subject.reload_diff(subject.author)
end end
end end
...@@ -1534,4 +1534,36 @@ describe MergeRequest, models: true do ...@@ -1534,4 +1534,36 @@ describe MergeRequest, models: true do
end end
end end
end end
describe '#version_params_for' do
subject { create(:merge_request, importing: true) }
let(:project) { subject.project }
let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
let!(:merge_request_diff3) { subject.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
context 'when the diff refs are for an older merge request version' do
let(:diff_refs) { merge_request_diff1.diff_refs }
it 'returns the diff ID for the version to show' do
expect(subject.version_params_for(diff_refs)).to eq(diff_id: merge_request_diff1.id)
end
end
context 'when the diff refs are for a comparison between merge request versions' do
let(:diff_refs) { merge_request_diff3.compare_with(merge_request_diff1.head_commit_sha).diff_refs }
it 'returns the diff ID and start sha of the versions to compare' do
expect(subject.version_params_for(diff_refs)).to eq(diff_id: merge_request_diff3.id, start_sha: merge_request_diff1.head_commit_sha)
end
end
context 'when the diff refs are not for a merge request version' do
let(:diff_refs) { project.commit(sample_commit.id).diff_refs }
it 'returns nil' do
expect(subject.version_params_for(diff_refs)).to be_nil
end
end
end
end end
...@@ -2,6 +2,7 @@ require 'spec_helper' ...@@ -2,6 +2,7 @@ require 'spec_helper'
describe Notes::DiffPositionUpdateService, services: true do describe Notes::DiffPositionUpdateService, services: true do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:current_user) { project.owner }
let(:create_commit) { project.commit("913c66a37b4a45b9769037c55c2d238bd0942d2e") } let(:create_commit) { project.commit("913c66a37b4a45b9769037c55c2d238bd0942d2e") }
let(:modify_commit) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e") } let(:modify_commit) { project.commit("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
let(:edit_commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") } let(:edit_commit) { project.commit("570e7b2abdd848b95f2f578043fc23bd6f6fd24d") }
...@@ -25,7 +26,7 @@ describe Notes::DiffPositionUpdateService, services: true do ...@@ -25,7 +26,7 @@ describe Notes::DiffPositionUpdateService, services: true do
subject do subject do
described_class.new( described_class.new(
project, project,
nil, current_user,
old_diff_refs: old_diff_refs, old_diff_refs: old_diff_refs,
new_diff_refs: new_diff_refs, new_diff_refs: new_diff_refs,
paths: [path] paths: [path]
...@@ -170,6 +171,23 @@ describe Notes::DiffPositionUpdateService, services: true do ...@@ -170,6 +171,23 @@ describe Notes::DiffPositionUpdateService, services: true do
expect(note.original_position).to eq(old_position) expect(note.original_position).to eq(old_position)
expect(note.position).to eq(old_position) expect(note.position).to eq(old_position)
end end
it 'sets the change position' do
subject.execute(note)
change_position = note.change_position
expect(change_position.start_sha).to eq(old_diff_refs.head_sha)
expect(change_position.head_sha).to eq(new_diff_refs.head_sha)
expect(change_position.old_line).to eq(9)
expect(change_position.new_line).to be_nil
end
it 'creates a system note' do
expect(SystemNoteService).to receive(:diff_discussion_outdated).with(
note.to_discussion, project, current_user, instance_of(Gitlab::Diff::Position))
subject.execute(note)
end
end end
end end
end end
...@@ -1034,4 +1034,35 @@ describe SystemNoteService, services: true do ...@@ -1034,4 +1034,35 @@ describe SystemNoteService, services: true do
expect(subject.note).to eq 'resolved all discussions' expect(subject.note).to eq 'resolved all discussions'
end end
end end
describe '.diff_discussion_outdated' do
let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
let(:merge_request) { discussion.noteable }
let(:project) { merge_request.source_project }
let(:change_position) { discussion.position }
def reloaded_merge_request
MergeRequest.find(merge_request.id)
end
subject { described_class.diff_discussion_outdated(discussion, project, author, change_position) }
it_behaves_like 'a system note' do
let(:expected_noteable) { discussion.first_note.noteable }
let(:action) { 'outdated' }
end
it 'creates a new note in the discussion' do
# we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded.
expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1)
end
it 'links to the diff in the system note' do
expect(subject.note).to include('version 1')
diff_id = merge_request.merge_request_diff.id
line_code = change_position.line_code(project.repository)
expect(subject.note).to include(diffs_namespace_project_merge_request_url(project.namespace, project, merge_request, diff_id: diff_id, anchor: line_code))
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment