blob: e618d3a73f362dadb335c2fdc0bec58156add5e7 [file] [log] [blame]
Wyatt Allen650c5292016-06-22 17:18:06 -07001<!DOCTYPE html>
2<!--
3Copyright (C) 2016 The Android Open Source Project
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16-->
17
18<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
19<title>gr-syntax-layer</title>
20
Viktar Donich29e1ce52017-03-28 17:02:44 -070021<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
Wyatt Allen650c5292016-06-22 17:18:06 -070022<script src="../../../bower_components/web-component-tester/browser.js"></script>
23
24<link rel="import" href="../../shared/gr-rest-api-interface/mock-diff-response_test.html">
25<link rel="import" href="gr-syntax-layer.html">
26
Viktar Donich29e1ce52017-03-28 17:02:44 -070027<script>void(0);</script>
28
Wyatt Allen650c5292016-06-22 17:18:06 -070029<test-fixture id="basic">
30 <template>
31 <gr-syntax-layer></gr-syntax-layer>
32 </template>
33</test-fixture>
34
35<script>
36 suite('gr-syntax-layer tests', function() {
37 var sandbox;
38 var diff;
39 var element;
40
Andrew Bonventre84ab5832016-08-03 14:48:18 -040041 function getMockHLJS() {
Wyatt Allenafbc6032016-08-11 10:26:55 -070042 var html = '<span class="gr-diff gr-syntax gr-syntax-string">' +
43 'ipsum</span>';
Andrew Bonventre84ab5832016-08-03 14:48:18 -040044 return {
45 configure: function() {},
46 highlight: function(lang, line, ignore, state) {
47 return {
Wyatt Allenafbc6032016-08-11 10:26:55 -070048 value: line.replace(/ipsum/, html),
Andrew Bonventre84ab5832016-08-03 14:48:18 -040049 top: state === undefined ? 1 : state + 1,
50 };
51 },
52 };
53 }
54
Wyatt Allen650c5292016-06-22 17:18:06 -070055 setup(function() {
56 sandbox = sinon.sandbox.create();
57 element = fixture('basic');
58 var mock = document.createElement('mock-diff-response');
59 diff = mock.diffResponse;
60 element.diff = diff;
61 });
62
63 teardown(function() {
64 sandbox.restore();
65 });
66
67 test('annotate without range does nothing', function() {
68 var annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
69 var el = document.createElement('div');
70 el.textContent = 'Etiam dui, blandit wisi.';
71 var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
72 line.beforeNumber = 12;
73
Wyatt Allen5c5f00f2016-07-25 22:46:20 -070074 element.annotate(el, line);
Wyatt Allen650c5292016-06-22 17:18:06 -070075
76 assert.isFalse(annotationSpy.called);
77 });
78
79 test('annotate with range applies it', function() {
80 var str = 'Etiam dui, blandit wisi.';
81 var start = 6;
82 var length = 3;
83 var className = 'foobar';
84
85 var annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
86 var el = document.createElement('div');
87 el.textContent = str;
88 var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
89 line.beforeNumber = 12;
90 element._baseRanges[11] = [{
91 start: start,
92 length: length,
93 className: className,
94 }];
95
Wyatt Allen5c5f00f2016-07-25 22:46:20 -070096 element.annotate(el, line);
Wyatt Allen650c5292016-06-22 17:18:06 -070097
98 assert.isTrue(annotationSpy.called);
99 assert.equal(annotationSpy.lastCall.args[0], el);
100 assert.equal(annotationSpy.lastCall.args[1], start);
101 assert.equal(annotationSpy.lastCall.args[2], length);
102 assert.equal(annotationSpy.lastCall.args[3], className);
103 assert.isOk(el.querySelector('hl.' + className));
104 });
105
Wyatt Allen7c66d992016-07-27 10:32:44 -0700106 test('annotate with range but disabled does nothing', function() {
107 var str = 'Etiam dui, blandit wisi.';
108 var start = 6;
109 var length = 3;
110 var className = 'foobar';
111
112 var annotationSpy = sandbox.spy(GrAnnotation, 'annotateElement');
113 var el = document.createElement('div');
114 el.textContent = str;
115 var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
116 line.beforeNumber = 12;
117 element._baseRanges[11] = [{
118 start: start,
119 length: length,
120 className: className,
121 }];
122 element.enabled = false;
123
124 element.annotate(el, line);
125
126 assert.isFalse(annotationSpy.called);
127 });
128
Wyatt Allen650c5292016-06-22 17:18:06 -0700129 test('process on empty diff does nothing', function(done) {
130 element.diff = {
131 meta_a: {content_type: 'application/json'},
132 meta_b: {content_type: 'application/json'},
133 content: [],
134 };
135 var processNextSpy = sandbox.spy(element, '_processNextLine');
136
137 var processPromise = element.process();
138
139 processPromise.then(function() {
140 assert.isFalse(processNextSpy.called);
141 assert.equal(element._baseRanges.length, 0);
142 assert.equal(element._revisionRanges.length, 0);
143 done();
144 });
145 });
146
Wyatt Allenc5794e42016-08-05 15:05:32 -0700147 test('process for unsupported languages does nothing', function(done) {
148 element.diff = {
149 meta_a: {content_type: 'text/x+objective-cobol-plus-plus'},
150 meta_b: {content_type: 'application/not-a-real-language'},
151 content: [],
152 };
153 var processNextSpy = sandbox.spy(element, '_processNextLine');
154
155 var processPromise = element.process();
156
157 processPromise.then(function() {
158 assert.isFalse(processNextSpy.called);
159 assert.equal(element._baseRanges.length, 0);
160 assert.equal(element._revisionRanges.length, 0);
161 done();
162 });
163 });
164
Wyatt Allen7c66d992016-07-27 10:32:44 -0700165 test('process while disabled does nothing', function(done) {
166 var processNextSpy = sandbox.spy(element, '_processNextLine');
167 element.enabled = false;
Wyatt Allendb56a6f2016-08-01 15:23:50 -0700168 var loadHLJSSpy = sandbox.spy(element, '_loadHLJS');
Wyatt Allen7c66d992016-07-27 10:32:44 -0700169
170 var processPromise = element.process();
171
172 processPromise.then(function() {
173 assert.isFalse(processNextSpy.called);
174 assert.equal(element._baseRanges.length, 0);
175 assert.equal(element._revisionRanges.length, 0);
Wyatt Allendb56a6f2016-08-01 15:23:50 -0700176 assert.isFalse(loadHLJSSpy.called);
Wyatt Allen7c66d992016-07-27 10:32:44 -0700177 done();
178 });
179 });
180
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400181 test('process highlight ipsum', function(done) {
182 element.diff.meta_a.content_type = 'application/json';
183 element.diff.meta_b.content_type = 'application/json';
Wyatt Allen650c5292016-06-22 17:18:06 -0700184
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400185 var mockHLJS = getMockHLJS();
186 var highlightSpy = sinon.spy(mockHLJS, 'highlight');
Wyatt Allene7a51872016-09-12 14:19:22 -0700187 sandbox.stub(element.$.libLoader, 'get',
188 function() { return Promise.resolve(mockHLJS); });
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400189 var processNextSpy = sandbox.spy(element, '_processNextLine');
190 var processPromise = element.process();
Wyatt Allen650c5292016-06-22 17:18:06 -0700191
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400192 processPromise.then(function() {
193 var linesA = diff.meta_a.lines;
194 var linesB = diff.meta_b.lines;
Wyatt Allen650c5292016-06-22 17:18:06 -0700195
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400196 assert.isTrue(processNextSpy.called);
197 assert.equal(element._baseRanges.length, linesA);
198 assert.equal(element._revisionRanges.length, linesB);
Wyatt Allen650c5292016-06-22 17:18:06 -0700199
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400200 assert.equal(highlightSpy.callCount, linesA + linesB);
Wyatt Allen650c5292016-06-22 17:18:06 -0700201
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400202 // The first line of both sides have a range.
203 [element._baseRanges[0], element._revisionRanges[0]]
204 .forEach(function(range) {
205 assert.equal(range.length, 1);
Wyatt Allenafbc6032016-08-11 10:26:55 -0700206 assert.equal(range[0].className,
207 'gr-diff gr-syntax gr-syntax-string');
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400208 assert.equal(range[0].start, 'lorem '.length);
209 assert.equal(range[0].length, 'ipsum'.length);
210 });
Wyatt Allen650c5292016-06-22 17:18:06 -0700211
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400212 // There are no ranges from ll.1-12 on the left and ll.1-11 on the
213 // right.
214 element._baseRanges.slice(1, 12)
215 .concat(element._revisionRanges.slice(1, 11))
216 .forEach(function(range) {
217 assert.equal(range.length, 0);
218 });
Wyatt Allen650c5292016-06-22 17:18:06 -0700219
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400220 // There should be another pair of ranges on l.13 for the left and
221 // l.12 for the right.
222 [element._baseRanges[13], element._revisionRanges[12]]
223 .forEach(function(range) {
224 assert.equal(range.length, 1);
Wyatt Allenafbc6032016-08-11 10:26:55 -0700225 assert.equal(range[0].className,
226 'gr-diff gr-syntax gr-syntax-string');
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400227 assert.equal(range[0].start, 32);
228 assert.equal(range[0].length, 'ipsum'.length);
229 });
Wyatt Allen650c5292016-06-22 17:18:06 -0700230
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400231 // The next group should have a similar instance on either side.
Wyatt Allen650c5292016-06-22 17:18:06 -0700232
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400233 var range = element._baseRanges[15];
234 assert.equal(range.length, 1);
Wyatt Allenafbc6032016-08-11 10:26:55 -0700235 assert.equal(range[0].className, 'gr-diff gr-syntax gr-syntax-string');
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400236 assert.equal(range[0].start, 34);
237 assert.equal(range[0].length, 'ipsum'.length);
Wyatt Allen650c5292016-06-22 17:18:06 -0700238
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400239 range = element._revisionRanges[14];
240 assert.equal(range.length, 1);
Wyatt Allenafbc6032016-08-11 10:26:55 -0700241 assert.equal(range[0].className, 'gr-diff gr-syntax gr-syntax-string');
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400242 assert.equal(range[0].start, 35);
243 assert.equal(range[0].length, 'ipsum'.length);
Wyatt Allen650c5292016-06-22 17:18:06 -0700244
Andrew Bonventre84ab5832016-08-03 14:48:18 -0400245 done();
Wyatt Allen650c5292016-06-22 17:18:06 -0700246 });
247 });
248
249 test('_diffChanged calls cancel', function() {
250 var cancelSpy = sandbox.spy(element, '_diffChanged');
251 element.diff = {content: []};
252 assert.isTrue(cancelSpy.called);
253 });
254
255 test('_rangesFromElement no ranges', function() {
256 var elem = document.createElement('span');
257 elem.textContent = 'Etiam dui, blandit wisi.';
258 var offset = 100;
259
260 var result = element._rangesFromElement(elem, offset);
261
262 assert.equal(result.length, 0);
263 });
264
265 test('_rangesFromElement single range', function() {
266 var str0 = 'Etiam ';
267 var str1 = 'dui, blandit';
268 var str2 = ' wisi.';
Wyatt Allenafbc6032016-08-11 10:26:55 -0700269 var className = 'gr-diff gr-syntax gr-syntax-string';
Wyatt Allen650c5292016-06-22 17:18:06 -0700270 var offset = 100;
271
272 var elem = document.createElement('span');
273 elem.appendChild(document.createTextNode(str0));
274 var span = document.createElement('span');
275 span.textContent = str1;
276 span.className = className;
277 elem.appendChild(span);
278 elem.appendChild(document.createTextNode(str2));
279
280 var result = element._rangesFromElement(elem, offset);
281
282 assert.equal(result.length, 1);
283 assert.equal(result[0].start, str0.length + offset);
284 assert.equal(result[0].length, str1.length);
285 assert.equal(result[0].className, className);
286 });
287
Wyatt Allenafbc6032016-08-11 10:26:55 -0700288 test('_rangesFromElement non-whitelist', function() {
289 var str0 = 'Etiam ';
290 var str1 = 'dui, blandit';
291 var str2 = ' wisi.';
292 var className = 'not-in-the-whitelist';
293 var offset = 100;
294
295 var elem = document.createElement('span');
296 elem.appendChild(document.createTextNode(str0));
297 var span = document.createElement('span');
298 span.textContent = str1;
299 span.className = className;
300 elem.appendChild(span);
301 elem.appendChild(document.createTextNode(str2));
302
303 var result = element._rangesFromElement(elem, offset);
304
305 assert.equal(result.length, 0);
306 });
307
Wyatt Allen650c5292016-06-22 17:18:06 -0700308 test('_rangesFromElement milti range', function() {
309 var str0 = 'Etiam ';
310 var str1 = 'dui,';
311 var str2 = ' blandit';
312 var str3 = ' wisi.';
Wyatt Allenafbc6032016-08-11 10:26:55 -0700313 var className = 'gr-diff gr-syntax gr-syntax-string';
Wyatt Allen650c5292016-06-22 17:18:06 -0700314 var offset = 100;
315
316 var elem = document.createElement('span');
317 elem.appendChild(document.createTextNode(str0));
318 var span = document.createElement('span');
319 span.textContent = str1;
320 span.className = className;
321 elem.appendChild(span);
322 elem.appendChild(document.createTextNode(str2));
323 span = document.createElement('span');
324 span.textContent = str3;
325 span.className = className;
326 elem.appendChild(span);
327
328 var result = element._rangesFromElement(elem, offset);
329
330 assert.equal(result.length, 2);
331
332 assert.equal(result[0].start, str0.length + offset);
333 assert.equal(result[0].length, str1.length);
334 assert.equal(result[0].className, className);
335
336 assert.equal(result[1].start,
337 str0.length + str1.length + str2.length + offset);
338 assert.equal(result[1].length, str3.length);
339 assert.equal(result[1].className, className);
340 });
341
342 test('_rangesFromElement nested range', function() {
343 var str0 = 'Etiam ';
344 var str1 = 'dui,';
345 var str2 = ' blandit';
346 var str3 = ' wisi.';
Wyatt Allenafbc6032016-08-11 10:26:55 -0700347 var className = 'gr-diff gr-syntax gr-syntax-string';
Wyatt Allen650c5292016-06-22 17:18:06 -0700348 var offset = 100;
349
350 var elem = document.createElement('span');
351 elem.appendChild(document.createTextNode(str0));
352 var span1 = document.createElement('span');
353 span1.textContent = str1;
354 span1.className = className;
355 elem.appendChild(span1);
356 var span2 = document.createElement('span');
357 span2.textContent = str2;
358 span2.className = className;
359 span1.appendChild(span2);
360 elem.appendChild(document.createTextNode(str3));
361
362 var result = element._rangesFromElement(elem, offset);
363
364 assert.equal(result.length, 2);
365
366 assert.equal(result[0].start, str0.length + offset);
367 assert.equal(result[0].length, str1.length + str2.length);
368 assert.equal(result[0].className, className);
369
370 assert.equal(result[1].start, str0.length + str1.length + offset);
371 assert.equal(result[1].length, str2.length);
372 assert.equal(result[1].className, className);
373 });
374
Wyatt Allen6c8fd1e2016-10-11 12:57:23 -0700375 test('_rangesFromString whitelist allows recursion', function() {
376 var str = [
377 '<span class="non-whtelisted-class">',
378 '<span class="gr-diff gr-syntax gr-syntax-keyword">public</span>',
379 '</span>'].join('');
380 var result = element._rangesFromString(str);
381 assert.notEqual(result.length, 0);
382 });
383
Wyatt Allen650c5292016-06-22 17:18:06 -0700384 test('_isSectionDone', function() {
385 var state = {sectionIndex: 0, lineIndex: 0};
386 assert.isFalse(element._isSectionDone(state));
387
388 state = {sectionIndex: 0, lineIndex: 2};
389 assert.isFalse(element._isSectionDone(state));
390
391 state = {sectionIndex: 0, lineIndex: 4};
392 assert.isTrue(element._isSectionDone(state));
393
394 state = {sectionIndex: 1, lineIndex: 2};
395 assert.isFalse(element._isSectionDone(state));
396
397 state = {sectionIndex: 1, lineIndex: 3};
398 assert.isTrue(element._isSectionDone(state));
399
400 state = {sectionIndex: 3, lineIndex: 0};
401 assert.isFalse(element._isSectionDone(state));
402
403 state = {sectionIndex: 3, lineIndex: 3};
404 assert.isFalse(element._isSectionDone(state));
405
406 state = {sectionIndex: 3, lineIndex: 4};
407 assert.isTrue(element._isSectionDone(state));
408 });
Wyatt Allen696a8472016-11-28 10:31:22 -0800409
410 test('workaround CPP LT directive', function() {
411 // Does nothing to regular line.
412 var line = 'int main(int argc, char** argv) { return 0; }';
413 assert.equal(element._workaround('cpp', line), line);
414
415 // Does nothing to include directive.
416 line = '#include <stdio>';
417 assert.equal(element._workaround('cpp', line), line);
418
419 // Converts left-shift operator in #define.
420 line = '#define GiB (1ull << 30)';
421 var expected = '#define GiB (1ull || 30)';
422 assert.equal(element._workaround('cpp', line), expected);
423
424 // Converts less-than operator in #if.
425 line = ' #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)';
426 expected = ' #if __GNUC__ | 4 || (__GNUC__ == 4 && __GNUC_MINOR__ | 1)';
427 assert.equal(element._workaround('cpp', line), expected);
428 });
429
430 test('workaround Java param-annotation', function() {
431 // Does nothing to regular line.
432 var line = 'public static void foo(int bar) { }';
433 assert.equal(element._workaround('java', line), line);
434
435 // Does nothing to regular annotation.
Wyatt Allen4704d2d2017-01-10 17:05:23 -0800436 line = 'public static void foo(@Nullable int bar) { }';
Wyatt Allen696a8472016-11-28 10:31:22 -0800437 assert.equal(element._workaround('java', line), line);
438
439 // Converts parameterized annotation.
440 line = 'public static void foo(@SuppressWarnings("unused") int bar) { }';
441 var expected = 'public static void foo(@SuppressWarnings "unused" ' +
442 ' int bar) { }';
443 assert.equal(element._workaround('java', line), expected);
444 });
Wyatt Allen4704d2d2017-01-10 17:05:23 -0800445
446 test('workaround CPP whcar_t character literals', function() {
447 // Does nothing to regular line.
448 var line = 'int main(int argc, char** argv) { return 0; }';
449 assert.equal(element._workaround('cpp', line), line);
450
451 // Does nothing to wchar_t string.
452 line = 'wchar_t* sz = L"abc 123";';
453 assert.equal(element._workaround('cpp', line), line);
454
455 // Converts wchar_t character literal to string.
456 line = 'wchar_t myChar = L\'#\'';
457 var expected = 'wchar_t myChar = L"."';
458 assert.equal(element._workaround('cpp', line), expected);
Wyatt Allen8bbb4bb2017-04-04 10:55:23 -0700459
460 // Converts wchar_t character literal with escape sequence to string.
461 line = 'wchar_t myChar = L\'\\"\'';
462 expected = 'wchar_t myChar = L"\\."';
463 assert.equal(element._workaround('cpp', line), expected);
Wyatt Allen4704d2d2017-01-10 17:05:23 -0800464 });
465
466 test('workaround go backslash character literals', function() {
467 // Does nothing to regular line.
468 var line = 'func foo(in []byte) (lit []byte, n int, err error) {';
469 assert.equal(element._workaround('go', line), line);
470
471 // Does nothing to string with backslash literal
472 line = 'c := "\\\\"';
473 assert.equal(element._workaround('go', line), line);
474
475 // Converts backslash literal character to a string.
476 line = 'c := \'\\\\\'';
477 var expected = 'c := "\\\\"';
478 assert.equal(element._workaround('go', line), expected);
479 });
Wyatt Allen650c5292016-06-22 17:18:06 -0700480 });
481</script>