Commit b0bde100 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'hoopes/gitlab-ce-21027-add-diff-hunks-to-notification-emails' into 'master'

Add diff hunks to notification emails

Add diff hunks to notification emails. Continued from https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5855 - thanks @hoopes!

This also fixes an issue where the + / - prefixes were missing from diffs in emails.

Screenshots (from my browser) of the HTML emails, along with text screenshots 😛

![image](/uploads/cb31400becf5149d40c8bb98a655aa93/image.png)

```
New comment for Merge Request !1 on app/views/admin/builds/index.html.haml:

http://localhost:3000/gitlab-org/gitlab-ce/merge_requests/1#note_1023

>          Finished

This is a comment at the top of a match section.
```

![image](/uploads/704dd3845797530697a27f5c1953c053/image.png)

```
New comment for Merge Request !1 on app/views/admin/builds/index.html.haml:

http://localhost:3000/gitlab-org/gitlab-ce/merge_requests/1#note_1022

>          Finished
>          %span.badge.js-running-count= @all_builds.finished.count(:id)
>  
> -    %li{class: ('active' if @scope == 'all')}
> -      = link_to admin_builds_path(scope: :all) do
> -        All
> -        %span.badge.js-totalbuilds-count= @all_builds.count(:id)
> -
>  .gray-content-block
>    #{(@scope || 'running').capitalize} builds
>  

This is a comment at the bottom of a match section.
```

![image](/uploads/4063f3d9738aea8ebf3c0e690d0eddee/image.png)

```
New comment for Merge Request !1 on app/views/admin/builds/index.html.haml:

http://localhost:3000/gitlab-org/gitlab-ce/merge_requests/1#note_1024

>          = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
>  
>    %ul.center-top-menu
> -    %li{class: ('active' if @scope.nil?)}
> +    %li{class: ('active' if @scope == 'all')}
>        = link_to admin_builds_path do
> +        All

This is a comment with some deleted and added lines above it.
```

Closes #21027, closes #24340.

