blob: d09c8111a4258c00d479383dc556408385d5c511 [file] [log] [blame]
Dmitrii Filippov06117e82020-06-25 13:26:55 +02001/**
2 * @license
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Ole Rehmsene5de55e2018-08-23 16:52:57 +020017
Dmitrii Filippov06117e82020-06-25 13:26:55 +020018import '../../../test/common-test-setup-karma.js';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010019import './gr-diff-host.js';
Dmitrii Filippov26f91242020-03-23 20:57:55 +010020import {GrDiffBuilderImage} from '../gr-diff-builder/gr-diff-builder-image.js';
Dmitrii Filippoveb8b2692020-04-06 18:02:35 +020021import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010022import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
Dhruv Srivastava794db3a2020-11-11 11:28:08 +010023import {sortComments, createCommentThreads} from '../../../utils/comment-util.js';
24import {Side, CommentSide} from '../../../constants/constants.js';
Dmitrii Filippov0695d402020-10-22 16:57:57 +020025import {createChange} from '../../../test/test-data-generators.js';
Dhruv Srivastava794db3a2020-11-11 11:28:08 +010026import {FILE} from '../gr-diff/gr-diff-line.js';
Dhruv Srivastavab223df22020-12-08 17:48:59 +010027import {CoverageType} from '../../../types/types.js';
Dmitrii Filippov9fcdcb72020-04-07 13:26:52 +020028
Dmitrii Filippov06117e82020-06-25 13:26:55 +020029const basicFixture = fixtureFromElement('gr-diff-host');
30
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010031suite('gr-diff-host tests', () => {
32 let element;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +020033
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010034 let getLoggedIn;
Ole Rehmsene5de55e2018-08-23 16:52:57 +020035
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010036 setup(() => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010037 getLoggedIn = false;
38 stub('gr-rest-api-interface', {
39 async getLoggedIn() { return getLoggedIn; },
40 });
Dmitrii Filippov06117e82020-06-25 13:26:55 +020041 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +020042 element.changeNum = 123;
43 element.path = 'some/path';
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +020044 sinon.stub(element.reporting, 'time');
45 sinon.stub(element.reporting, 'timeEnd');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010046 });
47
48 suite('plugin layers', () => {
49 const pluginLayers = [{annotate: () => {}}, {annotate: () => {}}];
Ole Rehmsene5de55e2018-08-23 16:52:57 +020050 setup(() => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010051 stub('gr-js-api-interface', {
52 getDiffLayers() { return pluginLayers; },
Ole Rehmsen578f9212019-04-11 23:58:56 +020053 });
Dmitrii Filippov06117e82020-06-25 13:26:55 +020054 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +020055 element.changeNum = 123;
56 element.path = 'some/path';
Ole Rehmsene5de55e2018-08-23 16:52:57 +020057 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010058 test('plugin layers requested', () => {
59 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +020060 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010061 element.reload();
62 assert(element.$.jsAPI.getDiffLayers.called);
Ole Rehmsene5de55e2018-08-23 16:52:57 +020063 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010064 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +020065
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010066 test('thread-discard handling', () => {
Dhruv Srivastava794db3a2020-11-11 11:28:08 +010067 const threads = createCommentThreads([
Ben Rohlfs1d487062020-09-26 11:26:03 +020068 {
69 id: 4711,
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +010070 diffSide: Side.LEFT,
Ben Rohlfs1d487062020-09-26 11:26:03 +020071 updated: '2015-12-20 15:01:20.396000000',
Dhruv Srivastava794db3a2020-11-11 11:28:08 +010072 patch_set: 1,
73 path: 'some/path',
Ben Rohlfs1d487062020-09-26 11:26:03 +020074 },
75 {
76 id: 42,
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +010077 diffSide: Side.LEFT,
Ben Rohlfs1d487062020-09-26 11:26:03 +020078 updated: '2017-12-20 15:01:20.396000000',
Dhruv Srivastava794db3a2020-11-11 11:28:08 +010079 patch_set: 1,
80 path: 'some/path',
Ben Rohlfs1d487062020-09-26 11:26:03 +020081 },
82 ]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010083 element._parentIndex = 1;
Ben Rohlfs1d487062020-09-26 11:26:03 +020084 element.changeNum = 2;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010085 element.path = 'some/path';
86 element.projectName = 'Some project';
87 const threadEls = threads.map(
88 thread => {
89 const threadEl = element._createThreadElement(thread);
90 // Polymer 2 doesn't fire ready events and doesn't execute
91 // observers if element is not added to the Dom.
92 // See https://github.com/Polymer/old-docs-site/issues/2322
93 // and https://github.com/Polymer/polymer/issues/4526
94 element._attachThreadElement(threadEl);
95 return threadEl;
Mayank Kumar41b0f952019-10-03 18:04:08 -070096 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +010097 assert.equal(threadEls.length, 2);
Ben Rohlfs1d487062020-09-26 11:26:03 +020098 assert.equal(threadEls[0].comments[0].id, 4711);
99 assert.equal(threadEls[1].comments[0].id, 42);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100100 for (const threadEl of threadEls) {
Tao Zhou93a4ed72020-08-21 09:52:02 +0200101 element.appendChild(threadEl);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100102 }
Mayank Kumar41b0f952019-10-03 18:04:08 -0700103
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100104 threadEls[0].dispatchEvent(
105 new CustomEvent('thread-discard', {detail: {rootId: 4711}}));
106 const attachedThreads = element.queryAllEffectiveChildren(
107 'gr-comment-thread');
108 assert.equal(attachedThreads.length, 1);
Ben Rohlfs1d487062020-09-26 11:26:03 +0200109 assert.equal(attachedThreads[0].comments[0].id, 42);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100110 });
111
112 suite('render reporting', () => {
113 test('starts total and content timer on render-start', done => {
114 element.dispatchEvent(
115 new CustomEvent('render-start', {bubbles: true, composed: true}));
Milutin Kristoficda88b332020-03-24 10:19:12 +0100116 assert.isTrue(element.reporting.time.calledWithExactly(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100117 'Diff Total Render'));
Milutin Kristoficda88b332020-03-24 10:19:12 +0100118 assert.isTrue(element.reporting.time.calledWithExactly(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100119 'Diff Content Render'));
120 done();
121 });
122
123 test('ends content timer on render-content', () => {
124 element.dispatchEvent(
125 new CustomEvent('render-content', {bubbles: true, composed: true}));
Milutin Kristoficda88b332020-03-24 10:19:12 +0100126 assert.isTrue(element.reporting.timeEnd.calledWithExactly(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100127 'Diff Content Render'));
128 });
129
Oleb0368262020-10-12 16:50:24 +0200130 test('ends total and syntax timer after syntax layer', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200131 sinon.stub(element.reporting, 'diffViewContentDisplayed');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100132 let notifySyntaxProcessed;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200133 sinon.stub(element.$.syntaxLayer, 'process').returns(new Promise(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100134 resolve => {
135 notifySyntaxProcessed = resolve;
136 }));
Ben Rohlfs43935a42020-12-01 19:14:09 +0100137 sinon.stub(element.restApiService, 'getDiff').returns(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100138 Promise.resolve({content: []}));
139 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200140 element.change = createChange();
Ben Rohlfs43935a42020-12-01 19:14:09 +0100141 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100142 element.prefs = prefs;
143 return element.reload(true);
144 });
145 // Multiple cascading microtasks are scheduled.
Oleb0368262020-10-12 16:50:24 +0200146 await flush();
147 notifySyntaxProcessed();
148 // Multiple cascading microtasks are scheduled.
149 await flush();
150 assert.isTrue(element.reporting.timeEnd.calledWithExactly(
151 'Diff Total Render'));
152 assert.isTrue(element.reporting.timeEnd.calledWithExactly(
153 'Diff Syntax Render'));
154 assert.isTrue(element.reporting.diffViewContentDisplayed.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100155 });
Mayank Kumar41b0f952019-10-03 18:04:08 -0700156
Oleb0368262020-10-12 16:50:24 +0200157 test('ends total timer w/ no syntax layer processing', async () => {
Ben Rohlfs43935a42020-12-01 19:14:09 +0100158 sinon.stub(element.restApiService, 'getDiff').returns(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100159 Promise.resolve({content: []}));
160 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200161 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100162 element.reload();
163 // Multiple cascading microtasks are scheduled.
Oleb0368262020-10-12 16:50:24 +0200164 await flush();
165 // Reporting can be called with other parameters (ex. PluginsLoaded),
166 // but only 'Diff Total Render' is important in this test.
167 assert.equal(
168 element.reporting.timeEnd.getCalls()
169 .filter(call => call.calledWithExactly('Diff Total Render'))
170 .length,
171 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100172 });
173
Oleb0368262020-10-12 16:50:24 +0200174 test('completes reload promise after syntax layer processing', async () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100175 let notifySyntaxProcessed;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200176 sinon.stub(element.$.syntaxLayer, 'process').returns(new Promise(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100177 resolve => {
178 notifySyntaxProcessed = resolve;
179 }));
Ben Rohlfs43935a42020-12-01 19:14:09 +0100180 sinon.stub(element.restApiService, 'getDiff').returns(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100181 Promise.resolve({content: []}));
182 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200183 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100184 let reloadComplete = false;
Ben Rohlfs43935a42020-12-01 19:14:09 +0100185 element.restApiService.getDiffPreferences()
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100186 .then(prefs => {
187 element.prefs = prefs;
188 return element.reload();
189 })
190 .then(() => {
191 reloadComplete = true;
192 });
193 // Multiple cascading microtasks are scheduled.
Oleb0368262020-10-12 16:50:24 +0200194 await flush();
195 assert.isFalse(reloadComplete);
196 notifySyntaxProcessed();
197 // Assert after the notification task is processed.
198 await flush();
199 assert.isTrue(reloadComplete);
Ole Rehmsen578f9212019-04-11 23:58:56 +0200200 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100201 });
Ole Rehmsen578f9212019-04-11 23:58:56 +0200202
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100203 test('reload() cancels before network resolves', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200204 const cancelStub = sinon.stub(element.$.diff, 'cancel');
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200205
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100206 // Stub the network calls into requests that never resolve.
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200207 sinon.stub(element, '_getDiff').callsFake(() => new Promise(() => {}));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100208 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200209 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100210
Olee3ea65d2020-10-13 14:59:08 +0200211 // Needs to be set to something first for it to cancel.
212 element.diff = {
213 content: [{
214 a: ['foo'],
215 }],
216 };
217
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100218 element.reload();
219 assert.isTrue(cancelStub.called);
220 });
221
222 suite('not logged in', () => {
223 setup(() => {
224 getLoggedIn = false;
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200225 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +0200226 element.changeNum = 123;
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200227 element.change = createChange();
Ben Rohlfs1d487062020-09-26 11:26:03 +0200228 element.path = 'some/path';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100229 });
230
231 test('reload() loads files weblinks', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200232 const weblinksStub = sinon.stub(GerritNav, '_generateWeblinks')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100233 .returns({name: 'stubb', url: '#s'});
Ben Rohlfs43935a42020-12-01 19:14:09 +0100234 sinon.stub(element.restApiService, 'getDiff').returns(Promise.resolve({
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100235 content: [],
236 }));
237 element.projectName = 'test-project';
238 element.path = 'test-path';
239 element.commitRange = {baseCommit: 'test-base', commit: 'test-commit'};
Tao Zhoufd9ffb52019-09-20 13:05:46 +0200240 element.patchRange = {};
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100241 return element.reload().then(() => {
242 assert.isTrue(weblinksStub.calledTwice);
243 assert.isTrue(weblinksStub.firstCall.calledWith({
244 commit: 'test-base',
245 file: 'test-path',
246 options: {
247 weblinks: undefined,
248 },
249 repo: 'test-project',
Dmitrii Filippoveb8b2692020-04-06 18:02:35 +0200250 type: GerritNav.WeblinkType.FILE}));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100251 assert.isTrue(weblinksStub.secondCall.calledWith({
252 commit: 'test-commit',
253 file: 'test-path',
254 options: {
255 weblinks: undefined,
256 },
257 repo: 'test-project',
Dmitrii Filippoveb8b2692020-04-06 18:02:35 +0200258 type: GerritNav.WeblinkType.FILE}));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100259 assert.deepEqual(element.filesWeblinks, {
260 meta_a: [{name: 'stubb', url: '#s'}],
261 meta_b: [{name: 'stubb', url: '#s'}],
262 });
263 });
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200264 });
265
Milutin Kristofic890bee02020-06-10 17:12:00 +0200266 test('prefetch getDiff', done => {
Ben Rohlfs43935a42020-12-01 19:14:09 +0100267 const diffRestApiStub = sinon.stub(element.restApiService, 'getDiff')
Milutin Kristofic890bee02020-06-10 17:12:00 +0200268 .returns(Promise.resolve({content: []}));
269 element.changeNum = 123;
270 element.patchRange = {basePatchNum: 1, patchNum: 2};
271 element.path = 'file.txt';
272 element.prefetchDiff();
273 element._getDiff().then(() =>{
274 assert.isTrue(diffRestApiStub.calledOnce);
275 done();
276 });
277 });
278
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100279 test('_getDiff handles null diff responses', done => {
280 stub('gr-rest-api-interface', {
281 getDiff() { return Promise.resolve(null); },
282 });
283 element.changeNum = 123;
284 element.patchRange = {basePatchNum: 1, patchNum: 2};
285 element.path = 'file.txt';
286 element._getDiff().then(done);
287 });
288
289 test('reload resolves on error', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200290 const onErrStub = sinon.stub(element, '_handleGetDiffError');
Ole5d9d3932020-10-09 17:54:53 +0200291 const error = new Response(null, {ok: false, status: 500});
Ben Rohlfs43935a42020-12-01 19:14:09 +0100292 sinon.stub(element.restApiService, 'getDiff').callsFake(
Ole5d9d3932020-10-09 17:54:53 +0200293 (changeNum, basePatchNum, patchNum, path, whitespace, onErr) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100294 onErr(error);
295 });
296 element.patchRange = {};
297 return element.reload().then(() => {
298 assert.isTrue(onErrStub.calledOnce);
299 });
300 });
301
302 suite('_handleGetDiffError', () => {
303 let serverErrorStub;
304 let pageErrorStub;
305
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200306 setup(() => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100307 serverErrorStub = sinon.stub();
Ben Rohlfsea4cb7e2020-12-03 16:00:00 +0100308 document.addEventListener('server-error', serverErrorStub);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100309 pageErrorStub = sinon.stub();
310 element.addEventListener('page-error', pageErrorStub);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200311 });
312
Ben Rohlfsea4cb7e2020-12-03 16:00:00 +0100313 teardown(() => {
314 document.removeEventListener('server-error', serverErrorStub);
315 });
316
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100317 test('page error on HTTP-409', () => {
318 element._handleGetDiffError({status: 409});
319 assert.isTrue(serverErrorStub.calledOnce);
320 assert.isFalse(pageErrorStub.called);
321 assert.isNotOk(element._errorMessage);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200322 });
323
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100324 test('server error on non-HTTP-409', () => {
325 element._handleGetDiffError({status: 500});
326 assert.isFalse(serverErrorStub.called);
327 assert.isTrue(pageErrorStub.calledOnce);
328 assert.isNotOk(element._errorMessage);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200329 });
330
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100331 test('error message if showLoadFailure', () => {
332 element.showLoadFailure = true;
333 element._handleGetDiffError({status: 500, statusText: 'Failure!'});
334 assert.isFalse(serverErrorStub.called);
335 assert.isFalse(pageErrorStub.called);
336 assert.equal(element._errorMessage,
337 'Encountered error when loading the diff: 500 Failure!');
338 });
339 });
340
341 suite('image diffs', () => {
342 let mockFile1;
343 let mockFile2;
344 setup(() => {
345 mockFile1 = {
346 body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
347 'wsAAAAAAAAAAAAAAAAA/w==',
348 type: 'image/bmp',
349 };
350 mockFile2 = {
351 body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
352 'wsAAAAAAAAAAAAA/////w==',
353 type: 'image/bmp',
354 };
Ben Rohlfs43935a42020-12-01 19:14:09 +0100355 sinon.stub(element.restApiService,
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200356 'getB64FileContents')
357 .callsFake(
358 (changeId, patchNum, path, opt_parentIndex) => Promise.resolve(
359 opt_parentIndex === 1 ? mockFile1 : mockFile2)
360 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100361
362 element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200363 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100364 element.comments = {
365 left: [],
366 right: [],
367 meta: {patchRange: element.patchRange},
368 };
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200369 });
370
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100371 test('renders image diffs with same file name', done => {
372 const mockDiff = {
373 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
374 meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
375 lines: 560},
376 intraline_status: 'OK',
377 change_type: 'MODIFIED',
378 diff_header: [
379 'diff --git a/carrot.jpg b/carrot.jpg',
380 'index 2adc47d..f9c2f2c 100644',
381 '--- a/carrot.jpg',
382 '+++ b/carrot.jpg',
383 'Binary files differ',
384 ],
385 content: [{skip: 66}],
386 binary: true,
387 };
Ben Rohlfs43935a42020-12-01 19:14:09 +0100388 sinon.stub(element.restApiService, 'getDiff')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100389 .returns(Promise.resolve(mockDiff));
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200390
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100391 const rendered = () => {
392 // Recognizes that it should be an image diff.
393 assert.isTrue(element.isImageDiff);
394 assert.instanceOf(
395 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200396
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100397 // Left image rendered with the parent commit's version of the file.
398 const leftImage =
399 element.$.diff.$.diffTable.querySelector('td.left img');
400 const leftLabel =
401 element.$.diff.$.diffTable.querySelector('td.left label');
402 const leftLabelContent = leftLabel.querySelector('.label');
403 const leftLabelName = leftLabel.querySelector('.name');
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200404
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100405 const rightImage =
406 element.$.diff.$.diffTable.querySelector('td.right img');
407 const rightLabel = element.$.diff.$.diffTable.querySelector(
408 'td.right label');
409 const rightLabelContent = rightLabel.querySelector('.label');
410 const rightLabelName = rightLabel.querySelector('.name');
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200411
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100412 assert.isNotOk(rightLabelName);
413 assert.isNotOk(leftLabelName);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200414
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100415 let leftLoaded = false;
416 let rightLoaded = false;
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200417
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100418 leftImage.addEventListener('load', () => {
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200419 assert.isOk(leftImage);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100420 assert.equal(leftImage.getAttribute('src'),
421 'data:image/bmp;base64, ' + mockFile1.body);
422 assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
423 leftLoaded = true;
424 if (rightLoaded) {
425 element.removeEventListener('render', rendered);
426 done();
427 }
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200428 });
429
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100430 rightImage.addEventListener('load', () => {
431 assert.isOk(rightImage);
432 assert.equal(rightImage.getAttribute('src'),
433 'data:image/bmp;base64, ' + mockFile2.body);
434 assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
435
436 rightLoaded = true;
437 if (leftLoaded) {
438 element.removeEventListener('render', rendered);
439 done();
440 }
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200441 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100442 };
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200443
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100444 element.addEventListener('render', rendered);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200445
Ben Rohlfs43935a42020-12-01 19:14:09 +0100446 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100447 element.prefs = prefs;
448 element.reload();
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200449 });
450 });
451
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100452 test('renders image diffs with a different file name', done => {
453 const mockDiff = {
454 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
455 meta_b: {name: 'carrot2.jpg', content_type: 'image/jpeg',
456 lines: 560},
457 intraline_status: 'OK',
458 change_type: 'MODIFIED',
459 diff_header: [
460 'diff --git a/carrot.jpg b/carrot2.jpg',
461 'index 2adc47d..f9c2f2c 100644',
462 '--- a/carrot.jpg',
463 '+++ b/carrot2.jpg',
464 'Binary files differ',
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200465 ],
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100466 content: [{skip: 66}],
467 binary: true,
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200468 };
Ben Rohlfs43935a42020-12-01 19:14:09 +0100469 sinon.stub(element.restApiService, 'getDiff')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100470 .returns(Promise.resolve(mockDiff));
471
472 const rendered = () => {
473 // Recognizes that it should be an image diff.
474 assert.isTrue(element.isImageDiff);
475 assert.instanceOf(
476 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
477
478 // Left image rendered with the parent commit's version of the file.
479 const leftImage =
480 element.$.diff.$.diffTable.querySelector('td.left img');
481 const leftLabel =
482 element.$.diff.$.diffTable.querySelector('td.left label');
483 const leftLabelContent = leftLabel.querySelector('.label');
484 const leftLabelName = leftLabel.querySelector('.name');
485
486 const rightImage =
487 element.$.diff.$.diffTable.querySelector('td.right img');
488 const rightLabel = element.$.diff.$.diffTable.querySelector(
489 'td.right label');
490 const rightLabelContent = rightLabel.querySelector('.label');
491 const rightLabelName = rightLabel.querySelector('.name');
492
493 assert.isOk(rightLabelName);
494 assert.isOk(leftLabelName);
495 assert.equal(leftLabelName.textContent, mockDiff.meta_a.name);
496 assert.equal(rightLabelName.textContent, mockDiff.meta_b.name);
497
498 let leftLoaded = false;
499 let rightLoaded = false;
500
501 leftImage.addEventListener('load', () => {
502 assert.isOk(leftImage);
503 assert.equal(leftImage.getAttribute('src'),
504 'data:image/bmp;base64, ' + mockFile1.body);
505 assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
506 leftLoaded = true;
507 if (rightLoaded) {
508 element.removeEventListener('render', rendered);
509 done();
510 }
511 });
512
513 rightImage.addEventListener('load', () => {
514 assert.isOk(rightImage);
515 assert.equal(rightImage.getAttribute('src'),
516 'data:image/bmp;base64, ' + mockFile2.body);
517 assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
518
519 rightLoaded = true;
520 if (leftLoaded) {
521 element.removeEventListener('render', rendered);
522 done();
523 }
524 });
525 };
526
527 element.addEventListener('render', rendered);
528
Ben Rohlfs43935a42020-12-01 19:14:09 +0100529 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100530 element.prefs = prefs;
531 element.reload();
532 });
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200533 });
534
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100535 test('renders added image', done => {
536 const mockDiff = {
537 meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
538 lines: 560},
539 intraline_status: 'OK',
540 change_type: 'ADDED',
541 diff_header: [
542 'diff --git a/carrot.jpg b/carrot.jpg',
543 'index 0000000..f9c2f2c 100644',
544 '--- /dev/null',
545 '+++ b/carrot.jpg',
546 'Binary files differ',
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200547 ],
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100548 content: [{skip: 66}],
549 binary: true,
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200550 };
Ben Rohlfs43935a42020-12-01 19:14:09 +0100551 sinon.stub(element.restApiService, 'getDiff')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100552 .returns(Promise.resolve(mockDiff));
553
554 element.addEventListener('render', () => {
555 // Recognizes that it should be an image diff.
556 assert.isTrue(element.isImageDiff);
557 assert.instanceOf(
558 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
559
560 const leftImage =
561 element.$.diff.$.diffTable.querySelector('td.left img');
562 const rightImage =
563 element.$.diff.$.diffTable.querySelector('td.right img');
564
565 assert.isNotOk(leftImage);
566 assert.isOk(rightImage);
567 done();
568 });
569
Ben Rohlfs43935a42020-12-01 19:14:09 +0100570 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100571 element.prefs = prefs;
572 element.reload();
573 });
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200574 });
575
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100576 test('renders removed image', done => {
577 const mockDiff = {
578 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg',
579 lines: 560},
580 intraline_status: 'OK',
581 change_type: 'DELETED',
582 diff_header: [
583 'diff --git a/carrot.jpg b/carrot.jpg',
584 'index f9c2f2c..0000000 100644',
585 '--- a/carrot.jpg',
586 '+++ /dev/null',
587 'Binary files differ',
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200588 ],
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100589 content: [{skip: 66}],
590 binary: true,
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200591 };
Ben Rohlfs43935a42020-12-01 19:14:09 +0100592 sinon.stub(element.restApiService, 'getDiff')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100593 .returns(Promise.resolve(mockDiff));
594
595 element.addEventListener('render', () => {
596 // Recognizes that it should be an image diff.
597 assert.isTrue(element.isImageDiff);
598 assert.instanceOf(
599 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
600
601 const leftImage =
602 element.$.diff.$.diffTable.querySelector('td.left img');
603 const rightImage =
604 element.$.diff.$.diffTable.querySelector('td.right img');
605
606 assert.isOk(leftImage);
607 assert.isNotOk(rightImage);
608 done();
609 });
610
Ben Rohlfs43935a42020-12-01 19:14:09 +0100611 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100612 element.prefs = prefs;
613 element.reload();
614 });
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200615 });
616
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100617 test('does not render disallowed image type', done => {
618 const mockDiff = {
619 meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg-evil',
620 lines: 560},
621 intraline_status: 'OK',
622 change_type: 'DELETED',
623 diff_header: [
624 'diff --git a/carrot.jpg b/carrot.jpg',
625 'index f9c2f2c..0000000 100644',
626 '--- a/carrot.jpg',
627 '+++ /dev/null',
628 'Binary files differ',
629 ],
630 content: [{skip: 66}],
631 binary: true,
632 };
633 mockFile1.type = 'image/jpeg-evil';
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200634
Ben Rohlfs43935a42020-12-01 19:14:09 +0100635 sinon.stub(element.restApiService, 'getDiff')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100636 .returns(Promise.resolve(mockDiff));
637
638 element.addEventListener('render', () => {
639 // Recognizes that it should be an image diff.
640 assert.isTrue(element.isImageDiff);
641 assert.instanceOf(
642 element.$.diff.$.diffBuilder._builder, GrDiffBuilderImage);
643 const leftImage =
644 element.$.diff.$.diffTable.querySelector('td.left img');
645 assert.isNotOk(leftImage);
646 done();
647 });
648
Ben Rohlfs43935a42020-12-01 19:14:09 +0100649 element.restApiService.getDiffPreferences().then(prefs => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100650 element.prefs = prefs;
651 element.reload();
652 });
653 });
654 });
655 });
656
657 test('delegates cancel()', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200658 const stub = sinon.stub(element.$.diff, 'cancel');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100659 element.patchRange = {};
Olee3ea65d2020-10-13 14:59:08 +0200660 element.cancel();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100661 assert.isTrue(stub.calledOnce);
662 assert.equal(stub.lastCall.args.length, 0);
663 });
664
665 test('delegates getCursorStops()', () => {
666 const returnValue = [document.createElement('b')];
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200667 const stub = sinon.stub(element.$.diff, 'getCursorStops')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100668 .returns(returnValue);
669 assert.equal(element.getCursorStops(), returnValue);
670 assert.isTrue(stub.calledOnce);
671 assert.equal(stub.lastCall.args.length, 0);
672 });
673
674 test('delegates isRangeSelected()', () => {
675 const returnValue = true;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200676 const stub = sinon.stub(element.$.diff, 'isRangeSelected')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100677 .returns(returnValue);
678 assert.equal(element.isRangeSelected(), returnValue);
679 assert.isTrue(stub.calledOnce);
680 assert.equal(stub.lastCall.args.length, 0);
681 });
682
683 test('delegates toggleLeftDiff()', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200684 const stub = sinon.stub(element.$.diff, 'toggleLeftDiff');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100685 element.toggleLeftDiff();
686 assert.isTrue(stub.calledOnce);
687 assert.equal(stub.lastCall.args.length, 0);
688 });
689
690 suite('blame', () => {
691 setup(() => {
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200692 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +0200693 element.changeNum = 123;
694 element.path = 'some/path';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100695 });
696
697 test('clearBlame', () => {
698 element._blame = [];
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200699 const setBlameSpy = sinon.spy(element.$.diff.$.diffBuilder, 'setBlame');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100700 element.clearBlame();
701 assert.isNull(element._blame);
702 assert.isTrue(setBlameSpy.calledWithExactly(null));
703 assert.equal(element.isBlameLoaded, false);
704 });
705
706 test('loadBlame', () => {
707 const mockBlame = [{id: 'commit id', ranges: [{start: 1, end: 2}]}];
708 const showAlertStub = sinon.stub();
709 element.addEventListener('show-alert', showAlertStub);
Ben Rohlfs43935a42020-12-01 19:14:09 +0100710 const getBlameStub = sinon.stub(element.restApiService, 'getBlame')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100711 .returns(Promise.resolve(mockBlame));
712 element.changeNum = 42;
713 element.patchRange = {patchNum: 5, basePatchNum: 4};
714 element.path = 'foo/bar.baz';
715 return element.loadBlame().then(() => {
716 assert.isTrue(getBlameStub.calledWithExactly(
717 42, 5, 'foo/bar.baz', true));
718 assert.isFalse(showAlertStub.called);
719 assert.equal(element._blame, mockBlame);
720 assert.equal(element.isBlameLoaded, true);
Ole Rehmsenb1a79672018-08-27 22:43:38 +0200721 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +0200722 });
Wyatt Allenefc81212018-08-20 16:40:48 -0700723
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100724 test('loadBlame empty', () => {
725 const mockBlame = [];
726 const showAlertStub = sinon.stub();
727 element.addEventListener('show-alert', showAlertStub);
Ben Rohlfs43935a42020-12-01 19:14:09 +0100728 sinon.stub(element.restApiService, 'getBlame')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100729 .returns(Promise.resolve(mockBlame));
730 element.changeNum = 42;
731 element.patchRange = {patchNum: 5, basePatchNum: 4};
732 element.path = 'foo/bar.baz';
733 return element.loadBlame()
734 .then(() => {
735 assert.isTrue(false, 'Promise should not resolve');
736 })
737 .catch(() => {
738 assert.isTrue(showAlertStub.calledOnce);
739 assert.isNull(element._blame);
740 assert.equal(element.isBlameLoaded, false);
741 });
742 });
743 });
744
745 test('getThreadEls() returns .comment-threads', () => {
746 const threadEl = document.createElement('div');
747 threadEl.className = 'comment-thread';
Tao Zhou93a4ed72020-08-21 09:52:02 +0200748 element.$.diff.appendChild(threadEl);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100749 assert.deepEqual(element.getThreadEls(), [threadEl]);
750 });
751
752 test('delegates addDraftAtLine(el)', () => {
753 const param0 = document.createElement('b');
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200754 const stub = sinon.stub(element.$.diff, 'addDraftAtLine');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100755 element.addDraftAtLine(param0);
756 assert.isTrue(stub.calledOnce);
757 assert.equal(stub.lastCall.args.length, 1);
758 assert.equal(stub.lastCall.args[0], param0);
759 });
760
761 test('delegates clearDiffContent()', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200762 const stub = sinon.stub(element.$.diff, 'clearDiffContent');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100763 element.clearDiffContent();
764 assert.isTrue(stub.calledOnce);
765 assert.equal(stub.lastCall.args.length, 0);
766 });
767
768 test('delegates expandAllContext()', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200769 const stub = sinon.stub(element.$.diff, 'expandAllContext');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100770 element.expandAllContext();
771 assert.isTrue(stub.calledOnce);
772 assert.equal(stub.lastCall.args.length, 0);
773 });
774
775 test('passes in changeNum', () => {
Ben Rohlfs1d487062020-09-26 11:26:03 +0200776 element.changeNum = 12345;
777 assert.equal(element.$.diff.changeNum, 12345);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100778 });
779
780 test('passes in noAutoRender', () => {
781 const value = true;
782 element.noAutoRender = value;
783 assert.equal(element.$.diff.noAutoRender, value);
784 });
785
786 test('passes in patchRange', () => {
787 const value = {patchNum: 'foo', basePatchNum: 'bar'};
788 element.patchRange = value;
789 assert.equal(element.$.diff.patchRange, value);
790 });
791
792 test('passes in path', () => {
793 const value = 'some/file/path';
794 element.path = value;
795 assert.equal(element.$.diff.path, value);
796 });
797
798 test('passes in prefs', () => {
799 const value = {};
800 element.prefs = value;
801 assert.equal(element.$.diff.prefs, value);
802 });
803
804 test('passes in changeNum', () => {
Ben Rohlfs1d487062020-09-26 11:26:03 +0200805 element.changeNum = 12345;
806 assert.equal(element.$.diff.changeNum, 12345);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100807 });
808
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100809 test('passes in displayLine', () => {
810 const value = true;
811 element.displayLine = value;
812 assert.equal(element.$.diff.displayLine, value);
813 });
814
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100815 test('passes in hidden', () => {
816 const value = true;
817 element.hidden = value;
818 assert.equal(element.$.diff.hidden, value);
819 assert.isNotNull(element.getAttribute('hidden'));
820 });
821
822 test('passes in noRenderOnPrefsChange', () => {
823 const value = true;
824 element.noRenderOnPrefsChange = value;
825 assert.equal(element.$.diff.noRenderOnPrefsChange, value);
826 });
827
828 test('passes in lineWrapping', () => {
829 const value = true;
830 element.lineWrapping = value;
831 assert.equal(element.$.diff.lineWrapping, value);
832 });
833
834 test('passes in viewMode', () => {
835 const value = 'SIDE_BY_SIDE';
836 element.viewMode = value;
837 assert.equal(element.$.diff.viewMode, value);
838 });
839
840 test('passes in lineOfInterest', () => {
841 const value = {number: 123, leftSide: true};
842 element.lineOfInterest = value;
843 assert.equal(element.$.diff.lineOfInterest, value);
844 });
845
846 suite('_reportDiff', () => {
847 let reportStub;
848
849 setup(() => {
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200850 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +0200851 element.changeNum = 123;
Tao Zhoue0d7c652020-05-04 11:32:05 +0200852 element.path = 'file.txt';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100853 element.patchRange = {basePatchNum: 1};
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200854 reportStub = sinon.stub(element.reporting, 'reportInteraction');
Dhruv Srivastavab84bf912020-02-03 19:05:59 +0100855 });
856
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100857 test('null and content-less', () => {
858 element._reportDiff(null);
859 assert.isFalse(reportStub.called);
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200860
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100861 element._reportDiff({});
862 assert.isFalse(reportStub.called);
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200863 });
864
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100865 test('diff w/ no delta', () => {
866 const diff = {
867 content: [
868 {ab: ['foo', 'bar']},
869 {ab: ['baz', 'foo']},
870 ],
871 };
872 element._reportDiff(diff);
873 assert.isTrue(reportStub.calledOnce);
874 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-zero');
875 assert.isUndefined(reportStub.lastCall.args[1]);
876 });
877
878 test('diff w/ no rebase delta', () => {
879 const diff = {
880 content: [
881 {ab: ['foo', 'bar']},
882 {a: ['baz', 'foo']},
883 {ab: ['foo', 'bar']},
884 {a: ['baz', 'foo'], b: ['bar', 'baz']},
885 {ab: ['foo', 'bar']},
886 {b: ['baz', 'foo']},
887 {ab: ['foo', 'bar']},
888 ],
889 };
890 element._reportDiff(diff);
891 assert.isTrue(reportStub.calledOnce);
892 assert.equal(reportStub.lastCall.args[0], 'rebase-percent-zero');
893 assert.isUndefined(reportStub.lastCall.args[1]);
894 });
895
896 test('diff w/ some rebase delta', () => {
897 const diff = {
898 content: [
899 {ab: ['foo', 'bar']},
900 {a: ['baz', 'foo'], due_to_rebase: true},
901 {ab: ['foo', 'bar']},
902 {a: ['baz', 'foo'], b: ['bar', 'baz']},
903 {ab: ['foo', 'bar']},
904 {b: ['baz', 'foo'], due_to_rebase: true},
905 {ab: ['foo', 'bar']},
906 {a: ['baz', 'foo']},
907 ],
908 };
909 element._reportDiff(diff);
910 assert.isTrue(reportStub.calledOnce);
911 assert.isTrue(reportStub.calledWith(
912 'rebase-percent-nonzero',
913 {percentRebaseDelta: 50}
914 ));
915 });
916
917 test('diff w/ all rebase delta', () => {
918 const diff = {content: [{
919 a: ['foo', 'bar'],
920 b: ['baz', 'foo'],
921 due_to_rebase: true,
922 }]};
923 element._reportDiff(diff);
924 assert.isTrue(reportStub.calledOnce);
925 assert.isTrue(reportStub.calledWith(
926 'rebase-percent-nonzero',
927 {percentRebaseDelta: 100}
928 ));
929 });
930
931 test('diff against parent event', () => {
932 element.patchRange.basePatchNum = 'PARENT';
933 const diff = {content: [{
934 a: ['foo', 'bar'],
935 b: ['baz', 'foo'],
936 }]};
937 element._reportDiff(diff);
938 assert.isTrue(reportStub.calledOnce);
939 assert.equal(reportStub.lastCall.args[0], 'diff-against-parent');
940 assert.isUndefined(reportStub.lastCall.args[1]);
941 });
942 });
943
944 test('comments sorting', () => {
945 const comments = [
946 {
947 id: 'new_draft',
948 message: 'i do not like either of you',
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +0100949 diffSide: Side.LEFT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100950 __draft: true,
951 updated: '2015-12-20 15:01:20.396000000',
952 },
953 {
954 id: 'sallys_confession',
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200955 message: 'i like you, jack',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100956 updated: '2015-12-23 15:00:20.396000000',
957 line: 1,
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +0100958 diffSide: Side.LEFT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100959 }, {
960 id: 'jacks_reply',
961 message: 'i like you, too',
962 updated: '2015-12-24 15:01:20.396000000',
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +0100963 diffSide: Side.LEFT,
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200964 line: 1,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100965 in_reply_to: 'sallys_confession',
966 },
967 ];
Dhruv Srivastavabc089d92020-09-23 16:31:01 +0200968 const sortedComments = sortComments(comments);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100969 assert.equal(sortedComments[0], comments[1]);
970 assert.equal(sortedComments[1], comments[2]);
971 assert.equal(sortedComments[2], comments[0]);
972 });
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +0200973
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100974 test('_createThreads', () => {
975 const comments = [
976 {
977 id: 'sallys_confession',
978 message: 'i like you, jack',
979 updated: '2015-12-23 15:00:20.396000000',
980 line: 1,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100981 patch_set: 1,
982 path: 'some/path',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100983 }, {
984 id: 'jacks_reply',
985 message: 'i like you, too',
986 updated: '2015-12-24 15:01:20.396000000',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100987 line: 1,
988 in_reply_to: 'sallys_confession',
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100989 patch_set: 1,
990 path: 'some/path',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100991 },
992 {
993 id: 'new_draft',
994 message: 'i do not like either of you',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100995 __draft: true,
996 updated: '2015-12-20 15:01:20.396000000',
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100997 patch_set: 1,
998 path: 'some/path',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100999 },
1000 ];
1001
Dhruv Srivastava868f20a2020-12-02 15:37:20 +01001002 const actualThreads = createCommentThreads(comments,
1003 {basePatchNum: 1, patchNum: 4});
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001004
1005 assert.equal(actualThreads.length, 2);
1006
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001007 assert.equal(actualThreads[0].diffSide, Side.LEFT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001008 assert.equal(actualThreads[0].comments.length, 2);
1009 assert.deepEqual(actualThreads[0].comments[0], comments[0]);
1010 assert.deepEqual(actualThreads[0].comments[1], comments[1]);
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001011 assert.equal(actualThreads[0].patchNum, 1);
1012 assert.equal(actualThreads[0].line, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001013
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001014 assert.equal(actualThreads[1].diffSide, Side.LEFT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001015 assert.equal(actualThreads[1].comments.length, 1);
1016 assert.deepEqual(actualThreads[1].comments[0], comments[2]);
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001017 assert.equal(actualThreads[1].patchNum, 1);
1018 assert.equal(actualThreads[1].line, FILE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001019 });
1020
Dhruv Srivastava868f20a2020-12-02 15:37:20 +01001021 test('_createThreads derives patchNum and range', () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001022 const comments = [{
1023 id: 'betsys_confession',
1024 message: 'i like you, jack',
1025 updated: '2015-12-24 15:00:10.396000000',
1026 range: {
1027 start_line: 1,
1028 start_character: 1,
1029 end_line: 1,
1030 end_character: 2,
1031 },
1032 patch_set: 5,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001033 path: '/p',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001034 line: 1,
1035 }];
1036
1037 const expectedThreads = [
1038 {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001039 diffSide: Side.LEFT,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001040 commentSide: CommentSide.REVISION,
1041 path: '/p',
1042 rootId: 'betsys_confession',
Dhruv Srivastava2073c492020-12-16 16:36:39 +01001043 mergeParentNum: undefined,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001044 comments: [{
1045 id: 'betsys_confession',
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001046 path: '/p',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001047 message: 'i like you, jack',
1048 updated: '2015-12-24 15:00:10.396000000',
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001049 range: {
1050 start_line: 1,
1051 start_character: 1,
1052 end_line: 1,
1053 end_character: 2,
1054 },
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001055 patch_set: 5,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001056 line: 1,
1057 }],
1058 patchNum: 5,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001059 range: {
1060 start_line: 1,
1061 start_character: 1,
1062 end_line: 1,
1063 end_character: 2,
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001064 },
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001065 line: 1,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001066 },
1067 ];
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001068
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001069 assert.deepEqual(
Dhruv Srivastava868f20a2020-12-02 15:37:20 +01001070 createCommentThreads(comments, {basePatchNum: 5, patchNum: 10}),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001071 expectedThreads);
1072 });
Ole Rehmsen8c8ce2d2018-10-12 16:20:57 +02001073
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001074 test('_createThreads does not thread unrelated comments at same location',
1075 () => {
1076 const comments = [
1077 {
1078 id: 'sallys_confession',
1079 message: 'i like you, jack',
1080 updated: '2015-12-23 15:00:20.396000000',
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +01001081 diffSide: Side.LEFT,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001082 path: '/p',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001083 }, {
1084 id: 'jacks_reply',
1085 message: 'i like you, too',
1086 updated: '2015-12-24 15:01:20.396000000',
Dhruv Srivastavaae9ac142020-12-01 22:57:19 +01001087 diffSide: Side.LEFT,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001088 path: '/p',
Tao Zhou3dba39e2019-12-13 15:14:31 +01001089 },
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001090 ];
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001091 assert.equal(createCommentThreads(comments).length, 2);
Tao Zhou3dba39e2019-12-13 15:14:31 +01001092 });
1093
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001094 test('_getOrCreateThread', () => {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001095 const diffSide = Side.LEFT;
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001096 const commentSide = CommentSide.PARENT;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001097
1098 assert.isOk(element._getOrCreateThread('2', 3,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001099 diffSide, commentSide, '/p'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001100
1101 let threads = dom(element.$.diff)
1102 .queryDistributedElements('gr-comment-thread');
1103
1104 assert.equal(threads.length, 1);
Dhruv Srivastavad3fbf88532020-11-20 14:25:17 +01001105 assert.equal(threads[0].diffSide, diffSide);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001106 assert.equal(threads[0].range, undefined);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001107 assert.equal(threads[0].patchNum, 2);
1108
1109 // Try to fetch a thread with a different range.
1110 const range = {
1111 start_line: 1,
1112 start_character: 1,
1113 end_line: 1,
1114 end_character: 3,
1115 };
1116
1117 assert.isOk(element._getOrCreateThread(
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001118 '3', 1, diffSide, commentSide, '/p', range));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001119
1120 threads = dom(element.$.diff)
1121 .queryDistributedElements('gr-comment-thread');
1122
1123 assert.equal(threads.length, 2);
Dhruv Srivastavad3fbf88532020-11-20 14:25:17 +01001124 assert.equal(threads[1].diffSide, diffSide);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001125 assert.equal(threads[1].range, range);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001126 assert.equal(threads[1].patchNum, 3);
1127 });
1128
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001129 test('thread should use old file path if first created ' +
Tao Zhoue0d7c652020-05-04 11:32:05 +02001130 'on patch set (left) before renaming', () => {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001131 const diffSide = Side.LEFT;
Tao Zhoue0d7c652020-05-04 11:32:05 +02001132 element.file = {basePath: 'file_renamed.txt', path: element.path};
1133
1134 assert.isOk(element._getOrCreateThread('2', 3,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001135 diffSide, CommentSide.REVISION, '/p'));
Tao Zhoue0d7c652020-05-04 11:32:05 +02001136
1137 const threads = dom(element.$.diff)
1138 .queryDistributedElements('gr-comment-thread');
1139
1140 assert.equal(threads.length, 1);
Dhruv Srivastavad3fbf88532020-11-20 14:25:17 +01001141 assert.equal(threads[0].diffSide, diffSide);
Tao Zhoue0d7c652020-05-04 11:32:05 +02001142 assert.equal(threads[0].path, element.file.basePath);
1143 });
1144
1145 test('thread should use new file path if first created' +
1146 'on patch set (right) after renaming', () => {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001147 const diffSide = Side.RIGHT;
Tao Zhoue0d7c652020-05-04 11:32:05 +02001148 element.file = {basePath: 'file_renamed.txt', path: element.path};
1149
1150 assert.isOk(element._getOrCreateThread('2', 3,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001151 diffSide, CommentSide.REVISION, '/p'));
Tao Zhoue0d7c652020-05-04 11:32:05 +02001152
1153 const threads = dom(element.$.diff)
1154 .queryDistributedElements('gr-comment-thread');
1155
1156 assert.equal(threads.length, 1);
Dhruv Srivastavad3fbf88532020-11-20 14:25:17 +01001157 assert.equal(threads[0].diffSide, diffSide);
Tao Zhoue0d7c652020-05-04 11:32:05 +02001158 assert.equal(threads[0].path, element.file.path);
1159 });
1160
1161 test('thread should use new file path if first created' +
1162 'on patch set (left) but is base', () => {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001163 const diffSide = Side.LEFT;
Tao Zhoue0d7c652020-05-04 11:32:05 +02001164 element.file = {basePath: 'file_renamed.txt', path: element.path};
1165
1166 assert.isOk(element._getOrCreateThread('2', 3,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +01001167 diffSide, CommentSide.PARENT, '/p', undefined));
Tao Zhoue0d7c652020-05-04 11:32:05 +02001168
1169 const threads = dom(element.$.diff)
1170 .queryDistributedElements('gr-comment-thread');
1171
1172 assert.equal(threads.length, 1);
Dhruv Srivastavad3fbf88532020-11-20 14:25:17 +01001173 assert.equal(threads[0].diffSide, diffSide);
Tao Zhoue0d7c652020-05-04 11:32:05 +02001174 assert.equal(threads[0].path, element.file.path);
1175 });
1176
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001177 test('_filterThreadElsForLocation with no threads', () => {
1178 const line = {beforeNumber: 3, afterNumber: 5};
1179
1180 const threads = [];
1181 assert.deepEqual(element._filterThreadElsForLocation(threads, line), []);
1182 assert.deepEqual(element._filterThreadElsForLocation(threads, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001183 Side.LEFT), []);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001184 assert.deepEqual(element._filterThreadElsForLocation(threads, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001185 Side.RIGHT), []);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001186 });
1187
1188 test('_filterThreadElsForLocation for line comments', () => {
1189 const line = {beforeNumber: 3, afterNumber: 5};
1190
1191 const l3 = document.createElement('div');
1192 l3.setAttribute('line-num', 3);
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001193 l3.setAttribute('diff-side', Side.LEFT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001194
1195 const l5 = document.createElement('div');
1196 l5.setAttribute('line-num', 5);
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001197 l5.setAttribute('diff-side', Side.LEFT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001198
1199 const r3 = document.createElement('div');
1200 r3.setAttribute('line-num', 3);
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001201 r3.setAttribute('diff-side', Side.RIGHT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001202
1203 const r5 = document.createElement('div');
1204 r5.setAttribute('line-num', 5);
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001205 r5.setAttribute('diff-side', Side.RIGHT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001206
1207 const threadEls = [l3, l5, r3, r5];
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001208 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001209 Side.LEFT), [l3]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001210 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001211 Side.RIGHT), [r5]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001212 });
1213
1214 test('_filterThreadElsForLocation for file comments', () => {
1215 const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
1216
1217 const l = document.createElement('div');
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001218 l.setAttribute('diff-side', Side.LEFT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001219 l.setAttribute('line-num', 'FILE');
1220
1221 const r = document.createElement('div');
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001222 r.setAttribute('diff-side', Side.RIGHT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001223 r.setAttribute('line-num', 'FILE');
1224
1225 const threadEls = [l, r];
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001226 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001227 Side.LEFT), [l]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001228 assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
Ben Rohlfs1d487062020-09-26 11:26:03 +02001229 Side.RIGHT), [r]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001230 });
1231
1232 suite('syntax layer with syntax_highlighting on', () => {
1233 setup(() => {
1234 const prefs = {
1235 line_length: 10,
1236 show_tabs: true,
1237 tab_size: 4,
1238 context: -1,
1239 syntax_highlighting: true,
1240 };
1241 element.patchRange = {};
1242 element.prefs = prefs;
Ben Rohlfs1d487062020-09-26 11:26:03 +02001243 element.changeNum = 123;
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001244 element.change = createChange();
Ben Rohlfs1d487062020-09-26 11:26:03 +02001245 element.path = 'some/path';
Tao Zhou3dba39e2019-12-13 15:14:31 +01001246 });
Hermann Loose234616a2020-02-11 16:54:27 +01001247
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001248 test('gr-diff-host provides syntax highlighting layer to gr-diff', () => {
1249 element.reload();
1250 assert.equal(element.$.diff.layers[0], element.$.syntaxLayer);
1251 });
Hermann Loose234616a2020-02-11 16:54:27 +01001252
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001253 test('rendering normal-sized diff does not disable syntax', () => {
1254 element.diff = {
1255 content: [{
1256 a: ['foo'],
1257 }],
1258 };
1259 assert.isTrue(element.$.syntaxLayer.enabled);
1260 });
Hermann Loose234616a2020-02-11 16:54:27 +01001261
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001262 test('rendering large diff disables syntax', () => {
1263 // Before it renders, set the first diff line to 500 '*' characters.
1264 element.diff = {
1265 content: [{
1266 a: [new Array(501).join('*')],
1267 }],
1268 };
1269 assert.isFalse(element.$.syntaxLayer.enabled);
1270 });
Hermann Loose234616a2020-02-11 16:54:27 +01001271
Oleb0368262020-10-12 16:50:24 +02001272 test('starts syntax layer processing on render event', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001273 sinon.stub(element.$.syntaxLayer, 'process')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001274 .returns(Promise.resolve());
Ben Rohlfs43935a42020-12-01 19:14:09 +01001275 sinon.stub(element.restApiService, 'getDiff').returns(
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001276 Promise.resolve({content: []}));
1277 element.reload();
Oleb0368262020-10-12 16:50:24 +02001278 await flush();
1279 element.dispatchEvent(
1280 new CustomEvent('render', {bubbles: true, composed: true}));
1281 assert.isTrue(element.$.syntaxLayer.process.called);
Hermann Loose234616a2020-02-11 16:54:27 +01001282 });
Ole Rehmsene5de55e2018-08-23 16:52:57 +02001283 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001284
David Ostrovskya2401c12020-05-03 19:29:26 +02001285 suite('syntax layer with syntax_highlighting off', () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001286 setup(() => {
1287 const prefs = {
1288 line_length: 10,
1289 show_tabs: true,
1290 tab_size: 4,
1291 context: -1,
1292 };
1293 element.diff = {
1294 content: [{
1295 a: ['foo'],
1296 }],
1297 };
1298 element.patchRange = {};
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001299 element.change = createChange();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001300 element.prefs = prefs;
1301 });
1302
1303 test('gr-diff-host provides syntax highlighting layer', () => {
1304 element.reload();
1305 assert.equal(element.$.diff.layers[0], element.$.syntaxLayer);
1306 });
1307
1308 test('syntax layer should be disabled', () => {
1309 assert.isFalse(element.$.syntaxLayer.enabled);
1310 });
1311
1312 test('still disabled for large diff', () => {
1313 // Before it renders, set the first diff line to 500 '*' characters.
1314 element.diff = {
1315 content: [{
1316 a: [new Array(501).join('*')],
1317 }],
1318 };
1319 assert.isFalse(element.$.syntaxLayer.enabled);
1320 });
1321 });
1322
1323 suite('coverage layer', () => {
1324 let notifyStub;
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001325 let coverageProviderStub;
1326 const exampleRanges = [
1327 {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001328 type: CoverageType.COVERED,
1329 side: Side.RIGHT,
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001330 code_range: {
1331 start_line: 1,
1332 end_line: 2,
1333 },
1334 },
1335 {
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001336 type: CoverageType.NOT_COVERED,
1337 side: Side.RIGHT,
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001338 code_range: {
1339 start_line: 3,
1340 end_line: 4,
1341 },
1342 },
1343 ];
1344
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001345 setup(() => {
1346 notifyStub = sinon.stub();
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001347 coverageProviderStub = sinon.stub().returns(
1348 Promise.resolve(exampleRanges));
1349
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001350 stub('gr-js-api-interface', {
Ben Rohlfs65af06d2020-09-17 09:22:42 +02001351 getCoverageAnnotationApis() {
1352 return Promise.resolve([{
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001353 notify: notifyStub,
1354 getCoverageProvider() {
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001355 return coverageProviderStub;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001356 },
Ben Rohlfs65af06d2020-09-17 09:22:42 +02001357 }]);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001358 },
1359 });
Dmitrii Filippov06117e82020-06-25 13:26:55 +02001360 element = basicFixture.instantiate();
Ben Rohlfs1d487062020-09-26 11:26:03 +02001361 element.changeNum = 123;
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001362 element.change = createChange();
Ben Rohlfs1d487062020-09-26 11:26:03 +02001363 element.path = 'some/path';
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001364 const prefs = {
1365 line_length: 10,
1366 show_tabs: true,
1367 tab_size: 4,
1368 context: -1,
1369 };
1370 element.diff = {
1371 content: [{
1372 a: ['foo'],
1373 }],
1374 };
1375 element.patchRange = {};
1376 element.prefs = prefs;
1377 });
1378
Ben Rohlfs65af06d2020-09-17 09:22:42 +02001379 test('getCoverageAnnotationApis should be called', done => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001380 element.reload();
1381 flush(() => {
Ben Rohlfs65af06d2020-09-17 09:22:42 +02001382 assert.isTrue(element.$.jsAPI.getCoverageAnnotationApis.calledOnce);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001383 done();
1384 });
1385 });
1386
1387 test('coverageRangeChanged should be called', done => {
1388 element.reload();
1389 flush(() => {
1390 assert.equal(notifyStub.callCount, 2);
Dhruv Srivastavab223df22020-12-08 17:48:59 +01001391 assert.isTrue(notifyStub.calledWithExactly(
1392 'some/path', 1, 2, Side.RIGHT));
1393 assert.isTrue(notifyStub.calledWithExactly(
1394 'some/path', 3, 4, Side.RIGHT));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001395 done();
1396 });
1397 });
Malgorzata Salawa4acc5752020-12-08 13:55:49 +01001398
1399 test('provider is called with appropriate params', done => {
1400 element.patchRange.basePatchNum = 1;
1401 element.patchRange.patchNum = 3;
1402
1403 element.reload();
1404 flush(() => {
1405 assert.isTrue(coverageProviderStub.calledWithExactly(
1406 123, 'some/path', 1, 3, element.change));
1407 done();
1408 });
1409 });
1410
1411 test('provider is called with appropriate params - special patchset values',
1412 done => {
1413 element.patchRange.basePatchNum = 'PARENT';
1414 element.patchRange.patchNum = 'invalid';
1415
1416 element.reload();
1417 flush(() => {
1418 assert.isTrue(coverageProviderStub.calledWithExactly(
1419 123, 'some/path', undefined, undefined, element.change));
1420 done();
1421 });
1422 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001423 });
1424
1425 suite('trailing newlines', () => {
1426 setup(() => {
1427 });
1428
1429 suite('_lastChunkForSide', () => {
1430 test('deltas', () => {
1431 const diff = {content: [
1432 {a: ['foo', 'bar'], b: ['baz']},
1433 {ab: ['foo', 'bar', 'baz']},
1434 {b: ['foo']},
1435 ]};
1436 assert.equal(element._lastChunkForSide(diff, false), diff.content[2]);
1437 assert.equal(element._lastChunkForSide(diff, true), diff.content[1]);
1438
1439 diff.content.push({a: ['foo'], b: ['bar']});
1440 assert.equal(element._lastChunkForSide(diff, false), diff.content[3]);
1441 assert.equal(element._lastChunkForSide(diff, true), diff.content[3]);
1442 });
1443
1444 test('addition with a undefined', () => {
1445 const diff = {content: [
1446 {b: ['foo', 'bar', 'baz']},
1447 ]};
1448 assert.equal(element._lastChunkForSide(diff, false), diff.content[0]);
1449 assert.isNull(element._lastChunkForSide(diff, true));
1450 });
1451
1452 test('addition with a empty', () => {
1453 const diff = {content: [
1454 {a: [], b: ['foo', 'bar', 'baz']},
1455 ]};
1456 assert.equal(element._lastChunkForSide(diff, false), diff.content[0]);
1457 assert.isNull(element._lastChunkForSide(diff, true));
1458 });
1459
1460 test('deletion with b undefined', () => {
1461 const diff = {content: [
1462 {a: ['foo', 'bar', 'baz']},
1463 ]};
1464 assert.isNull(element._lastChunkForSide(diff, false));
1465 assert.equal(element._lastChunkForSide(diff, true), diff.content[0]);
1466 });
1467
1468 test('deletion with b empty', () => {
1469 const diff = {content: [
1470 {a: ['foo', 'bar', 'baz'], b: []},
1471 ]};
1472 assert.isNull(element._lastChunkForSide(diff, false));
1473 assert.equal(element._lastChunkForSide(diff, true), diff.content[0]);
1474 });
1475
1476 test('empty', () => {
1477 const diff = {content: []};
1478 assert.isNull(element._lastChunkForSide(diff, false));
1479 assert.isNull(element._lastChunkForSide(diff, true));
1480 });
1481 });
1482
1483 suite('_hasTrailingNewlines', () => {
1484 test('shared no trailing', () => {
1485 const diff = undefined;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001486 sinon.stub(element, '_lastChunkForSide')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001487 .returns({ab: ['foo', 'bar']});
1488 assert.isFalse(element._hasTrailingNewlines(diff, false));
1489 assert.isFalse(element._hasTrailingNewlines(diff, true));
1490 });
1491
1492 test('delta trailing in right', () => {
1493 const diff = undefined;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001494 sinon.stub(element, '_lastChunkForSide')
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001495 .returns({a: ['foo', 'bar'], b: ['baz', '']});
1496 assert.isTrue(element._hasTrailingNewlines(diff, false));
1497 assert.isFalse(element._hasTrailingNewlines(diff, true));
1498 });
1499
1500 test('addition', () => {
1501 const diff = undefined;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001502 sinon.stub(element, '_lastChunkForSide').callsFake((diff, leftSide) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001503 if (leftSide) { return null; }
1504 return {b: ['foo', '']};
1505 });
1506 assert.isTrue(element._hasTrailingNewlines(diff, false));
1507 assert.isNull(element._hasTrailingNewlines(diff, true));
1508 });
1509
1510 test('deletion', () => {
1511 const diff = undefined;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001512 sinon.stub(element, '_lastChunkForSide').callsFake((diff, leftSide) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001513 if (!leftSide) { return null; }
1514 return {a: ['foo']};
1515 });
1516 assert.isNull(element._hasTrailingNewlines(diff, false));
1517 assert.isFalse(element._hasTrailingNewlines(diff, true));
1518 });
1519 });
1520 });
1521});
Dmitrii Filippov06117e82020-06-25 13:26:55 +02001522