
These three events are just used to sync the model to reflect the changes. As nothing in gr-diff and descendents needs the comment model anymore, we can remove that property and instead do the updating in gr-diff-host, where we still need the comments model property to be kept in sync. This change removes the last dependency on the comment model from gr-diff and descendents, so they can now be reused indepedently of Gerrit's comment model. Change-Id: I9549ea640688006c099493c2156170d706a1c65c
970 lines
34 KiB
HTML
970 lines
34 KiB
HTML
<!DOCTYPE html>
|
||
<!--
|
||
@license
|
||
Copyright (C) 2015 The Android Open Source Project
|
||
|
||
Licensed under the Apache License, Version 2.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
-->
|
||
|
||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||
<title>gr-diff</title>
|
||
|
||
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||
<script src="../../../scripts/util.js"></script>
|
||
|
||
<link rel="import" href="../../shared/gr-rest-api-interface/mock-diff-response_test.html">
|
||
<link rel="import" href="gr-diff.html">
|
||
|
||
<script>void(0);</script>
|
||
|
||
<test-fixture id="basic">
|
||
<template>
|
||
<gr-diff></gr-diff>
|
||
</template>
|
||
</test-fixture>
|
||
|
||
<script>
|
||
suite('gr-diff tests', () => {
|
||
let element;
|
||
let sandbox;
|
||
|
||
setup(() => {
|
||
sandbox = sinon.sandbox.create();
|
||
});
|
||
|
||
teardown(() => {
|
||
sandbox.restore();
|
||
});
|
||
|
||
test('cancel', () => {
|
||
element = fixture('basic');
|
||
const cancelStub = sandbox.stub(element.$.diffBuilder, 'cancel');
|
||
element.cancel();
|
||
assert.isTrue(cancelStub.calledOnce);
|
||
});
|
||
|
||
test('line limit with line_wrapping', () => {
|
||
element = fixture('basic');
|
||
element.prefs = {line_wrapping: true, line_length: 80, tab_size: 2};
|
||
flushAsynchronousOperations();
|
||
assert.equal(element.customStyle['--line-limit'], '80ch');
|
||
});
|
||
|
||
test('line limit without line_wrapping', () => {
|
||
element = fixture('basic');
|
||
element.prefs = {line_wrapping: false, line_length: 80, tab_size: 2};
|
||
flushAsynchronousOperations();
|
||
assert.isNotOk(element.customStyle['--line-limit']);
|
||
});
|
||
|
||
suite('_get{PatchNum|IsParentComment}ByLineAndContent', () => {
|
||
let lineEl;
|
||
let contentEl;
|
||
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
lineEl = document.createElement('td');
|
||
contentEl = document.createElement('span');
|
||
});
|
||
|
||
suite('_getPatchNumByLineAndContent', () => {
|
||
test('right side', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
lineEl.classList.add('right');
|
||
assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl),
|
||
4);
|
||
});
|
||
|
||
test('left side parent by linenum', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
lineEl.classList.add('left');
|
||
assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl),
|
||
4);
|
||
});
|
||
|
||
test('left side parent by content', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
contentEl.classList.add('remove');
|
||
assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl),
|
||
4);
|
||
});
|
||
|
||
test('left side merge parent', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: -2};
|
||
contentEl.classList.add('remove');
|
||
assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl),
|
||
4);
|
||
});
|
||
|
||
test('left side non parent', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 3};
|
||
contentEl.classList.add('remove');
|
||
assert.equal(element._getPatchNumByLineAndContent(lineEl, contentEl),
|
||
3);
|
||
});
|
||
});
|
||
|
||
suite('_getIsParentCommentByLineAndContent', () => {
|
||
test('right side', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
lineEl.classList.add('right');
|
||
assert.isFalse(
|
||
element._getIsParentCommentByLineAndContent(lineEl, contentEl));
|
||
});
|
||
|
||
test('left side parent by linenum', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
lineEl.classList.add('left');
|
||
assert.isTrue(
|
||
element._getIsParentCommentByLineAndContent(lineEl, contentEl));
|
||
});
|
||
|
||
test('left side parent by content', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 'PARENT'};
|
||
contentEl.classList.add('remove');
|
||
assert.isTrue(
|
||
element._getIsParentCommentByLineAndContent(lineEl, contentEl));
|
||
});
|
||
|
||
test('left side merge parent', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: -2};
|
||
contentEl.classList.add('remove');
|
||
assert.isTrue(
|
||
element._getIsParentCommentByLineAndContent(lineEl, contentEl));
|
||
});
|
||
|
||
test('left side non parent', () => {
|
||
element.patchRange = {patchNum: 4, basePatchNum: 3};
|
||
contentEl.classList.add('remove');
|
||
assert.isFalse(
|
||
element._getIsParentCommentByLineAndContent(lineEl, contentEl));
|
||
});
|
||
});
|
||
});
|
||
|
||
suite('not logged in', () => {
|
||
setup(() => {
|
||
const getLoggedInPromise = Promise.resolve(false);
|
||
stub('gr-rest-api-interface', {
|
||
getLoggedIn() { return getLoggedInPromise; },
|
||
});
|
||
element = fixture('basic');
|
||
return getLoggedInPromise;
|
||
});
|
||
|
||
test('toggleLeftDiff', () => {
|
||
element.toggleLeftDiff();
|
||
assert.isTrue(element.classList.contains('no-left'));
|
||
element.toggleLeftDiff();
|
||
assert.isFalse(element.classList.contains('no-left'));
|
||
});
|
||
|
||
test('addDraftAtLine', () => {
|
||
sandbox.stub(element, '_selectLine');
|
||
const loggedInErrorSpy = sandbox.spy();
|
||
element.addEventListener('show-auth-required', loggedInErrorSpy);
|
||
element.addDraftAtLine();
|
||
assert.isTrue(loggedInErrorSpy.called);
|
||
});
|
||
|
||
test('view does not start with displayLine classList', () => {
|
||
assert.isFalse(
|
||
element.$$('.diffContainer').classList.contains('displayLine'));
|
||
});
|
||
|
||
test('displayLine class added called when displayLine is true', () => {
|
||
const spy = sandbox.spy(element, '_computeContainerClass');
|
||
element.displayLine = true;
|
||
assert.isTrue(spy.called);
|
||
assert.isTrue(
|
||
element.$$('.diffContainer').classList.contains('displayLine'));
|
||
});
|
||
|
||
test('thread groups', () => {
|
||
const contentEl = document.createElement('div');
|
||
|
||
element.changeNum = 123;
|
||
element.patchRange = {basePatchNum: 1, patchNum: 2};
|
||
element.path = 'file.txt';
|
||
|
||
const mock = document.createElement('mock-diff-response');
|
||
element.$.diffBuilder._builder = element.$.diffBuilder._getDiffBuilder(
|
||
mock.diffResponse, {tab_size: 2, line_length: 80});
|
||
|
||
// No thread groups.
|
||
assert.isNotOk(element._getThreadGroupForLine(contentEl));
|
||
|
||
// A thread group gets created.
|
||
const threadGroupEl = element._getOrCreateThreadGroup(contentEl);
|
||
assert.isOk(threadGroupEl);
|
||
|
||
// The new thread group can be fetched.
|
||
assert.isOk(element._getThreadGroupForLine(contentEl));
|
||
|
||
assert.equal(contentEl.querySelectorAll('.thread-group').length, 1);
|
||
});
|
||
|
||
suite('image diffs', () => {
|
||
let mockFile1;
|
||
let mockFile2;
|
||
setup(() => {
|
||
mockFile1 = {
|
||
body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
|
||
'wsAAAAAAAAAAAAAAAAA/w==',
|
||
type: 'image/bmp',
|
||
};
|
||
mockFile2 = {
|
||
body: 'Qk06AAAAAAAAADYAAAAoAAAAAQAAAP////8BACAAAAAAAAAAAAATCwAAE' +
|
||
'wsAAAAAAAAAAAAA/////w==',
|
||
type: 'image/bmp',
|
||
};
|
||
|
||
element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
|
||
element.isImageDiff = true;
|
||
element.prefs = {
|
||
auto_hide_diff_table_header: true,
|
||
context: 10,
|
||
cursor_blink_rate: 0,
|
||
font_size: 12,
|
||
ignore_whitespace: 'IGNORE_NONE',
|
||
intraline_difference: true,
|
||
line_length: 100,
|
||
line_wrapping: false,
|
||
show_line_endings: true,
|
||
show_tabs: true,
|
||
show_whitespace_errors: true,
|
||
syntax_highlighting: true,
|
||
tab_size: 8,
|
||
theme: 'DEFAULT',
|
||
};
|
||
});
|
||
|
||
test('renders image diffs with same file name', done => {
|
||
const rendered = () => {
|
||
// Recognizes that it should be an image diff.
|
||
assert.isTrue(element.isImageDiff);
|
||
assert.instanceOf(
|
||
element.$.diffBuilder._builder, GrDiffBuilderImage);
|
||
|
||
// Left image rendered with the parent commit's version of the file.
|
||
const leftImage = element.$.diffTable.querySelector('td.left img');
|
||
const leftLabel =
|
||
element.$.diffTable.querySelector('td.left label');
|
||
const leftLabelContent = leftLabel.querySelector('.label');
|
||
const leftLabelName = leftLabel.querySelector('.name');
|
||
|
||
const rightImage =
|
||
element.$.diffTable.querySelector('td.right img');
|
||
const rightLabel = element.$.diffTable.querySelector(
|
||
'td.right label');
|
||
const rightLabelContent = rightLabel.querySelector('.label');
|
||
const rightLabelName = rightLabel.querySelector('.name');
|
||
|
||
assert.isNotOk(rightLabelName);
|
||
assert.isNotOk(leftLabelName);
|
||
|
||
let leftLoaded = false;
|
||
let rightLoaded = false;
|
||
|
||
leftImage.addEventListener('load', () => {
|
||
assert.isOk(leftImage);
|
||
assert.equal(leftImage.getAttribute('src'),
|
||
'data:image/bmp;base64, ' + mockFile1.body);
|
||
assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
|
||
leftLoaded = true;
|
||
if (rightLoaded) {
|
||
element.removeEventListener('render', rendered);
|
||
done();
|
||
}
|
||
});
|
||
|
||
rightImage.addEventListener('load', () => {
|
||
assert.isOk(rightImage);
|
||
assert.equal(rightImage.getAttribute('src'),
|
||
'data:image/bmp;base64, ' + mockFile2.body);
|
||
assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
|
||
|
||
rightLoaded = true;
|
||
if (leftLoaded) {
|
||
element.removeEventListener('render', rendered);
|
||
done();
|
||
}
|
||
});
|
||
};
|
||
|
||
element.addEventListener('render', rendered);
|
||
|
||
element.baseImage = mockFile1;
|
||
element.revisionImage = mockFile2;
|
||
element.diff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
|
||
meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
intraline_status: 'OK',
|
||
change_type: 'MODIFIED',
|
||
diff_header: [
|
||
'diff --git a/carrot.jpg b/carrot.jpg',
|
||
'index 2adc47d..f9c2f2c 100644',
|
||
'--- a/carrot.jpg',
|
||
'+++ b/carrot.jpg',
|
||
'Binary files differ',
|
||
],
|
||
content: [{skip: 66}],
|
||
binary: true,
|
||
};
|
||
});
|
||
|
||
test('renders image diffs with a different file name', done => {
|
||
const mockDiff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
|
||
meta_b: {name: 'carrot2.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
intraline_status: 'OK',
|
||
change_type: 'MODIFIED',
|
||
diff_header: [
|
||
'diff --git a/carrot.jpg b/carrot2.jpg',
|
||
'index 2adc47d..f9c2f2c 100644',
|
||
'--- a/carrot.jpg',
|
||
'+++ b/carrot2.jpg',
|
||
'Binary files differ',
|
||
],
|
||
content: [{skip: 66}],
|
||
binary: true,
|
||
};
|
||
|
||
const rendered = () => {
|
||
// Recognizes that it should be an image diff.
|
||
assert.isTrue(element.isImageDiff);
|
||
assert.instanceOf(
|
||
element.$.diffBuilder._builder, GrDiffBuilderImage);
|
||
|
||
// Left image rendered with the parent commit's version of the file.
|
||
const leftImage = element.$.diffTable.querySelector('td.left img');
|
||
const leftLabel =
|
||
element.$.diffTable.querySelector('td.left label');
|
||
const leftLabelContent = leftLabel.querySelector('.label');
|
||
const leftLabelName = leftLabel.querySelector('.name');
|
||
|
||
const rightImage =
|
||
element.$.diffTable.querySelector('td.right img');
|
||
const rightLabel = element.$.diffTable.querySelector(
|
||
'td.right label');
|
||
const rightLabelContent = rightLabel.querySelector('.label');
|
||
const rightLabelName = rightLabel.querySelector('.name');
|
||
|
||
assert.isOk(rightLabelName);
|
||
assert.isOk(leftLabelName);
|
||
assert.equal(leftLabelName.textContent, mockDiff.meta_a.name);
|
||
assert.equal(rightLabelName.textContent, mockDiff.meta_b.name);
|
||
|
||
let leftLoaded = false;
|
||
let rightLoaded = false;
|
||
|
||
leftImage.addEventListener('load', () => {
|
||
assert.isOk(leftImage);
|
||
assert.equal(leftImage.getAttribute('src'),
|
||
'data:image/bmp;base64, ' + mockFile1.body);
|
||
assert.equal(leftLabelContent.textContent, '1×1 image/bmp');
|
||
leftLoaded = true;
|
||
if (rightLoaded) {
|
||
element.removeEventListener('render', rendered);
|
||
done();
|
||
}
|
||
});
|
||
|
||
rightImage.addEventListener('load', () => {
|
||
assert.isOk(rightImage);
|
||
assert.equal(rightImage.getAttribute('src'),
|
||
'data:image/bmp;base64, ' + mockFile2.body);
|
||
assert.equal(rightLabelContent.textContent, '1×1 image/bmp');
|
||
|
||
rightLoaded = true;
|
||
if (leftLoaded) {
|
||
element.removeEventListener('render', rendered);
|
||
done();
|
||
}
|
||
});
|
||
};
|
||
|
||
element.addEventListener('render', rendered);
|
||
|
||
element.baseImage = mockFile1;
|
||
element.baseImage._name = mockDiff.meta_a.name;
|
||
element.revisionImage = mockFile2;
|
||
element.revisionImage._name = mockDiff.meta_b.name;
|
||
element.diff = mockDiff;
|
||
});
|
||
|
||
test('renders added image', done => {
|
||
const mockDiff = {
|
||
meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
intraline_status: 'OK',
|
||
change_type: 'ADDED',
|
||
diff_header: [
|
||
'diff --git a/carrot.jpg b/carrot.jpg',
|
||
'index 0000000..f9c2f2c 100644',
|
||
'--- /dev/null',
|
||
'+++ b/carrot.jpg',
|
||
'Binary files differ',
|
||
],
|
||
content: [{skip: 66}],
|
||
binary: true,
|
||
};
|
||
|
||
element.addEventListener('render', () => {
|
||
// Recognizes that it should be an image diff.
|
||
assert.isTrue(element.isImageDiff);
|
||
assert.instanceOf(
|
||
element.$.diffBuilder._builder, GrDiffBuilderImage);
|
||
|
||
const leftImage = element.$.diffTable.querySelector('td.left img');
|
||
const rightImage = element.$.diffTable.querySelector('td.right img');
|
||
|
||
assert.isNotOk(leftImage);
|
||
assert.isOk(rightImage);
|
||
done();
|
||
});
|
||
|
||
element.revisionImage = mockFile2;
|
||
element.diff = mockDiff;
|
||
});
|
||
|
||
test('renders removed image', done => {
|
||
const mockDiff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
intraline_status: 'OK',
|
||
change_type: 'DELETED',
|
||
diff_header: [
|
||
'diff --git a/carrot.jpg b/carrot.jpg',
|
||
'index f9c2f2c..0000000 100644',
|
||
'--- a/carrot.jpg',
|
||
'+++ /dev/null',
|
||
'Binary files differ',
|
||
],
|
||
content: [{skip: 66}],
|
||
binary: true,
|
||
};
|
||
|
||
element.addEventListener('render', () => {
|
||
// Recognizes that it should be an image diff.
|
||
assert.isTrue(element.isImageDiff);
|
||
assert.instanceOf(
|
||
element.$.diffBuilder._builder, GrDiffBuilderImage);
|
||
|
||
const leftImage = element.$.diffTable.querySelector('td.left img');
|
||
const rightImage = element.$.diffTable.querySelector('td.right img');
|
||
|
||
assert.isOk(leftImage);
|
||
assert.isNotOk(rightImage);
|
||
done();
|
||
});
|
||
|
||
element.baseImage = mockFile1;
|
||
element.diff = mockDiff;
|
||
});
|
||
|
||
test('does not render disallowed image type', done => {
|
||
const mockDiff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg-evil',
|
||
lines: 560},
|
||
intraline_status: 'OK',
|
||
change_type: 'DELETED',
|
||
diff_header: [
|
||
'diff --git a/carrot.jpg b/carrot.jpg',
|
||
'index f9c2f2c..0000000 100644',
|
||
'--- a/carrot.jpg',
|
||
'+++ /dev/null',
|
||
'Binary files differ',
|
||
],
|
||
content: [{skip: 66}],
|
||
binary: true,
|
||
};
|
||
mockFile1.type = 'image/jpeg-evil';
|
||
|
||
element.addEventListener('render', () => {
|
||
// Recognizes that it should be an image diff.
|
||
assert.isTrue(element.isImageDiff);
|
||
assert.instanceOf(
|
||
element.$.diffBuilder._builder, GrDiffBuilderImage);
|
||
const leftImage = element.$.diffTable.querySelector('td.left img');
|
||
assert.isNotOk(leftImage);
|
||
done();
|
||
});
|
||
|
||
element.baseImage = mockFile1;
|
||
element.diff = mockDiff;
|
||
});
|
||
});
|
||
|
||
test('_handleTap lineNum', done => {
|
||
const addDraftStub = sandbox.stub(element, 'addDraftAtLine');
|
||
const el = document.createElement('div');
|
||
el.className = 'lineNum';
|
||
el.addEventListener('click', e => {
|
||
element._handleTap(e);
|
||
assert.isTrue(addDraftStub.called);
|
||
assert.equal(addDraftStub.lastCall.args[0], el);
|
||
done();
|
||
});
|
||
el.click();
|
||
});
|
||
|
||
test('_handleTap context', done => {
|
||
const showContextStub =
|
||
sandbox.stub(element.$.diffBuilder, 'showContext');
|
||
const el = document.createElement('div');
|
||
el.className = 'showContext';
|
||
el.addEventListener('click', e => {
|
||
element._handleTap(e);
|
||
assert.isTrue(showContextStub.called);
|
||
done();
|
||
});
|
||
el.click();
|
||
});
|
||
|
||
test('_handleTap content', done => {
|
||
const content = document.createElement('div');
|
||
const lineEl = document.createElement('div');
|
||
|
||
const selectStub = sandbox.stub(element, '_selectLine');
|
||
sandbox.stub(element.$.diffBuilder, 'getLineElByChild', () => lineEl);
|
||
|
||
content.className = 'content';
|
||
content.addEventListener('click', e => {
|
||
element._handleTap(e);
|
||
assert.isTrue(selectStub.called);
|
||
assert.equal(selectStub.lastCall.args[0], lineEl);
|
||
done();
|
||
});
|
||
content.click();
|
||
});
|
||
|
||
suite('getCursorStops', () => {
|
||
const setupDiff = function() {
|
||
const mock = document.createElement('mock-diff-response');
|
||
element.diff = mock.diffResponse;
|
||
element.prefs = {
|
||
context: 10,
|
||
tab_size: 8,
|
||
font_size: 12,
|
||
line_length: 100,
|
||
cursor_blink_rate: 0,
|
||
line_wrapping: false,
|
||
intraline_difference: true,
|
||
show_line_endings: true,
|
||
show_tabs: true,
|
||
show_whitespace_errors: true,
|
||
syntax_highlighting: true,
|
||
auto_hide_diff_table_header: true,
|
||
theme: 'DEFAULT',
|
||
ignore_whitespace: 'IGNORE_NONE',
|
||
};
|
||
|
||
element._renderDiffTable();
|
||
flushAsynchronousOperations();
|
||
};
|
||
|
||
test('getCursorStops returns [] when hidden and noAutoRender', () => {
|
||
element.noAutoRender = true;
|
||
setupDiff();
|
||
element.hidden = true;
|
||
assert.equal(element.getCursorStops().length, 0);
|
||
});
|
||
|
||
test('getCursorStops', () => {
|
||
setupDiff();
|
||
assert.equal(element.getCursorStops().length, 50);
|
||
});
|
||
});
|
||
|
||
test('adds .hiddenscroll', () => {
|
||
Gerrit.hiddenscroll = true;
|
||
element.displayLine = true;
|
||
assert.include(element.$$('.diffContainer').className, 'hiddenscroll');
|
||
});
|
||
});
|
||
|
||
suite('logged in', () => {
|
||
let fakeLineEl;
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
element.loggedIn = true;
|
||
element.patchRange = {};
|
||
|
||
fakeLineEl = {
|
||
getAttribute: sandbox.stub().returns(42),
|
||
classList: {
|
||
contains: sandbox.stub().returns(true),
|
||
},
|
||
};
|
||
});
|
||
|
||
test('addDraftAtLine', () => {
|
||
sandbox.stub(element, '_selectLine');
|
||
sandbox.stub(element, '_createComment');
|
||
element.addDraftAtLine(fakeLineEl);
|
||
assert.isTrue(element._createComment
|
||
.calledWithExactly(fakeLineEl, 42));
|
||
});
|
||
|
||
test('addDraftAtLine on an edit', () => {
|
||
element.patchRange.basePatchNum = element.EDIT_NAME;
|
||
sandbox.stub(element, '_selectLine');
|
||
sandbox.stub(element, '_createComment');
|
||
const alertSpy = sandbox.spy();
|
||
element.addEventListener('show-alert', alertSpy);
|
||
element.addDraftAtLine(fakeLineEl);
|
||
assert.isTrue(alertSpy.called);
|
||
assert.isFalse(element._createComment.called);
|
||
});
|
||
|
||
test('addDraftAtLine on an edit base', () => {
|
||
element.patchRange.patchNum = element.EDIT_NAME;
|
||
element.patchRange.basePatchNum = element.PARENT_NAME;
|
||
sandbox.stub(element, '_selectLine');
|
||
sandbox.stub(element, '_createComment');
|
||
const alertSpy = sandbox.spy();
|
||
element.addEventListener('show-alert', alertSpy);
|
||
element.addDraftAtLine(fakeLineEl);
|
||
assert.isTrue(alertSpy.called);
|
||
assert.isFalse(element._createComment.called);
|
||
});
|
||
|
||
suite('change in preferences', () => {
|
||
setup(() => {
|
||
element.diff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
|
||
meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
diff_header: [],
|
||
intraline_status: 'OK',
|
||
change_type: 'MODIFIED',
|
||
content: [{skip: 66}],
|
||
};
|
||
});
|
||
|
||
test('change in preferences re-renders diff', () => {
|
||
sandbox.stub(element, '_renderDiffTable');
|
||
element.prefs = {};
|
||
element.prefs = {time_format: 'HHMM_12'};
|
||
assert.isTrue(element._renderDiffTable.called);
|
||
});
|
||
|
||
test('change in preferences does not re-renders diff with ' +
|
||
'noRenderOnPrefsChange', () => {
|
||
sandbox.stub(element, '_renderDiffTable');
|
||
element.noRenderOnPrefsChange = true;
|
||
element.prefs = {};
|
||
element.prefs = {time_format: 'HHMM_12'};
|
||
assert.isFalse(element._renderDiffTable.called);
|
||
});
|
||
});
|
||
});
|
||
|
||
suite('diff header', () => {
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
element.diff = {
|
||
meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
|
||
meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
|
||
lines: 560},
|
||
diff_header: [],
|
||
intraline_status: 'OK',
|
||
change_type: 'MODIFIED',
|
||
content: [{skip: 66}],
|
||
};
|
||
});
|
||
|
||
test('hidden', () => {
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', 'diff --git a/test.jpg b/test.jpg');
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', 'index 2adc47d..f9c2f2c 100644');
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', '--- a/test.jpg');
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', '+++ b/test.jpg');
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', 'test');
|
||
assert.equal(element._diffHeaderItems.length, 1);
|
||
flushAsynchronousOperations();
|
||
|
||
assert.equal(element.$.diffHeader.textContent.trim(), 'test');
|
||
});
|
||
|
||
test('binary files', () => {
|
||
element.diff.binary = true;
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', 'diff --git a/test.jpg b/test.jpg');
|
||
assert.equal(element._diffHeaderItems.length, 0);
|
||
element.push('diff.diff_header', 'test');
|
||
assert.equal(element._diffHeaderItems.length, 1);
|
||
element.push('diff.diff_header', 'Binary files differ');
|
||
assert.equal(element._diffHeaderItems.length, 1);
|
||
});
|
||
});
|
||
|
||
suite('safety and bypass', () => {
|
||
let renderStub;
|
||
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
renderStub = sandbox.stub(element.$.diffBuilder, 'render',
|
||
() => {
|
||
Promise.resolve();
|
||
element.$.diffBuilder.dispatchEvent(
|
||
new CustomEvent('render', {bubbles: true}));
|
||
});
|
||
const mock = document.createElement('mock-diff-response');
|
||
sandbox.stub(element.$.diffBuilder, 'getDiffLength').returns(10000);
|
||
element.diff = mock.diffResponse;
|
||
element.noRenderOnPrefsChange = true;
|
||
});
|
||
|
||
test('large render w/ context = 10', done => {
|
||
element.prefs = {context: 10};
|
||
element.addEventListener('render', () => {
|
||
assert.isTrue(renderStub.called);
|
||
assert.isFalse(element._showWarning);
|
||
done();
|
||
});
|
||
element._renderDiffTable();
|
||
});
|
||
|
||
test('large render w/ whole file and bypass', done => {
|
||
element.prefs = {context: -1};
|
||
element._safetyBypass = 10;
|
||
element.addEventListener('render', () => {
|
||
assert.isTrue(renderStub.called);
|
||
assert.isFalse(element._showWarning);
|
||
done();
|
||
});
|
||
element._renderDiffTable();
|
||
});
|
||
|
||
test('large render w/ whole file and no bypass', done => {
|
||
element.prefs = {context: -1};
|
||
element.addEventListener('render', () => {
|
||
assert.isFalse(renderStub.called);
|
||
assert.isTrue(element._showWarning);
|
||
done();
|
||
});
|
||
element._renderDiffTable();
|
||
});
|
||
});
|
||
|
||
suite('blame', () => {
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
});
|
||
|
||
test('unsetting', () => {
|
||
element.blame = [];
|
||
const setBlameSpy = sandbox.spy(element.$.diffBuilder, 'setBlame');
|
||
element.classList.add('showBlame');
|
||
element.blame = null;
|
||
assert.isTrue(setBlameSpy.calledWithExactly(null));
|
||
assert.isFalse(element.classList.contains('showBlame'));
|
||
});
|
||
|
||
test('setting', () => {
|
||
const mockBlame = [{id: 'commit id', ranges: [{start: 1, end: 2}]}];
|
||
element.blame = mockBlame;
|
||
assert.isTrue(element.classList.contains('showBlame'));
|
||
});
|
||
});
|
||
|
||
suite('trailing newlines', () => {
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
});
|
||
|
||
suite('_lastChunkForSide', () => {
|
||
test('deltas', () => {
|
||
const diff = {content: [
|
||
{a: ['foo', 'bar'], b: ['baz']},
|
||
{ab: ['foo', 'bar', 'baz']},
|
||
{b: ['foo']},
|
||
]};
|
||
assert.equal(element._lastChunkForSide(diff, false), diff.content[2]);
|
||
assert.equal(element._lastChunkForSide(diff, true), diff.content[1]);
|
||
|
||
diff.content.push({a: ['foo'], b: ['bar']});
|
||
assert.equal(element._lastChunkForSide(diff, false), diff.content[3]);
|
||
assert.equal(element._lastChunkForSide(diff, true), diff.content[3]);
|
||
});
|
||
|
||
test('addition', () => {
|
||
const diff = {content: [
|
||
{b: ['foo', 'bar', 'baz']},
|
||
]};
|
||
assert.equal(element._lastChunkForSide(diff, false), diff.content[0]);
|
||
assert.isNull(element._lastChunkForSide(diff, true));
|
||
});
|
||
|
||
test('deletion', () => {
|
||
const diff = {content: [
|
||
{a: ['foo', 'bar', 'baz']},
|
||
]};
|
||
assert.isNull(element._lastChunkForSide(diff, false));
|
||
assert.equal(element._lastChunkForSide(diff, true), diff.content[0]);
|
||
});
|
||
|
||
test('empty', () => {
|
||
const diff = {content: []};
|
||
assert.isNull(element._lastChunkForSide(diff, false));
|
||
assert.isNull(element._lastChunkForSide(diff, true));
|
||
});
|
||
});
|
||
|
||
suite('_hasTrailingNewlines', () => {
|
||
test('shared no trailing', () => {
|
||
const diff = undefined;
|
||
sandbox.stub(element, '_lastChunkForSide')
|
||
.returns({ab: ['foo', 'bar']});
|
||
assert.isFalse(element._hasTrailingNewlines(diff, false));
|
||
assert.isFalse(element._hasTrailingNewlines(diff, true));
|
||
});
|
||
|
||
test('delta trailing in right', () => {
|
||
const diff = undefined;
|
||
sandbox.stub(element, '_lastChunkForSide')
|
||
.returns({a: ['foo', 'bar'], b: ['baz', '']});
|
||
assert.isTrue(element._hasTrailingNewlines(diff, false));
|
||
assert.isFalse(element._hasTrailingNewlines(diff, true));
|
||
});
|
||
|
||
test('addition', () => {
|
||
const diff = undefined;
|
||
sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => {
|
||
if (leftSide) { return null; }
|
||
return {b: ['foo', '']};
|
||
});
|
||
assert.isTrue(element._hasTrailingNewlines(diff, false));
|
||
assert.isNull(element._hasTrailingNewlines(diff, true));
|
||
});
|
||
|
||
test('deletion', () => {
|
||
const diff = undefined;
|
||
sandbox.stub(element, '_lastChunkForSide', (diff, leftSide) => {
|
||
if (!leftSide) { return null; }
|
||
return {a: ['foo']};
|
||
});
|
||
assert.isNull(element._hasTrailingNewlines(diff, false));
|
||
assert.isFalse(element._hasTrailingNewlines(diff, true));
|
||
});
|
||
});
|
||
|
||
test('_computeNewlineWarning', () => {
|
||
const NO_NEWLINE_BASE = 'No newline at end of base file.';
|
||
const NO_NEWLINE_REVISION = 'No newline at end of revision file.';
|
||
|
||
let hasLeft;
|
||
let hasRight;
|
||
sandbox.stub(element, '_hasTrailingNewlines', (diff, left) => {
|
||
if (left) { return hasLeft; }
|
||
return hasRight;
|
||
});
|
||
const diff = undefined;
|
||
|
||
// The revision has a trailing newline, but the base doesn't.
|
||
hasLeft = true;
|
||
hasRight = false;
|
||
assert.equal(element._computeNewlineWarning(diff), NO_NEWLINE_REVISION);
|
||
|
||
// Trailing newlines were undetermined in the revision.
|
||
hasLeft = true;
|
||
hasRight = null;
|
||
assert.isNull(element._computeNewlineWarning(diff));
|
||
|
||
// Missing trailing newlines in the base.
|
||
hasLeft = false;
|
||
hasRight = null;
|
||
assert.equal(element._computeNewlineWarning(diff), NO_NEWLINE_BASE);
|
||
|
||
// Missing trailing newlines in both.
|
||
hasLeft = false;
|
||
hasRight = false;
|
||
assert.equal(element._computeNewlineWarning(diff),
|
||
NO_NEWLINE_BASE + ' — ' + NO_NEWLINE_REVISION);
|
||
});
|
||
|
||
test('_computeNewlineWarningClass', () => {
|
||
const hidden = 'newlineWarning hidden';
|
||
const shown = 'newlineWarning';
|
||
assert.equal(element._computeNewlineWarningClass(null, true), hidden);
|
||
assert.equal(element._computeNewlineWarningClass('foo', true), hidden);
|
||
assert.equal(element._computeNewlineWarningClass(null, false), hidden);
|
||
assert.equal(element._computeNewlineWarningClass('foo', false), shown);
|
||
});
|
||
});
|
||
|
||
suite('key locations', () => {
|
||
let renderStub;
|
||
|
||
setup(() => {
|
||
element = fixture('basic');
|
||
element.prefs = {};
|
||
renderStub = sandbox.stub(element.$.diffBuilder, 'render');
|
||
});
|
||
|
||
test('lineOfInterest is a key location', () => {
|
||
element.lineOfInterest = {number: 789, leftSide: true};
|
||
element._renderDiffTable();
|
||
assert.isTrue(renderStub.called);
|
||
assert.deepEqual(renderStub.lastCall.args[0], {
|
||
left: {789: true},
|
||
right: {},
|
||
});
|
||
});
|
||
|
||
test('line comments are key locations', () => {
|
||
const threadEl = document.createElement('div');
|
||
threadEl.className = 'comment-thread';
|
||
threadEl.setAttribute('comment-side', 'right');
|
||
threadEl.setAttribute('line-num', 3);
|
||
Polymer.dom(element).appendChild(threadEl);
|
||
Polymer.dom.flush();
|
||
|
||
element._renderDiffTable();
|
||
assert.isTrue(renderStub.called);
|
||
assert.deepEqual(renderStub.lastCall.args[0], {
|
||
left: {},
|
||
right: {3: true},
|
||
});
|
||
});
|
||
|
||
test('file comments are key locations', () => {
|
||
const threadEl = document.createElement('div');
|
||
threadEl.className = 'comment-thread';
|
||
threadEl.setAttribute('comment-side', 'left');
|
||
Polymer.dom(element).appendChild(threadEl);
|
||
Polymer.dom.flush();
|
||
|
||
element._renderDiffTable();
|
||
assert.isTrue(renderStub.called);
|
||
assert.deepEqual(renderStub.lastCall.args[0], {
|
||
left: {FILE: true},
|
||
right: {},
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
a11ySuite('basic');
|
||
</script>
|