See merge request !7660
parents 3bf34fac 87665170
...@@ -4,6 +4,7 @@ module Emails ...@@ -4,6 +4,7 @@ module Emails
setup_note_mail(note_id, recipient_id) setup_note_mail(note_id, recipient_id)
@commit = @note.noteable @commit = @note.noteable
@discussion = @note.to_discussion if @note.diff_note?
@target_url = namespace_project_commit_url(*note_target_url_options) @target_url = namespace_project_commit_url(*note_target_url_options)
mail_answer_thread(@commit, mail_answer_thread(@commit,
...@@ -24,6 +25,7 @@ module Emails ...@@ -24,6 +25,7 @@ module Emails
setup_note_mail(note_id, recipient_id) setup_note_mail(note_id, recipient_id)
@merge_request = @note.noteable @merge_request = @note.noteable
@discussion = @note.to_discussion if @note.diff_note?
@target_url = namespace_project_merge_request_url(*note_target_url_options) @target_url = namespace_project_merge_request_url(*note_target_url_options)
mail_answer_thread(@merge_request, note_thread_options(recipient_id)) mail_answer_thread(@merge_request, note_thread_options(recipient_id))
end end
......
...@@ -25,7 +25,12 @@ class Discussion ...@@ -25,7 +25,12 @@ class Discussion
to: :last_resolved_note, to: :last_resolved_note,
allow_nil: true allow_nil: true
delegate :blob, :highlighted_diff_lines, to: :diff_file, allow_nil: true delegate :blob,
:highlighted_diff_lines,
:diff_lines,
to: :diff_file,
allow_nil: true
def self.for_notes(notes) def self.for_notes(notes)
notes.group_by(&:discussion_id).values.map { |notes| new(notes) } notes.group_by(&:discussion_id).values.map { |notes| new(notes) }
...@@ -159,10 +164,11 @@ class Discussion ...@@ -159,10 +164,11 @@ class Discussion
end end
# Returns an array of at most 16 highlighted lines above a diff note # Returns an array of at most 16 highlighted lines above a diff note
def truncated_diff_lines def truncated_diff_lines(highlight: true)
lines = highlight ? highlighted_diff_lines : diff_lines
prev_lines = [] prev_lines = []
highlighted_diff_lines.each do |line| lines.each do |line|
if line.meta? if line.meta?
prev_lines.clear prev_lines.clear
else else
......
<% if current_application_settings.email_author_in_body %>
<%= @note.author_name %> wrote:
<% end -%>
<%= @note.note %>
= content_for :head do
= stylesheet_link_tag 'mailers/highlighted_diff_email'
New comment
- if @discussion && @discussion.diff_file
on
= link_to @note.diff_file.file_path, @target_url, class: 'details'
\:
%table
= render partial: "projects/diffs/line",
collection: @discussion.truncated_diff_lines,
as: :line,
locals: { diff_file: @note.diff_file,
plain: true,
email: true }
= render 'note_message'
<% if @discussion && @discussion.diff_file -%>
on <%= @note.diff_file.file_path -%>
<% end -%>:
<%= url %>
<%= render 'simple_diff' if @discussion -%>
<%= render 'note_message' %>
<% @discussion.truncated_diff_lines(highlight: false).each do |line| %>
> <%= line.text %>
<% end %>
= render 'note_message' %p.details
= render 'note_mr_or_commit_email'
New comment for Commit <%= @commit.short_id %> New comment for Commit <%= @commit.short_id -%>
<%= render partial: 'note_mr_or_commit_email', locals: { url: @target_url } %>
<%= url_for(namespace_project_commit_url(@note.project.namespace, @note.project, id: @commit.id, anchor: "note_#{@note.id}")) %>
Author: <%= @note.author_name %>
<%= @note.note %>
- if @note.diff_note? && @note.diff_file %p.details
%p.details = render 'note_mr_or_commit_email'
New comment on diff for
= link_to @note.diff_file.file_path, @target_url
\:
= render 'note_message'
New comment for Merge Request <%= @merge_request.to_reference %> New comment for Merge Request <%= @merge_request.to_reference -%>
<%= render partial: 'note_mr_or_commit_email', locals: { url: @target_url }%>
<%= url_for(namespace_project_merge_request_url(@merge_request.target_project.namespace, @merge_request.target_project, @merge_request, anchor: "note_#{@note.id}")) %>
<%= @note.author_name %>
<%= @note.note %>
= content_for :head do = content_for :head do
= stylesheet_link_tag 'mailers/repository_push_email' = stylesheet_link_tag 'mailers/highlighted_diff_email'
%h3 %h3
#{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name} #{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name}
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
%a{href: "##{line_code}", data: { linenumber: link_text }} %a{href: "##{line_code}", data: { linenumber: link_text }}
%td.line_content.noteable_line{ class: type, data: (diff_view_line_data(line_code, diff_file.position(line), type) unless plain) }< %td.line_content.noteable_line{ class: type, data: (diff_view_line_data(line_code, diff_file.position(line), type) unless plain) }<
- if email - if email
%pre= diff_line_content(line.text) %pre= line.text
- else - else
= diff_line_content(line.text) = diff_line_content(line.text)
......
---
title: Add git diff context to notifications of new notes on merge requests
merge_request:
author: Heidi Hoopes
...@@ -50,7 +50,7 @@ describe Notify do ...@@ -50,7 +50,7 @@ describe Notify do
context 'when enabled email_author_in_body' do context 'when enabled email_author_in_body' do
before do before do
allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) stub_application_setting(email_author_in_body: true)
end end
it 'contains a link to note author' do it 'contains a link to note author' do
...@@ -229,7 +229,7 @@ describe Notify do ...@@ -229,7 +229,7 @@ describe Notify do
context 'when enabled email_author_in_body' do context 'when enabled email_author_in_body' do
before do before do
allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) stub_application_setting(email_author_in_body: true)
end end
it 'contains a link to note author' do it 'contains a link to note author' do
...@@ -607,7 +607,7 @@ describe Notify do ...@@ -607,7 +607,7 @@ describe Notify do
context 'when enabled email_author_in_body' do context 'when enabled email_author_in_body' do
before do before do
allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) stub_application_setting(email_author_in_body: true)
end end
it 'contains a link to note author' do it 'contains a link to note author' do
...@@ -686,6 +686,79 @@ describe Notify do ...@@ -686,6 +686,79 @@ describe Notify do
end end
end end
end end
context 'items that are noteable, emails for a note on a diff' do
let(:note_author) { create(:user, name: 'author_name') }
before :each do
allow(Note).to receive(:find).with(note.id).and_return(note)
end
shared_examples 'a note email on a diff' do |model|
let(:note) { create(model, project: project, author: note_author) }
it "includes diffs with character-level highlighting" do
is_expected.to have_body_text /<span class=\"p\">}<\/span><\/span>/
end
it 'contains a link to the diff file' do
is_expected.to have_body_text /#{note.diff_file.file_path}/
end
it_behaves_like 'it should have Gmail Actions links'
it 'is sent as the author' do
sender = subject.header[:from].addrs[0]
expect(sender.display_name).to eq(note_author.name)
expect(sender.address).to eq(gitlab_sender)
end
it 'is sent to the given recipient' do
is_expected.to deliver_to recipient.notification_email
end
it 'contains the message from the note' do
is_expected.to have_body_text /#{note.note}/
end
it 'does not contain note author' do
is_expected.not_to have_body_text /wrote\:/
end
context 'when enabled email_author_in_body' do
before do
stub_application_setting(email_author_in_body: true)
end
it 'contains a link to note author' do
is_expected.to have_body_text note.author_name
is_expected.to have_body_text /wrote\:/
end
end
end
describe 'on a commit' do
let(:commit) { project.commit }
let(:note) { create(:diff_note_on_commit) }
subject { Notify.note_commit_email(recipient.id, note.id) }
it_behaves_like 'a note email on a diff', :diff_note_on_commit
it_behaves_like 'it should show Gmail Actions View Commit link'
it_behaves_like 'a user cannot unsubscribe through footer link'
end
describe 'on a merge request' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let(:note) { create(:diff_note_on_merge_request) }
subject { Notify.note_merge_request_email(recipient.id, note.id) }
it_behaves_like 'a note email on a diff', :diff_note_on_merge_request
it_behaves_like 'it should show Gmail Actions View Merge request link'
it_behaves_like 'an unsubscribeable thread'
end
end
end end
context 'for a group' do context 'for a group' do
......
...@@ -590,4 +590,23 @@ describe Discussion, model: true do ...@@ -590,4 +590,23 @@ describe Discussion, model: true do
end end
end end
end end
describe "#truncated_diff_lines" do
let(:truncated_lines) { subject.truncated_diff_lines }
context "when diff is greater than allowed number of truncated diff lines " do
it "returns fewer lines" do
expect(subject.diff_lines.count).to be > described_class::NUMBER_OF_TRUNCATED_DIFF_LINES
expect(truncated_lines.count).to be <= described_class::NUMBER_OF_TRUNCATED_DIFF_LINES
end
end
context "when some diff lines are meta" do
it "returns no meta lines" do
expect(subject.diff_lines).to include(be_meta)
expect(truncated_lines).not_to include(be_meta)
end
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