summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/diff/highlight_spec.rb
blob: 5d0a603d11d064a61eb92ff791d9ff0950b2c219 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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
require 'spec_helper'

describe Gitlab::Diff::Highlight do
  include RepoHelpers

  let(:project) { create(:project, :repository) }
  let(:commit) { project.commit(sample_commit.id) }
  let(:diff) { commit.raw_diffs.first }
  let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }

  shared_examples 'without inline diffs' do
    let(:code) { '<h2 onmouseover="alert(2)">Test</h2>' }

    before do
      allow(Gitlab::Diff::InlineDiff).to receive(:for_lines).and_return([])
      allow_any_instance_of(Gitlab::Diff::Line).to receive(:text).and_return(code)
    end

    it 'returns html escaped diff text' do
      expect(subject[1].rich_text).to eq html_escape(code)
      expect(subject[1].rich_text).to be_html_safe
    end
  end

  describe '#highlight' do
    context "with a diff file" do
      let(:subject) { described_class.new(diff_file, repository: project.repository).highlight }

      it 'returns Gitlab::Diff::Line elements' do
        expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line)
      end

      it 'does not modify "match" lines' do
        expect(subject[0].text).to eq('@@ -6,12 +6,18 @@ module Popen')
        expect(subject[22].text).to eq('@@ -19,6 +25,7 @@ module Popen')
      end

      it 'highlights and marks unchanged lines' do
        code = %Q{ <span id="LC7" class="line" lang="ruby">  <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n}

        expect(subject[2].rich_text).to eq(code)
      end

      it 'highlights and marks removed lines' do
        code = %Q{-<span id="LC9" class="line" lang="ruby">      <span class="k">raise</span> <span class="s2">"System commands must be given as an array of strings"</span></span>\n}

        expect(subject[4].rich_text).to eq(code)
      end

      it 'highlights and marks added lines' do
        code = %Q{+<span id="LC9" class="line" lang="ruby">      <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n}

        expect(subject[5].rich_text).to eq(code)
      end

      context 'when no diff_refs' do
        before do
          allow(diff_file).to receive(:diff_refs).and_return(nil)
        end

        context 'when no inline diffs' do
          it_behaves_like 'without inline diffs'
        end
      end
    end

    context "with diff lines" do
      let(:subject) { described_class.new(diff_file.diff_lines, repository: project.repository).highlight }

      it 'returns Gitlab::Diff::Line elements' do
        expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line)
      end

      it 'does not modify "match" lines' do
        expect(subject[0].text).to eq('@@ -6,12 +6,18 @@ module Popen')
        expect(subject[22].text).to eq('@@ -19,6 +25,7 @@ module Popen')
      end

      it 'marks unchanged lines' do
        code = %q{   def popen(cmd, path=nil)}

        expect(subject[2].text).to eq(code)
        expect(subject[2].text).not_to be_html_safe
      end

      it 'marks removed lines' do
        code = %q{-      raise "System commands must be given as an array of strings"}

        expect(subject[4].text).to eq(code)
        expect(subject[4].text).not_to be_html_safe
      end

      it 'marks added lines' do
        code = %q{+      raise <span class="idiff left right">RuntimeError, </span>&quot;System commands must be given as an array of strings&quot;}

        expect(subject[5].rich_text).to eq(code)
        expect(subject[5].rich_text).to be_html_safe
      end

      context 'when the inline diff marker has an invalid range' do
        before do
          allow_any_instance_of(Gitlab::Diff::InlineDiffMarker).to receive(:mark).and_raise(RangeError)
        end

        it 'keeps the original rich line' do
          allow(Gitlab::Sentry).to receive(:track_exception)

          code = %q{+      raise RuntimeError, "System commands must be given as an array of strings"}

          expect(subject[5].text).to eq(code)
          expect(subject[5].text).not_to be_html_safe
        end

        it 'reports to Sentry if configured' do
          expect(Gitlab::Sentry).to receive(:track_exception).and_call_original

          expect { subject }. to raise_exception(RangeError)
        end
      end

      context 'when no inline diffs' do
        it_behaves_like 'without inline diffs'
      end
    end
  end
end