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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Diff::Highlight do
include RepoHelpers
let_it_be(: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 addition">RuntimeError</span></span><span class="p"><span class="idiff addition">,</span></span><span class="idiff right addition"> </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 addition">RuntimeError, </span>"System commands must be given as an array of strings"}
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::ErrorTracking).to receive(:track_and_raise_for_dev_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::ErrorTracking).to receive(:track_and_raise_for_dev_exception).and_call_original
expect { subject }. to raise_exception(RangeError)
end
end
context 'when `use_marker_ranges` feature flag is disabled' do
it 'returns the same result' do
with_feature_flag = described_class.new(diff_file, repository: project.repository).highlight
stub_feature_flags(use_marker_ranges: false)
without_feature_flag = described_class.new(diff_file, repository: project.repository).highlight
expect(with_feature_flag.map(&:rich_text)).to eq(without_feature_flag.map(&:rich_text))
end
end
context 'when no inline diffs' do
it_behaves_like 'without inline diffs'
end
end
context 'when blob is too large' do
let(:subject) { described_class.new(diff_file, repository: project.repository).highlight }
before do
allow(Gitlab::Highlight).to receive(:too_large?).and_return(true)
end
it 'blobs are highlighted as plain text without loading all data' do
expect(diff_file.blob).not_to receive(:load_all_data!)
expect(subject[2].rich_text).to eq(%Q{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n})
expect(subject[2].rich_text).to be_html_safe
end
context 'when limited_diff_highlighting is disabled' do
before do
stub_feature_flags(limited_diff_highlighting: false)
stub_feature_flags(diff_line_syntax_highlighting: false)
end
it 'blobs are highlighted as plain text with loading all data' do
expect(diff_file.blob).to receive(:load_all_data!).twice
code = %Q{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n}
expect(subject[2].rich_text).to eq(code)
end
end
end
end
end
|