BigW Consortium Gitlab

diff_helper_spec.rb 10 KB
Newer Older
Marin Jankovski committed
1 2 3 4 5
require 'spec_helper'

describe DiffHelper do
  include RepoHelpers

6
  let(:project) { create(:project, :repository) }
7
  let(:repository) { project.repository }
8
  let(:commit) { project.commit(sample_commit.id) }
9
  let(:diffs) { commit.raw_diffs }
10
  let(:diff) { diffs.first }
Douwe Maan committed
11
  let(:diff_refs) { commit.diff_refs }
12
  let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
Marin Jankovski committed
13

14
  describe 'diff_view' do
15 16 17 18 19 20 21 22 23 24 25 26 27
    it 'uses the view param over the cookie' do
      controller.params[:view] = 'parallel'
      helper.request.cookies[:diff_view] = 'inline'

      expect(helper.diff_view).to eq :parallel
    end

    it 'returns the default value when the view param is invalid' do
      controller.params[:view] = 'invalid'

      expect(helper.diff_view).to eq :inline
    end

28 29 30
    it 'returns a valid value when cookie is set' do
      helper.request.cookies[:diff_view] = 'parallel'

31
      expect(helper.diff_view).to eq :parallel
32 33
    end

34
    it 'returns the default value when cookie is invalid' do
35 36
      helper.request.cookies[:diff_view] = 'invalid'

37
      expect(helper.diff_view).to eq :inline
38 39
    end

40
    it 'returns the default value when cookie is nil' do
41 42
      expect(helper.request.cookies).to be_empty

43
      expect(helper.diff_view).to eq :inline
44 45
    end
  end
46

47
  describe 'diff_options' do
48
    it 'returns no collapse false' do
49
      expect(diff_options).to include(expanded: false)
50 51
    end

52 53 54
    it 'returns no collapse true if expanded' do
      allow(controller).to receive(:params) { { expanded: true } }
      expect(diff_options).to include(expanded: true)
55 56
    end

57
    it 'returns no collapse true if action name diff_for_path' do
58
      allow(controller).to receive(:action_name) { 'diff_for_path' }
59
      expect(diff_options).to include(expanded: true)
60
    end
61

62
    it 'returns paths if action name diff_for_path and param old path' do
63 64 65 66 67
      allow(controller).to receive(:params) { { old_path: 'lib/wadus.rb' } }
      allow(controller).to receive(:action_name) { 'diff_for_path' }
      expect(diff_options[:paths]).to include('lib/wadus.rb')
    end

68
    it 'returns paths if action name diff_for_path and param new path' do
69 70 71 72
      allow(controller).to receive(:params) { { new_path: 'lib/wadus.rb' } }
      allow(controller).to receive(:action_name) { 'diff_for_path' }
      expect(diff_options[:paths]).to include('lib/wadus.rb')
    end
73 74
  end

75
  describe '#diff_line_content' do
76 77 78 79 80 81 82 83
    context 'when the line is empty' do
      it 'returns a non breaking space' do
        expect(diff_line_content(nil)).to eq(' ')
      end

      it 'returns an HTML-safe string' do
        expect(diff_line_content(nil)).to be_html_safe
      end
Marin Jankovski committed
84 85
    end

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    context 'when the line is not empty' do
      context 'when the line starts with +, -, or a space' do
        it 'strips the first character' do
          expect(diff_line_content('+new line')).to eq('new line')
          expect(diff_line_content('-new line')).to eq('new line')
          expect(diff_line_content(' new line')).to eq('new line')
        end

        context 'when the line is HTML-safe' do
          it 'returns an HTML-safe string' do
            expect(diff_line_content('+new line'.html_safe)).to be_html_safe
            expect(diff_line_content('-new line'.html_safe)).to be_html_safe
            expect(diff_line_content(' new line'.html_safe)).to be_html_safe
          end
        end

        context 'when the line is not HTML-safe' do
          it 'returns a non-HTML-safe string' do
            expect(diff_line_content('+new line')).not_to be_html_safe
            expect(diff_line_content('-new line')).not_to be_html_safe
            expect(diff_line_content(' new line')).not_to be_html_safe
          end
        end
      end

      context 'when the line does not start with a +, -, or a space' do
        it 'returns the string' do
          expect(diff_line_content('@@ -6,12 +6,18 @@ module Popen')).to eq('@@ -6,12 +6,18 @@ module Popen')
        end

        context 'when the line is HTML-safe' do
          it 'returns an HTML-safe string' do
            expect(diff_line_content('@@ -6,12 +6,18 @@ module Popen'.html_safe)).to be_html_safe
          end
        end

        context 'when the line is not HTML-safe' do
          it 'returns a non-HTML-safe string' do
            expect(diff_line_content('@@ -6,12 +6,18 @@ module Popen')).not_to be_html_safe
          end
        end
      end
128
    end
129 130 131 132 133 134 135 136
  end

  describe "#mark_inline_diffs" do
    let(:old_line) { %{abc 'def'} }
    let(:new_line) { %{abc "def"} }

    it "returns strings with marked inline diffs" do
      marked_old_line, marked_new_line = mark_inline_diffs(old_line, new_line)
137

138
      expect(marked_old_line).to eq(%q{abc <span class="idiff left right deletion">'def'</span>})
139
      expect(marked_old_line).to be_html_safe
140
      expect(marked_new_line).to eq(%q{abc <span class="idiff left right addition">"def"</span>})
