Ensure only renderable text diffs are collapsed

Other diffs (those that are too large to render anyway, image diffs,
diffs suppressed by .gitattributes) should be rendered immediately.
This commit is contained in:
Sean McGivern 2016-07-06 12:36:39 +01:00
parent b8d3016abb
commit 90a6be190f
8 changed files with 166 additions and 10 deletions

View file

@ -2,13 +2,15 @@ class @SingleDiff
LOADING_HTML = '<i class="fa fa-spinner fa-spin"></i>'
ERROR_HTML = '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>'
COLLAPSED_HTML = '<div class="nothing-here-block diff-collapsed">This diff is collapsed. Click to expand it.</div>'
constructor: (@file) ->
@content = $('.diff-content', @file)
@diffForPath = @content.data 'diff-for-path'
@diffForPath = @content.find('[data-diff-for-path]').data 'diff-for-path'
@setOpenState()
$('.file-title > a', @file).on 'click', @toggleDiff
@enableToggleOnContent()
setOpenState: ->
if @diffForPath
@ -18,11 +20,15 @@ class @SingleDiff
@contentHTML = @content.html()
return
enableToggleOnContent: ->
@content.find('.nothing-here-block.diff-collapsed').on 'click', @toggleDiff
toggleDiff: (e) =>
e.preventDefault()
@isOpen = !@isOpen
if not @isOpen and not @hasError
@content.empty()
@content.html COLLAPSED_HTML
@enableToggleOnContent
return
if @contentHTML
@setContentHTML()

View file

@ -189,3 +189,7 @@ span.idiff {
border-bottom-right-radius: 2px;
}
}
.nothing-here-block.diff-collapsed {
cursor: pointer;
}

View file

@ -15,6 +15,7 @@ module DiffHelper
diff_commit = commit_for_diff(diff_file)
blob = project.repository.blob_for_diff(diff_commit, diff_file)
@expand_all = true
locals = {
diff_file: diff_file,

View file

@ -9,7 +9,11 @@
- if !project.repository.diffable?(blob)
.nothing-here-block This diff was suppressed by a .gitattributes entry.
- elsif diff_file.diff_lines.length > 0
- if diff_view == 'parallel'
- if diff_file.collapsed_by_default? && !@expand_all
- url = url_for(params.merge(action: :diff_for_path, path: diff_file.file_path, format: nil))
.nothing-here-block.diff-collapsed{data: { diff_for_path: url } }
This diff is collapsed. Click to expand it.
- elsif diff_view == 'parallel'
= render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob
- else
= render "projects/diffs/text_file", diff_file: diff_file

View file

@ -16,9 +16,4 @@
= view_file_btn(diff_commit.id, diff_file, project)
- if diff_file.collapsed_by_default?
- url = url_for(params.merge(action: :diff_for_path, path: diff_file.file_path, format: nil))
.diff-content.diff-wrap-lines{data: { diff_for_path: url }}
.nothing-here-block File hidden by default; content for this element available at #{url}
- else
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project
= render 'projects/diffs/content', diff_file: diff_file, diff_commit: diff_commit, diff_refs: diff_refs, blob: blob, project: project

View file

@ -0,0 +1,138 @@
require 'spec_helper'
feature 'Expand and collapse diffs', js: true, feature: true do
include WaitForAjax
before do
login_as :admin
merge_request = create(:merge_request, source_branch: 'expand-collapse-diffs', target_branch: 'master')
project = merge_request.source_project
# Ensure that undiffable.md is in .gitattributes
project.repository.copy_gitattributes('expand-collapse-diffs')
visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request)
execute_script('window.ajaxUris = []; $(document).ajaxSend(function(event, xhr, settings) { ajaxUris.push(settings.url) });')
end
def file_container(filename)
find("[data-blob-diff-path*='#{filename}']")
end
# Use define_method instead of let (which is memoized) so that this just works across a
# reload.
#
['small_diff.md', 'large_diff.md', 'undiffable.md', 'too_large.md', 'too_large_image.jpg'].each do |file|
define_method(file.split('.').first) { file_container(file) }
end
context 'visiting an existing merge request' do
it 'shows small diffs immediately' do
expect(small_diff).to have_selector('.code')
expect(small_diff).not_to have_selector('.nothing-here-block')
end
it 'collapses larges diffs by default' do
expect(large_diff).not_to have_selector('.code')
expect(large_diff).to have_selector('.nothing-here-block')
end
it 'shows non-renderable diffs as such immediately, regardless of their size' do
expect(undiffable).not_to have_selector('.code')
expect(undiffable).to have_selector('.nothing-here-block')
expect(undiffable).to have_content('gitattributes')
end
it 'does not allow diffs that are larger than the maximum size to be expanded' do
expect(too_large).not_to have_selector('.code')
expect(too_large).to have_selector('.nothing-here-block')
expect(too_large).to have_content('too large')
end
it 'shows image diffs immediately, regardless of their size' do
expect(too_large_image).not_to have_selector('.nothing-here-block')
expect(too_large_image).to have_selector('.image')
end
context 'expanding a large diff' do
before do
click_link('large_diff.md')
wait_for_ajax
end
it 'makes a request to get the content' do
ajax_uris = evaluate_script('ajaxUris')
expect(ajax_uris).not_to be_empty
expect(ajax_uris.first).to include('large_diff.md')
end
it 'shows the diff content' do
expect(large_diff).to have_selector('.code')
expect(large_diff).not_to have_selector('.nothing-here-block')
end
context 'adding a comment to the expanded diff' do
let(:comment_text) { 'A comment' }
before do
large_diff.find('.line_holder', match: :prefer_exact).hover
large_diff.find('.add-diff-note').click
large_diff.find('.note-textarea').send_keys comment_text
large_diff.find_button('Comment').click
wait_for_ajax
end
it 'adds the comment' do
expect(large_diff.find('.notes')).to have_content comment_text
end
context 'reloading the page' do
before { refresh }
it 'collapses the large diff by default' do
expect(large_diff).not_to have_selector('.code')
expect(large_diff).to have_selector('.nothing-here-block')
end
context 'expanding the diff' do
before do
click_link('large_diff.md')
wait_for_ajax
end
it 'shows the diff content' do
expect(large_diff).to have_selector('.code')
expect(large_diff).not_to have_selector('.nothing-here-block')
end
it 'shows the diff comment' do
expect(large_diff.find('.notes')).to have_content comment_text
end
end
end
end
end
context 'collapsing an expanded diff' do
before { click_link('small_diff.md') }
it 'hides the diff content' do
expect(small_diff).not_to have_selector('.code')
expect(small_diff).to have_selector('.nothing-here-block')
end
context 're-expanding the same diff' do
before { click_link('small_diff.md') }
it 'shows the diff content' do
expect(small_diff).to have_selector('.code')
expect(small_diff).not_to have_selector('.nothing-here-block')
end
it 'does not make a new HTTP request' do
expect(evaluate_script('ajaxUris')).to be_empty
end
end
end
end
end

View file

@ -76,7 +76,7 @@ feature 'Prioritize labels', feature: true do
expect(page.all('li').last).to have_content('bug')
end
visit current_url
refresh
wait_for_ajax
page.within('.prioritized-labels') do

View file

@ -27,6 +27,14 @@ module CapybaraHelpers
end
end
end
# Refresh the page. Calling `visit current_url` doesn't seem to work consistently.
#
def refresh
url = current_url
visit 'about:blank'
visit url
end
end
RSpec.configure do |config|