blob: f87ef7af222b9dc0034b5b5f198fe6ca4cdbd5a3 [file] [log] [blame]
Ole Rehmsene5de55e2018-08-23 16:52:57 +02001<!DOCTYPE html>
2<!--
3@license
4Copyright (C) 2018 The Android Open Source Project
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17-->
18
19<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
20<title>gr-diff</title>
Ole Rehmsen62909352019-05-16 16:10:33 +020021<script src="/test/common-test-setup.js"></script>
22<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
Ole Rehmsene5de55e2018-08-23 16:52:57 +020023
Ole Rehmsenecf0b782019-05-16 11:29:39 +020024<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
Ole Rehmsen31640742019-05-16 11:24:47 +020025<script src="/bower_components/web-component-tester/browser.js"></script>
Ole Rehmsene5de55e2018-08-23 16:52:57 +020026<link rel="import" href="../../../test/common-test-setup.html"/>
27
28<link rel="import" href="gr-diff-host.html">
29
30<script>void(0);</script>
31
32<test-fixture id="basic">
33 <template>
34 <gr-diff-host></gr-diff-host>
35 </template>
36</test-fixture>
37
38<script>
39 suite('gr-diff-host tests', () => {
40 let element;
41 let sandbox;
Ole Rehmsen49ba2872018-10-29 15:48:23 +010042 let getLoggedIn;
Ole Rehmsene5de55e2018-08-23 16:52:57 +020043
44 setup(() => {
45 sandbox = sinon.sandbox.create();
Ole Rehmsen49ba2872018-10-29 15:48:23 +010046 getLoggedIn = false;
47 stub('gr-rest-api-interface', {
48 async getLoggedIn() { return getLoggedIn; },
49 });
Ole Rehmsen578f9212019-04-11 23:58:56 +020050 stub('gr-reporting', {
51 time: sandbox.stub(),
52 timeEnd: sandbox.stub(),
53 });
Ole Rehmsenb1a79672018-08-27 22:43:38 +020054 element = fixture('basic');
Ole Rehmsene5de55e2018-08-23 16:52:57 +020055 });
56
57 teardown(() => {
58 sandbox.restore();
59 });
60
Dhruv Srivastava7ebdb772019-09-19 15:46:29 +020061
62 suite('plugin layers', () => {
63 const pluginLayers = [{}, {}];
64 setup(() => {
65 stub('gr-js-api-interface', {
66 getDiffLayers() { return pluginLayers; },
67 });
68 element = fixture('basic');
69 });
70 test('plugin layers requested', () => {
71 element.patchRange = {};
72 element.reload();
73 assert(element.$.jsAPI.getDiffLayers.called);
74 });
75 });
76
Ole Rehmsen53876362018-11-15 21:21:31 +010077 suite('handle comment-update', () => {
78 setup(() => {
79 sandbox.stub(element, '_commentsChanged');
80 element.comments = {
81 meta: {
82 changeNum: '42',
83 patchRange: {
84 basePatchNum: 'PARENT',
85 patchNum: 3,
86 },
87 path: '/path/to/foo',
88 projectConfig: {foo: 'bar'},
89 },
90 left: [
91 {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
92 {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
93 {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
94 {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
95 ],
96 right: [
97 {id: 'c1', __commentSide: 'right'},
98 {id: 'c2', __commentSide: 'right'},
99 {id: 'd1', __draft: true, __commentSide: 'right'},
100 {id: 'd2', __draft: true, __commentSide: 'right'},
101 ],
102 };
103 });
104
105 test('creating a draft', () => {
106 const comment = {__draft: true, __draftID: 'tempID', side: 'PARENT',
107 __commentSide: 'left'};
108 element.fire('comment-update', {comment});
109 assert.include(element.comments.left, comment);
110 });
111
112 test('discarding a draft', () => {
113 const draftID = 'tempID';
114 const id = 'savedID';
115 const comment = {
116 __draft: true,
117 __draftID: draftID,
118 side: 'PARENT',
119 __commentSide: 'left',
120 };
121 const diffCommentsModifiedStub = sandbox.stub();
122 element.addEventListener('diff-comments-modified',
123 diffCommentsModifiedStub);
124 element.comments.left.push(comment);
125 comment.id = id;
126 element.fire('comment-discard', {comment});
127 const drafts = element.comments.left.filter(item => {
128 return item.__draftID === draftID;
129 });
130 assert.equal(drafts.length, 0);
131 assert.isTrue(diffCommentsModifiedStub.called);
132 });
133
134 test('saving a draft', () => {
135 const draftID = 'tempID';
136 const id = 'savedID';
137 const comment = {
138 __draft: true,
139 __draftID: draftID,
140 side: 'PARENT',
141 __commentSide: 'left',
142 };
143 const diffCommentsModifiedStub = sandbox.stub();
144 element.addEventListener('diff-comments-modified',
145 diffCommentsModifiedStub);
146 element.comments.left.push(comment);
147 comment.id = id;
148 element.fire('comment-save', {comment});
149 const drafts = element.comments.left.filter(item => {
150 return item.__draftID === draftID;
151 });
152 assert.equal(drafts.length, 1);
153 assert.equal(drafts[0].id, id);
154 assert.isTrue(diffCommentsModifiedStub.called);
155 });
156 });
157
158 test('remove comment', () => {
159 sandbox.stub(element, '_commentsChanged');
160 element.comments = {
161 meta: {
162 changeNum: '42',
163 patchRange: {
164 basePatchNum: 'PARENT',
165 patchNum: 3,
166 },
167 path: '/path/to/foo',
168 projectConfig: {foo: 'bar'},
169 },
170 left: [
171 {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
172 {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
173 {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
174 {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
175 ],
176 right: [
177 {id: 'c1', __commentSide: 'right'},
178 {id: 'c2', __commentSide: 'right'},
179 {id: 'd1', __draft: true, __commentSide: 'right'},
180 {id: 'd2', __draft: true, __commentSide: 'right'},
181 ],
182 };
183
184 element._removeComment({});
185 // Using JSON.stringify because Safari 9.1 (11601.5.17.1) doesn’t seem
186 // to believe that one object deepEquals another even when they do :-/.
187 assert.equal(JSON.stringify(element.comments), JSON.stringify({
188 meta: {
189 changeNum: '42',
190 patchRange: {
191 basePatchNum: 'PARENT',
192 patchNum: 3,
193 },
194 path: '/path/to/foo',
195 projectConfig: {foo: 'bar'},
196 },
197 left: [
198 {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
199 {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
200 {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
201 {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
202 ],
203 right: [
204 {id: 'c1', __commentSide: 'right'},
205 {id: 'c2', __commentSide: 'right'},
206 {id: 'd1', __draft: true, __commentSide: 'right'},
207 {id: 'd2', __draft: true, __commentSide: 'right'},
208 ],
209 }));
210
211 element._removeComment({id: 'bc2', side: 'PARENT',
212 __commentSide: 'left'});
213 assert.deepEqual(element.comments, {
214 meta: {
215 changeNum: '42',
216 patchRange: {
217 basePatchNum: 'PARENT',
218 patchNum: 3,
219 },
220 path: '/path/to/foo',
221 projectConfig: {foo: 'bar'},
222 },
223 left: [
224 {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
225 {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
226 {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
227 ],
228 right: [
229 {id: 'c1', __commentSide: 'right'},
230 {id: 'c2', __commentSide: 'right'},
231 {id: 'd1', __draft: true, __commentSide: 'right'},
232 {id: 'd2', __draft: true, __commentSide: 'right'},
233 ],
234 });
235
236 element._removeComment({id: 'd2', __commentSide: 'right'});
237 assert.deepEqual(element.comments, {
238 meta: {
239 changeNum: '42',
240 patchRange: {
241 basePatchNum: 'PARENT',
242 patchNum: 3,
243 },
244 path: '/path/to/foo',
245 projectConfig: {foo: 'bar'},
246 },
247 left: [
248 {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
249 {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
250 {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
251 ],
252 right: [
253 {id: 'c1', __commentSide: 'right'},
254 {id: 'c2', __commentSide: 'right'},
255 {id: 'd1', __draft: true, __commentSide: 'right'},
256 ],
257 });
258 });
259
Ole Rehmsenc4d62572018-11-08 09:07:35 +0100260 test('thread-discard handling', () => {
261 const threads = [
262 {comments: [{id: 4711}]},
263 {comments: [{id: 42}]},
264 ];
265 element._parentIndex = 1;
266 element.changeNum = '2';
267 element.path = 'some/path';
268 element.projectName = 'Some project';
269 const threadEls = threads.map(
Dmitrii Filippov9bdc5812019-09-25 15:00:27 +0200270 thread => {
271 const threadEl = element._createThreadElement(thread);
272 // Polymer 2 doesn't fire ready events and doesn't execute
273 // observers if element is not added to the Dom.
274 // See https://github.com/Polymer/old-docs-site/issues/2322
275 // and https://github.com/Polymer/polymer/issues/4526
276 element._attachThreadElement(threadEl);
277 return threadEl;
278 });
Ole Rehmsenc4d62572018-11-08 09:07:35 +0100279 assert.equal(threadEls.length, 2);
280 assert.equal(threadEls[0].rootId, 4711);
281 assert.equal(threadEls[1].rootId, 42);
282 for (const threadEl of threadEls) {
283 Polymer.dom(element).appendChild(threadEl);
284 }
285
286 threadEls[0].dispatchEvent(
287 new CustomEvent('thread-discard', {detail: {rootId: 4711}}));
288 const attachedThreads = element.queryAllEffectiveChildren(
Ole Rehmsen9b946162018-11-19 21:45:41 +0100289 'gr-comment-thread');
Ole Rehmsenc4d62572018-11-08 09:07:35 +0100290 assert.equal(attachedThreads.length, 1);
291 assert.equal(attachedThreads[0].rootId, 42);
292 });
293
Ole Rehmsen578f9212019-04-11 23:58:56 +0200294 suite('render reporting', () => {
295 test('starts total and content timer on render-start', done => {
296 element.dispatchEvent(
Ole Rehmsenc82baba2019-05-16 14:43:01 +0200297 new CustomEvent('render-start', {bubbles: true, composed: true}));
Ole Rehmsen578f9212019-04-11 23:58:56 +0200298 assert.isTrue(element.$.reporting.time.calledWithExactly(
299 'Diff Total Render'));
300 assert.isTrue(element.$.reporting.time.calledWithExactly(
301 'Diff Content Render'));
302 done();
303 });
304
305 test('ends content and starts syntax timer on render-content', done => {
306 element.dispatchEvent(
Ole Rehmsenc82baba2019-05-16 14:43:01 +0200307 new CustomEvent('render-content', {bubbles: true, composed: true}));
Ole Rehmsen578f9212019-04-11 23:58:56 +0200308 assert.isTrue(element.$.reporting.time.calledWithExactly(
309 'Diff Syntax Render'));
310 assert.isTrue(element.$.reporting.timeEnd.calledWithExactly(
311 'Diff Content Render'));
312 done();
313 });
314
315 test('ends total and syntax timer on render-syntax', done => {
316 element.dispatchEvent(
Ole Rehmsenc82baba2019-05-16 14:43:01 +0200317 new CustomEvent('render-syntax', {bubbles: true, composed: true}));
Ole Rehmsen578f9212019-04-11 23:58:56 +0200318 assert.isTrue(element.$.reporting.timeEnd.calledWithExactly(
319 'Diff Total Render'));
320 assert.isTrue(element.$.reporting.timeEnd.calledWithExactly(
321 'Diff Syntax Render'));
322 done();
323 });
324 });
325
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200326 test('reload() cancels before network resolves', () => {
327 const cancelStub = sandbox.stub(element.$.diff, 'cancel');
328
329 // Stub the network calls into requests that never resolve.
330 sandbox.stub(element, '_getDiff', () => new Promise(() => {}));
Tao Zhoufd9ffb52019-09-20 13:05:46 +0200331 element.patchRange = {};
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200332
333 element.reload();
334 assert.isTrue(cancelStub.called);
335 });
336
337 suite('not logged in', () => {
338 setup(() => {
Ole Rehmsen49ba2872018-10-29 15:48:23 +0100339 getLoggedIn = false;
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200340 element = fixture('basic');
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200341 });
342
343 test('reload() loads files weblinks', () => {
344 const weblinksStub = sandbox.stub(Gerrit.Nav, '_generateWeblinks')
345 .returns({name: 'stubb', url: '#s'});
346 sandbox.stub(element.$.restAPI, 'getDiff').returns(Promise.resolve({
347 content: [],
348 }));
349 element.projectName = 'test-project';
350 element.path = 'test-path';
351 element.commitRange = {baseCommit: 'test-base', commit: 'test-commit'};
352 element.patchRange = {};
353 return element.reload().then(() => {
354 assert.isTrue(weblinksStub.calledTwice);
355 assert.isTrue(weblinksStub.firstCall.calledWith({
356 commit: 'test-base',
357 file: 'test-path',
358 options: {
359 weblinks: undefined,
360 },
361 repo: 'test-project',
362 type: Gerrit.Nav.WeblinkType.FILE}));
363 assert.isTrue(weblinksStub.secondCall.calledWith({
364 commit: 'test-commit',
365 file: 'test-path',
366 options: {
367 weblinks: undefined,
368 },
369 repo: 'test-project',
370 type: Gerrit.Nav.WeblinkType.FILE}));
371 assert.deepEqual(element.filesWeblinks, {
372 meta_a: [{name: 'stubb', url: '#s'}],
373 meta_b: [{name: 'stubb', url: '#s'}],
374 });
375 });
376 });
377
378 test('_getDiff handles null diff responses', done => {
379 stub('gr-rest-api-interface', {
380 getDiff() { return Promise.resolve(null); },
381 });
382 element.changeNum = 123;
383 element.patchRange = {basePatchNum: 1, patchNum: 2};
384 element.path = 'file.txt';
385 element._getDiff().then(done);
386 });
387
388 test('reload resolves on error', () => {
389 const onErrStub = sandbox.stub(element, '_handleGetDiffError');
390 const error = {ok: false, status: 500};
391 sandbox.stub(element.$.restAPI, 'getDiff',
392 (changeNum, basePatchNum, patchNum, path, onErr) => {
393 onErr(error);
394 });
Tao Zhoufd9ffb52019-09-20 13:05:46 +0200395 element.patchRange = {};
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200396 return element.reload().then(() => {
397 assert.isTrue(onErrStub.calledOnce);
398 });
399 });
400
401 suite('_handleGetDiffError', () => {
402 let serverErrorStub;
403 let pageErrorStub;
404
405 setup(() => {
406 serverErrorStub = sinon.stub();
407 element.addEventListener('server-error', serverErrorStub);
408 pageErrorStub = sinon.stub();
409 element.addEventListener('page-error', pageErrorStub);
410 });
411
412 test('page error on HTTP-409', () => {
413 element._handleGetDiffError({status: 409});
414 assert.isTrue(serverErrorStub.calledOnce);
415 assert.isFalse(pageErrorStub.called);
416 assert.isNotOk(element._errorMessage);
417 });
418
419 test('server error on non-HTTP-409', () => {
420 element._handleGetDiffError({status: 500});
421 assert.isFalse(serverErrorStub.called);
422 assert.isTrue(pageErrorStub.calledOnce);
423 assert.isNotOk(element._errorMessage);
424 });
425
426 test('error message if showLoadFailure', () => {
427 element.showLoadFailure = true;
428 element._handleGetDiffError({status: 500, statusText: 'Failure!'});
429 assert.isFalse(serverErrorStub.called);
430 assert.isFalse(pageErrorStub.called);
431 assert.equal(element._errorMessage,
432 'Encountered error when loading the diff: 500 Failure!');
433 });
434 });
435
436 suite('image diffs', () => {
437 let mockFile1;
438 let mockFile2;
439 setup(() => {
440 mockFile1 = {
441 body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
442 'wsAAAAAAAAAAAAAAAAA/w==',
443 type: 'image/bmp',
444 };
445 mockFile2 = {
446 body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
447 'wsAAAAAAAAAAAAA/////w==',
448 type: 'image/bmp',
449 };
450 sandbox.stub(element.$.restAPI,
451 'getB64FileContents',
452 (changeId, patchNum, path, opt_parentIndex) => {
453 return Promise.resolve(opt_parentIndex === 1 ? mockFile1 :
454 mockFile2);
455 });
456
457 element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200458 element.comments = {
459 left: [],
460 right: [],
461 meta: {patchRange: element.patchRange},
462 };
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200463 });
464
465 test('renders image diffs with same file name', done => {
466 const mockDiff = {
467 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
468 meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
469 lines: 560},
470 intraline_status: 'OK',
471 change_type: 'MODIFIED',
472 diff_header: [
473 'diff --git a/carrot.jpg b/carrot.jpg',
474 'index 2adc47d..f9c2f2c 100644',
475 '--- a/carrot.jpg',
476 '+++ b/carrot.jpg',
477 'Binary files differ',
478 ],
479 content: [{skip: 66}],
480 binary: true,
481 };
482 sandbox.stub(element.$.restAPI, 'getDiff')
483 .returns(Promise.resolve(mockDiff));
484
485 const rendered = () => {
486 // Recognizes that it should be an image diff.
487 assert.isTrue(element.isImageDiff);
488 assert.instanceOf(
489 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
490
491 // Left image rendered with the parent commit's version of the file.
492 const leftImage =
493 element.$.diff.$.diffTable.querySelector('td.left img');
494 const leftLabel =
495 element.$.diff.$.diffTable.querySelector('td.left label');
496 const leftLabelContent = leftLabel.querySelector('.label');
497 const leftLabelName = leftLabel.querySelector('.name');
498
499 const rightImage =
500 element.$.diff.$.diffTable.querySelector('td.right img');
501 const rightLabel = element.$.diff.$.diffTable.querySelector(
502 'td.right label');
503 const rightLabelContent = rightLabel.querySelector('.label');
504 const rightLabelName = rightLabel.querySelector('.name');
505
506 assert.isNotOk(rightLabelName);
507 assert.isNotOk(leftLabelName);
508
509 let leftLoaded = false;
510 let rightLoaded = false;
511
512 leftImage.addEventListener('load', () => {
513 assert.isOk(leftImage);
514 assert.equal(leftImage.getAttribute('src'),
515 'data:image/bmp;base64, ' + mockFile1.body);
516 assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
517 leftLoaded = true;
518 if (rightLoaded) {
519 element.removeEventListener('render', rendered);
520 done();
521 }
522 });
523
524 rightImage.addEventListener('load', () => {
525 assert.isOk(rightImage);
526 assert.equal(rightImage.getAttribute('src'),
527 'data:image/bmp;base64, ' + mockFile2.body);
528 assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
529
530 rightLoaded = true;
531 if (leftLoaded) {
532 element.removeEventListener('render', rendered);
533 done();
534 }
535 });
536 };
537
538 element.addEventListener('render', rendered);
539
540 element.$.restAPI.getDiffPreferences().then(prefs => {
541 element.prefs = prefs;
542 element.reload();
543 });
544 });
545
546 test('renders image diffs with a different file name', done => {
547 const mockDiff = {
548 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
549 meta_b: {name: 'carrot2.jpg', content_type: 'image/jpeg',
550 lines: 560},
551 intraline_status: 'OK',
552 change_type: 'MODIFIED',
553 diff_header: [
554 'diff --git a/carrot.jpg b/carrot2.jpg',
555 'index 2adc47d..f9c2f2c 100644',
556 '--- a/carrot.jpg',
557 '+++ b/carrot2.jpg',
558 'Binary files differ',
559 ],
560 content: [{skip: 66}],
561 binary: true,
562 };
563 sandbox.stub(element.$.restAPI, 'getDiff')
564 .returns(Promise.resolve(mockDiff));
565
566 const rendered = () => {
567 // Recognizes that it should be an image diff.
568 assert.isTrue(element.isImageDiff);
569 assert.instanceOf(
570 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
571
572 // Left image rendered with the parent commit's version of the file.
573 const leftImage =
574 element.$.diff.$.diffTable.querySelector('td.left img');
575 const leftLabel =
576 element.$.diff.$.diffTable.querySelector('td.left label');
577 const leftLabelContent = leftLabel.querySelector('.label');
578 const leftLabelName = leftLabel.querySelector('.name');
579
580 const rightImage =
581 element.$.diff.$.diffTable.querySelector('td.right img');
582 const rightLabel = element.$.diff.$.diffTable.querySelector(
583 'td.right label');
584 const rightLabelContent = rightLabel.querySelector('.label');
585 const rightLabelName = rightLabel.querySelector('.name');
586
587 assert.isOk(rightLabelName);
588 assert.isOk(leftLabelName);
589 assert.equal(leftLabelName.textContent, mockDiff.meta_a.name);
590 assert.equal(rightLabelName.textContent, mockDiff.meta_b.name);
591
592 let leftLoaded = false;
593 let rightLoaded = false;
594
595 leftImage.addEventListener('load', () => {
596 assert.isOk(leftImage);
597 assert.equal(leftImage.getAttribute('src'),
598 'data:image/bmp;base64, ' + mockFile1.body);
599 assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
600 leftLoaded = true;
601 if (rightLoaded) {
602 element.removeEventListener('render', rendered);
603 done();
604 }
605 });
606
607 rightImage.addEventListener('load', () => {
608 assert.isOk(rightImage);
609 assert.equal(rightImage.getAttribute('src'),
610 'data:image/bmp;base64, ' + mockFile2.body);
611 assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
612
613 rightLoaded = true;
614 if (leftLoaded) {
615 element.removeEventListener('render', rendered);
616 done();
617 }
618 });
619 };
620
621 element.addEventListener('render', rendered);
622
623 element.$.restAPI.getDiffPreferences().then(prefs => {
624 element.prefs = prefs;
625 element.reload();
626 });
627 });
628
629 test('renders added image', done => {
630 const mockDiff = {
631 meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
632 lines: 560},
633 intraline_status: 'OK',
634 change_type: 'ADDED',
635 diff_header: [
636 'diff --git a/carrot.jpg b/carrot.jpg',
637 'index 0000000..f9c2f2c 100644',
638 '--- /dev/null',
639 '+++ b/carrot.jpg',
640 'Binary files differ',
641 ],
642 content: [{skip: 66}],
643 binary: true,
644 };
645 sandbox.stub(element.$.restAPI, 'getDiff')
646 .returns(Promise.resolve(mockDiff));
647
648 element.addEventListener('render', () => {
649 // Recognizes that it should be an image diff.
650 assert.isTrue(element.isImageDiff);
651 assert.instanceOf(
652 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
653
654 const leftImage =
655 element.$.diff.$.diffTable.querySelector('td.left img');
656 const rightImage =
657 element.$.diff.$.diffTable.querySelector('td.right img');
658
659 assert.isNotOk(leftImage);
660 assert.isOk(rightImage);
661 done();
662 });
663
664 element.$.restAPI.getDiffPreferences().then(prefs => {
665 element.prefs = prefs;
666 element.reload();
667 });
668 });
669
670 test('renders removed image', done => {
671 const mockDiff = {
672 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg',
673 lines: 560},
674 intraline_status: 'OK',
675 change_type: 'DELETED',
676 diff_header: [
677 'diff --git a/carrot.jpg b/carrot.jpg',
678 'index f9c2f2c..0000000 100644',
679 '--- a/carrot.jpg',
680 '+++ /dev/null',
681 'Binary files differ',
682 ],
683 content: [{skip: 66}],
684 binary: true,
685 };
686 sandbox.stub(element.$.restAPI, 'getDiff')
687 .returns(Promise.resolve(mockDiff));
688
689 element.addEventListener('render', () => {
690 // Recognizes that it should be an image diff.
691 assert.isTrue(element.isImageDiff);
692 assert.instanceOf(
693 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
694
695 const leftImage =
696 element.$.diff.$.diffTable.querySelector('td.left img');
697 const rightImage =
698 element.$.diff.$.diffTable.querySelector('td.right img');
699
700 assert.isOk(leftImage);
701 assert.isNotOk(rightImage);
702 done();
703 });
704
705 element.$.restAPI.getDiffPreferences().then(prefs => {
706 element.prefs = prefs;
707 element.reload();
708 });
709 });
710
711 test('does not render disallowed image type', done => {
712 const mockDiff = {
713 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg-evil',
714 lines: 560},
715 intraline_status: 'OK',
716 change_type: 'DELETED',
717 diff_header: [
718 'diff --git a/carrot.jpg b/carrot.jpg',
719 'index f9c2f2c..0000000 100644',
720 '--- a/carrot.jpg',
721 '+++ /dev/null',
722 'Binary files differ',
723 ],
724 content: [{skip: 66}],
725 binary: true,
726 };
727 mockFile1.type = 'image/jpeg-evil';
728
729 sandbox.stub(element.$.restAPI, 'getDiff')
730 .returns(Promise.resolve(mockDiff));
731
732 element.addEventListener('render', () => {
733 // Recognizes that it should be an image diff.
734 assert.isTrue(element.isImageDiff);
735 assert.instanceOf(
736 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
737 const leftImage =
738 element.$.diff.$.diffTable.querySelector('td.left img');
739 assert.isNotOk(leftImage);
740 done();
741 });
742
743 element.$.restAPI.getDiffPreferences().then(prefs => {
744 element.prefs = prefs;
745 element.reload();
746 });
747 });
748 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200749 });
750
751 test('delegates cancel()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200752 const stub = sandbox.stub(element.$.diff, 'cancel');
Tao Zhoufd9ffb52019-09-20 13:05:46 +0200753 element.patchRange = {};
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200754 element.reload();
755 assert.isTrue(stub.calledOnce);
756 assert.equal(stub.lastCall.args.length, 0);
757 });
758
759 test('delegates getCursorStops()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200760 const returnValue = [document.createElement('b')];
761 const stub = sandbox.stub(element.$.diff, 'getCursorStops')
762 .returns(returnValue);
763 assert.equal(element.getCursorStops(), returnValue);
764 assert.isTrue(stub.calledOnce);
765 assert.equal(stub.lastCall.args.length, 0);
766 });
767
768 test('delegates isRangeSelected()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200769 const returnValue = true;
770 const stub = sandbox.stub(element.$.diff, 'isRangeSelected')
771 .returns(returnValue);
772 assert.equal(element.isRangeSelected(), returnValue);
773 assert.isTrue(stub.calledOnce);
774 assert.equal(stub.lastCall.args.length, 0);
775 });
776
777 test('delegates toggleLeftDiff()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200778 const stub = sandbox.stub(element.$.diff, 'toggleLeftDiff');
779 element.toggleLeftDiff();
780 assert.isTrue(stub.calledOnce);
781 assert.equal(stub.lastCall.args.length, 0);
782 });
783
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200784 suite('blame', () => {
785 setup(() => {
786 element = fixture('basic');
787 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200788
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200789 test('clearBlame', () => {
790 element._blame = [];
791 const setBlameSpy = sandbox.spy(element.$.diff.$.diffBuilder, 'setBlame');
792 element.clearBlame();
793 assert.isNull(element._blame);
794 assert.isTrue(setBlameSpy.calledWithExactly(null));
795 assert.equal(element.isBlameLoaded, false);
796 });
797
798 test('loadBlame', () => {
799 const mockBlame = [{id: 'commit id', ranges: [{start: 1, end: 2}]}];
800 const showAlertStub = sinon.stub();
801 element.addEventListener('show-alert', showAlertStub);
802 const getBlameStub = sandbox.stub(element.$.restAPI, 'getBlame')
803 .returns(Promise.resolve(mockBlame));
804 element.changeNum = 42;
805 element.patchRange = {patchNum: 5, basePatchNum: 4};
806 element.path = 'foo/bar.baz';
807 return element.loadBlame().then(() => {
808 assert.isTrue(getBlameStub.calledWithExactly(
809 42, 5, 'foo/bar.baz', true));
810 assert.isFalse(showAlertStub.called);
811 assert.equal(element._blame, mockBlame);
812 assert.equal(element.isBlameLoaded, true);
813 });
814 });
815
816 test('loadBlame empty', () => {
817 const mockBlame = [];
818 const showAlertStub = sinon.stub();
819 element.addEventListener('show-alert', showAlertStub);
820 sandbox.stub(element.$.restAPI, 'getBlame')
821 .returns(Promise.resolve(mockBlame));
822 element.changeNum = 42;
823 element.patchRange = {patchNum: 5, basePatchNum: 4};
824 element.path = 'foo/bar.baz';
825 return element.loadBlame()
826 .then(() => {
827 assert.isTrue(false, 'Promise should not resolve');
828 })
829 .catch(() => {
830 assert.isTrue(showAlertStub.calledOnce);
831 assert.isNull(element._blame);
832 assert.equal(element.isBlameLoaded, false);
833 });
834 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200835 });
836
Ole Rehmsena970d4e2018-11-09 11:33:16 +0100837 test('getThreadEls() returns .comment-threads', () => {
838 const threadEl = document.createElement('div');
839 threadEl.className = 'comment-thread';
840 Polymer.dom(element.$.diff).appendChild(threadEl);
841 assert.deepEqual(element.getThreadEls(), [threadEl]);
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200842 });
843
844 test('delegates addDraftAtLine(el)', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200845 const param0 = document.createElement('b');
846 const stub = sandbox.stub(element.$.diff, 'addDraftAtLine');
847 element.addDraftAtLine(param0);
848 assert.isTrue(stub.calledOnce);
849 assert.equal(stub.lastCall.args.length, 1);
850 assert.equal(stub.lastCall.args[0], param0);
851 });
852
853 test('delegates clearDiffContent()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200854 const stub = sandbox.stub(element.$.diff, 'clearDiffContent');
855 element.clearDiffContent();
856 assert.isTrue(stub.calledOnce);
857 assert.equal(stub.lastCall.args.length, 0);
858 });
859
860 test('delegates expandAllContext()', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200861 const stub = sandbox.stub(element.$.diff, 'expandAllContext');
862 element.expandAllContext();
863 assert.isTrue(stub.calledOnce);
864 assert.equal(stub.lastCall.args.length, 0);
865 });
866
867 test('passes in changeNum', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200868 const value = '12345';
869 element.changeNum = value;
870 assert.equal(element.$.diff.changeNum, value);
871 });
872
873 test('passes in noAutoRender', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200874 const value = true;
875 element.noAutoRender = value;
876 assert.equal(element.$.diff.noAutoRender, value);
877 });
878
879 test('passes in patchRange', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200880 const value = {patchNum: 'foo', basePatchNum: 'bar'};
881 element.patchRange = value;
882 assert.equal(element.$.diff.patchRange, value);
883 });
884
885 test('passes in path', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200886 const value = 'some/file/path';
887 element.path = value;
888 assert.equal(element.$.diff.path, value);
889 });
890
891 test('passes in prefs', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200892 const value = {};
893 element.prefs = value;
894 assert.equal(element.$.diff.prefs, value);
895 });
896
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200897 test('passes in changeNum', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200898 const value = '12345';
899 element.changeNum = value;
900 assert.equal(element.$.diff.changeNum, value);
901 });
902
903 test('passes in projectName', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200904 const value = 'Gerrit';
905 element.projectName = value;
906 assert.equal(element.$.diff.projectName, value);
907 });
908
909 test('passes in displayLine', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200910 const value = true;
911 element.displayLine = value;
912 assert.equal(element.$.diff.displayLine, value);
913 });
914
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200915 test('passes in commitRange', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200916 const value = {};
917 element.commitRange = value;
918 assert.equal(element.$.diff.commitRange, value);
919 });
920
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200921 test('passes in hidden', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200922 const value = true;
923 element.hidden = value;
924 assert.equal(element.$.diff.hidden, value);
925 assert.isNotNull(element.getAttribute('hidden'));
926 });
927
928 test('passes in noRenderOnPrefsChange', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200929 const value = true;
930 element.noRenderOnPrefsChange = value;
931 assert.equal(element.$.diff.noRenderOnPrefsChange, value);
932 });
933
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200934 test('passes in lineWrapping', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200935 const value = true;
936 element.lineWrapping = value;
937 assert.equal(element.$.diff.lineWrapping, value);
938 });
939
940 test('passes in viewMode', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200941 const value = 'SIDE_BY_SIDE';
942 element.viewMode = value;
943 assert.equal(element.$.diff.viewMode, value);
944 });
945
946 test('passes in lineOfInterest', () => {
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200947 const value = {number: 123, leftSide: true};
948 element.lineOfInterest = value;
949 assert.equal(element.$.diff.lineOfInterest, value);
950 });
951
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200952 suite('_reportDiff', () => {
953 let reportStub;
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200954
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200955 setup(() => {
956 element = fixture('basic');
957 element.patchRange = {basePatchNum: 1};
958 reportStub = sandbox.stub(element.$.reporting, 'reportInteraction');
959 });
960
961 test('null and content-less', () => {
962 element._reportDiff(null);
963 assert.isFalse(reportStub.called);
964
965 element._reportDiff({});
966 assert.isFalse(reportStub.called);
967 });
968
969 test('diff w/ no delta', () => {
970 const diff = {
971 content: [
972 {ab: ['foo', 'bar']},
973 {ab: ['baz', 'foo']},
974 ],
975 };
976 element._reportDiff(diff);
977 assert.isTrue(reportStub.calledOnce);
978 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-zero');
979 assert.isUndefined(reportStub.lastCall.args[1]);
980 });
981
982 test('diff w/ no rebase delta', () => {
983 const diff = {
984 content: [
985 {ab: ['foo', 'bar']},
986 {a: ['baz', 'foo']},
987 {ab: ['foo', 'bar']},
988 {a: ['baz', 'foo'], b: ['bar', 'baz']},
989 {ab: ['foo', 'bar']},
990 {b: ['baz', 'foo']},
991 {ab: ['foo', 'bar']},
992 ],
993 };
994 element._reportDiff(diff);
995 assert.isTrue(reportStub.calledOnce);
996 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-zero');
997 assert.isUndefined(reportStub.lastCall.args[1]);
998 });
999
1000 test('diff w/ some rebase delta', () => {
1001 const diff = {
1002 content: [
1003 {ab: ['foo', 'bar']},
1004 {a: ['baz', 'foo'], due_to_rebase: true},
1005 {ab: ['foo', 'bar']},
1006 {a: ['baz', 'foo'], b: ['bar', 'baz']},
1007 {ab: ['foo', 'bar']},
1008 {b: ['baz', 'foo'], due_to_rebase: true},
1009 {ab: ['foo', 'bar']},
1010 {a: ['baz', 'foo']},
1011 ],
1012 };
1013 element._reportDiff(diff);
1014 assert.isTrue(reportStub.calledOnce);
1015 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-nonzero');
1016 assert.strictEqual(reportStub.lastCall.args[1], 50);
1017 });
1018
1019 test('diff w/ all rebase delta', () => {
1020 const diff = {content: [{
1021 a: ['foo', 'bar'],
1022 b: ['baz', 'foo'],
1023 due_to_rebase: true,
1024 }]};
1025 element._reportDiff(diff);
1026 assert.isTrue(reportStub.calledOnce);
1027 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-nonzero');
1028 assert.strictEqual(reportStub.lastCall.args[1], 100);
1029 });
1030
1031 test('diff against parent event', () => {
1032 element.patchRange.basePatchNum = 'PARENT';
1033 const diff = {content: [{
1034 a: ['foo', 'bar'],
1035 b: ['baz', 'foo'],
1036 }]};
1037 element._reportDiff(diff);
1038 assert.isTrue(reportStub.calledOnce);
1039 assert.equal(reportStub.lastCall.args[0], 'diff-against-parent');
1040 assert.isUndefined(reportStub.lastCall.args[1]);
1041 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +02001042 });
Wyatt Allenefc81212018-08-20 16:40:48 -07001043
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001044 test('_createThreads', () => {
1045 const comments = [
1046 {
1047 id: 'sallys_confession',
1048 message: 'i like you, jack',
1049 updated: '2015-12-23 15:00:20.396000000',
1050 line: 1,
1051 __commentSide: 'left',
1052 }, {
1053 id: 'jacks_reply',
1054 message: 'i like you, too',
1055 updated: '2015-12-24 15:01:20.396000000',
1056 __commentSide: 'left',
1057 line: 1,
1058 in_reply_to: 'sallys_confession',
1059 },
1060 {
1061 id: 'new_draft',
1062 message: 'i do not like either of you',
1063 __commentSide: 'left',
1064 __draft: true,
1065 updated: '2015-12-20 15:01:20.396000000',
1066 },
1067 ];
1068
1069 const actualThreads = element._createThreads(comments);
1070
1071 assert.equal(actualThreads.length, 2);
1072
1073 assert.equal(
1074 actualThreads[0].start_datetime, '2015-12-23 15:00:20.396000000');
1075 assert.equal(actualThreads[0].commentSide, 'left');
1076 assert.equal(actualThreads[0].comments.length, 2);
1077 assert.deepEqual(actualThreads[0].comments[0], comments[0]);
1078 assert.deepEqual(actualThreads[0].comments[1], comments[1]);
1079 assert.equal(actualThreads[0].patchNum, undefined);
1080 assert.equal(actualThreads[0].rootId, 'sallys_confession');
1081 assert.equal(actualThreads[0].lineNum, 1);
1082
1083 assert.equal(
1084 actualThreads[1].start_datetime, '2015-12-20 15:01:20.396000000');
1085 assert.equal(actualThreads[1].commentSide, 'left');
1086 assert.equal(actualThreads[1].comments.length, 1);
1087 assert.deepEqual(actualThreads[1].comments[0], comments[2]);
1088 assert.equal(actualThreads[1].patchNum, undefined);
1089 assert.equal(actualThreads[1].rootId, 'new_draft');
1090 assert.equal(actualThreads[1].lineNum, undefined);
1091 });
1092
1093 test('_createThreads inherits patchNum and range', () => {
1094 const comments = [{
1095 id: 'betsys_confession',
1096 message: 'i like you, jack',
1097 updated: '2015-12-24 15:00:10.396000000',
1098 range: {
1099 start_line: 1,
1100 start_character: 1,
1101 end_line: 1,
1102 end_character: 2,
1103 },
1104 patch_set: 5,
1105 __commentSide: 'left',
1106 line: 1,
1107 }];
1108
1109 expectedThreads = [
1110 {
1111 start_datetime: '2015-12-24 15:00:10.396000000',
1112 commentSide: 'left',
1113 comments: [{
1114 id: 'betsys_confession',
1115 message: 'i like you, jack',
1116 updated: '2015-12-24 15:00:10.396000000',
1117 range: {
1118 start_line: 1,
1119 start_character: 1,
1120 end_line: 1,
1121 end_character: 2,
1122 },
1123 patch_set: 5,
1124 __commentSide: 'left',
1125 line: 1,
1126 }],
1127 patchNum: 5,
1128 rootId: 'betsys_confession',
1129 range: {
1130 start_line: 1,
1131 start_character: 1,
1132 end_line: 1,
1133 end_character: 2,
1134 },
1135 lineNum: 1,
1136 isOnParent: false,
1137 },
1138 ];
1139
1140 assert.deepEqual(
1141 element._createThreads(comments),
1142 expectedThreads);
1143 });
1144
1145 test('_createThreads does not thread unrelated comments at same location',
1146 () => {
1147 const comments = [
1148 {
1149 id: 'sallys_confession',
1150 message: 'i like you, jack',
1151 updated: '2015-12-23 15:00:20.396000000',
1152 __commentSide: 'left',
1153 }, {
1154 id: 'jacks_reply',
1155 message: 'i like you, too',
1156 updated: '2015-12-24 15:01:20.396000000',
1157 __commentSide: 'left',
1158 },
1159 ];
1160 assert.equal(element._createThreads(comments).length, 2);
1161 });
1162
1163 test('_createThreads derives isOnParent using side from first comment',
1164 () => {
1165 const comments = [
1166 {
1167 id: 'sallys_confession',
1168 message: 'i like you, jack',
1169 updated: '2015-12-23 15:00:20.396000000',
1170 // line: 1,
1171 // __commentSide: 'left',
1172 }, {
1173 id: 'jacks_reply',
1174 message: 'i like you, too',
1175 updated: '2015-12-24 15:01:20.396000000',
1176 // __commentSide: 'left',
1177 // line: 1,
1178 in_reply_to: 'sallys_confession',
1179 },
1180 ];
1181
1182 assert.equal(element._createThreads(comments)[0].isOnParent, false);
1183
1184 comments[0].side = 'REVISION';
1185 assert.equal(element._createThreads(comments)[0].isOnParent, false);
1186
1187 comments[0].side = 'PARENT';
1188 assert.equal(element._createThreads(comments)[0].isOnParent, true);
1189 });
1190
Ole Rehmsen8b3dae72018-10-18 14:47:15 +02001191 test('_getOrCreateThread', () => {
Ole Rehmsen8b3dae72018-10-18 14:47:15 +02001192 const commentSide = 'left';
1193
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001194 assert.isOk(element._getOrCreateThread('2', 3,
1195 commentSide, undefined, false));
Ole Rehmsenada18d52018-10-25 14:46:06 +02001196
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001197 let threads = Polymer.dom(element.$.diff)
Ole Rehmsen9b946162018-11-19 21:45:41 +01001198 .queryDistributedElements('gr-comment-thread');
Ole Rehmsenada18d52018-10-25 14:46:06 +02001199
1200 assert.equal(threads.length, 1);
1201 assert.equal(threads[0].commentSide, commentSide);
1202 assert.equal(threads[0].range, undefined);
1203 assert.equal(threads[0].isOnParent, false);
1204 assert.equal(threads[0].patchNum, 2);
1205
Ole Rehmsen8b3dae72018-10-18 14:47:15 +02001206
1207 // Try to fetch a thread with a different range.
1208 range = {
Ole Rehmsenf66706c2018-11-13 10:21:54 +01001209 start_line: 1,
1210 start_character: 1,
1211 end_line: 1,
1212 end_character: 3,
Ole Rehmsen8b3dae72018-10-18 14:47:15 +02001213 };
1214
1215 assert.isOk(element._getOrCreateThread(
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001216 '3', 1, commentSide, range, true));
Ole Rehmsenada18d52018-10-25 14:46:06 +02001217
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001218 threads = Polymer.dom(element.$.diff)
Ole Rehmsen9b946162018-11-19 21:45:41 +01001219 .queryDistributedElements('gr-comment-thread');
Ole Rehmsenada18d52018-10-25 14:46:06 +02001220
1221 assert.equal(threads.length, 2);
1222 assert.equal(threads[1].commentSide, commentSide);
1223 assert.equal(threads[1].range, range);
1224 assert.equal(threads[1].isOnParent, true);
1225 assert.equal(threads[1].patchNum, 3);
Ole Rehmsen8b3dae72018-10-18 14:47:15 +02001226 });
1227
Ole Rehmsena970d4e2018-11-09 11:33:16 +01001228 test('_filterThreadElsForLocation with no threads', () => {
1229 const line = {beforeNumber: 3, afterNumber: 5};
1230
1231 const threads = [];
1232 assert.deepEqual(element._filterThreadElsForLocation(threads, line), []);
1233 assert.deepEqual(element._filterThreadElsForLocation(threads, line,
1234 Gerrit.DiffSide.LEFT), []);
1235 assert.deepEqual(element._filterThreadElsForLocation(threads, line,
1236 Gerrit.DiffSide.RIGHT), []);
1237 });
1238
1239 test('_filterThreadElsForLocation for line comments', () => {
1240 const line = {beforeNumber: 3, afterNumber: 5};
1241
1242 const l3 = document.createElement('div');
1243 l3.setAttribute('line-num', 3);
1244 l3.setAttribute('comment-side', 'left');
1245
1246 const l5 = document.createElement('div');
1247 l5.setAttribute('line-num', 5);
1248 l5.setAttribute('comment-side', 'left');
1249
1250 const r3 = document.createElement('div');
1251 r3.setAttribute('line-num', 3);
1252 r3.setAttribute('comment-side', 'right');
1253
1254 const r5 = document.createElement('div');
1255 r5.setAttribute('line-num', 5);
1256 r5.setAttribute('comment-side', 'right');
1257
1258 const threadEls = [l3, l5, r3, r5];
1259 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
1260 [l3, r5]);
1261 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
1262 Gerrit.DiffSide.LEFT), [l3]);
1263 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
1264 Gerrit.DiffSide.RIGHT), [r5]);
1265 });
1266
1267 test('_filterThreadElsForLocation for file comments', () => {
1268 const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
1269
1270 const l = document.createElement('div');
1271 l.setAttribute('comment-side', 'left');
Tao Zhoufd9ffb52019-09-20 13:05:46 +02001272 l.setAttribute('line-num', 'FILE');
Ole Rehmsena970d4e2018-11-09 11:33:16 +01001273
1274 const r = document.createElement('div');
1275 r.setAttribute('comment-side', 'right');
Tao Zhoufd9ffb52019-09-20 13:05:46 +02001276 r.setAttribute('line-num', 'FILE');
Ole Rehmsena970d4e2018-11-09 11:33:16 +01001277
1278 const threadEls = [l, r];
1279 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
1280 [l, r]);
1281 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
1282 Gerrit.DiffSide.BOTH), [l, r]);
1283 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
1284 Gerrit.DiffSide.LEFT), [l]);
1285 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
1286 Gerrit.DiffSide.RIGHT), [r]);
1287 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +02001288 });
1289</script>