141
      expect(marked_new_line).to be_html_safe
Marin Jankovski committed
142 143
    end
  end
144

145
  describe '#parallel_diff_discussions' do
146 147 148 149
    let(:discussion) { { 'abc_3_3' => 'comment' } }
    let(:diff_file) { double(line_code: 'abc_3_3') }

    before do
150
      helper.instance_variable_set(:@grouped_diff_discussions, discussion)
151 152 153
    end

    it 'does not put comments on nonewline lines' do
154 155 156 157 158 159 160 161 162 163
      left = Gitlab::Diff::Line.new('\\nonewline', 'old-nonewline', 3, 3, 3)
      right = Gitlab::Diff::Line.new('\\nonewline', 'new-nonewline', 3, 3, 3)

      result = helper.parallel_diff_discussions(left, right, diff_file)

      expect(result).to eq([nil, nil])
    end

    it 'puts comments on added lines' do
      left = Gitlab::Diff::Line.new('\\nonewline', 'old-nonewline', 3, 3, 3)
164
      right = Gitlab::Diff::Line.new('new line', 'new', 3, 3, 3)
165 166 167 168 169

      result = helper.parallel_diff_discussions(left, right, diff_file)

      expect(result).to eq([nil, 'comment'])
    end
170 171 172 173 174 175 176 177 178

    it 'puts comments on unchanged lines' do
      left = Gitlab::Diff::Line.new('unchanged line', nil, 3, 3, 3)
      right = Gitlab::Diff::Line.new('unchanged line', nil, 3, 3, 3)

      result = helper.parallel_diff_discussions(left, right, diff_file)

      expect(result).to eq(['comment', nil])
    end
179 180
  end

181 182 183 184 185
  describe "#diff_match_line" do
    let(:old_pos) { 40 }
    let(:new_pos) { 50 }
    let(:text) { 'some_text' }

186
    it "generates foldable top match line for inline view with empty text by default" do
187 188 189 190 191 192 193 194
      output = diff_match_line old_pos, new_pos

      expect(output).to be_html_safe
      expect(output).to have_css "td:nth-child(1):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.old_line[data-linenumber='#{old_pos}']", text: '...'
      expect(output).to have_css "td:nth-child(2):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.new_line[data-linenumber='#{new_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(3):not(.parallel).line_content.match', text: ''
    end

195
    it "allows to define text and bottom option" do
196 197 198 199 200 201 202 203
      output = diff_match_line old_pos, new_pos, text: text, bottom: true

      expect(output).to be_html_safe
      expect(output).to have_css "td:nth-child(1).diff-line-num.unfold.js-unfold.js-unfold-bottom.old_line[data-linenumber='#{old_pos}']", text: '...'
      expect(output).to have_css "td:nth-child(2).diff-line-num.unfold.js-unfold.js-unfold-bottom.new_line[data-linenumber='#{new_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(3):not(.parallel).line_content.match', text: text
    end

204
    it "generates match line for parallel view" do
205 206 207 208 209 210 211 212 213
      output = diff_match_line old_pos, new_pos, text: text, view: :parallel

      expect(output).to be_html_safe
      expect(output).to have_css "td:nth-child(1):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.old_line[data-linenumber='#{old_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(2).line_content.match.parallel', text: text
      expect(output).to have_css "td:nth-child(3):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.new_line[data-linenumber='#{new_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(4).line_content.match.parallel', text: text
    end

214
    it "allows to generate only left match line for parallel view" do
215 216 217 218 219 220 221 222
      output = diff_match_line old_pos, nil, text: text, view: :parallel

      expect(output).to be_html_safe
      expect(output).to have_css "td:nth-child(1):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.old_line[data-linenumber='#{old_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(2).line_content.match.parallel', text: text
      expect(output).not_to have_css 'td:nth-child(3)'
    end

223
    it "allows to generate only right match line for parallel view" do
224 225 226 227 228 229 230 231
      output = diff_match_line nil, new_pos, text: text, view: :parallel

      expect(output).to be_html_safe
      expect(output).to have_css "td:nth-child(1):not(.js-unfold-bottom).diff-line-num.unfold.js-unfold.new_line[data-linenumber='#{new_pos}']", text: '...'
      expect(output).to have_css 'td:nth-child(2).line_content.match.parallel', text: text
      expect(output).not_to have_css 'td:nth-child(3)'
    end
  end
Douwe Maan committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

  context 'viewer related' do
    let(:viewer) { diff_file.simple_viewer }

    before do
      assign(:project, project)
    end

    describe '#diff_render_error_reason' do
      context 'for error :too_large' do
        before do
          expect(viewer).to receive(:render_error).and_return(:too_large)
        end

        it 'returns an error message' do
          expect(helper.diff_render_error_reason(viewer)).to eq('it is too large')
        end
      end

      context 'for error :server_side_but_stored_externally' do
        before do
          expect(viewer).to receive(:render_error).and_return(:server_side_but_stored_externally)
          expect(diff_file).to receive(:external_storage).and_return(:lfs)
        end

        it 'returns an error message' do
          expect(helper.diff_render_error_reason(viewer)).to eq('it is stored in LFS')
        end
      end
    end

    describe '#diff_render_error_options' do
      it 'includes a "view the blob" link' do
        expect(helper.diff_render_error_options(viewer)).to include(/view the blob/)
      end
    end
  end
Marin Jankovski committed
269
end