
Done for clarity and differentiation with `editPatchsetLoaded`. Bug: Issue 4437 Change-Id: I05432b202921cad7f906a1cbe9ed68aaeac164cb
902 lines
33 KiB
HTML
902 lines
33 KiB
HTML
<!DOCTYPE html>
|
|
<!--
|
|
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-view</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="../../../bower_components/page/page.js"></script>
|
|
<script src="../../../scripts/util.js"></script>
|
|
|
|
<link rel="import" href="gr-diff-view.html">
|
|
|
|
<script>void(0);</script>
|
|
|
|
<test-fixture id="basic">
|
|
<template>
|
|
<gr-diff-view></gr-diff-view>
|
|
</template>
|
|
</test-fixture>
|
|
|
|
<test-fixture id="blank">
|
|
<template>
|
|
<div></div>
|
|
</template>
|
|
</test-fixture>
|
|
|
|
<script>
|
|
suite('gr-diff-view tests', () => {
|
|
let element;
|
|
let sandbox;
|
|
|
|
const PARENT = 'PARENT';
|
|
|
|
setup(() => {
|
|
sandbox = sinon.sandbox.create();
|
|
|
|
stub('gr-rest-api-interface', {
|
|
getConfig() { return Promise.resolve({change: {}}); },
|
|
getLoggedIn() { return Promise.resolve(false); },
|
|
getProjectConfig() { return Promise.resolve({}); },
|
|
getDiffChangeDetail() { return Promise.resolve({}); },
|
|
getChangeFiles() { return Promise.resolve({}); },
|
|
saveFileReviewed() { return Promise.resolve(); },
|
|
getDiffComments() { return Promise.resolve({}); },
|
|
getDiffRobotComments() { return Promise.resolve({}); },
|
|
getDiffDrafts() { return Promise.resolve({}); },
|
|
});
|
|
element = fixture('basic');
|
|
return element._loadComments();
|
|
});
|
|
|
|
teardown(() => {
|
|
sandbox.restore();
|
|
});
|
|
|
|
test('toggle left diff with a hotkey', () => {
|
|
const toggleLeftDiffStub = sandbox.stub(element.$.diff, 'toggleLeftDiff');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a');
|
|
assert.isTrue(toggleLeftDiffStub.calledOnce);
|
|
});
|
|
|
|
test('keyboard shortcuts', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: '10',
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
revisions: {
|
|
a: {_number: 10, commit: {parents: []}},
|
|
},
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
element.changeViewState.selectedFileIndex = 1;
|
|
|
|
const diffNavStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
|
|
const changeNavStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
|
|
assert(changeNavStub.lastCall.calledWith(element._change),
|
|
'Should navigate to /c/42/');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 221, null, ']');
|
|
assert(diffNavStub.lastCall.calledWith(element._change, 'wheatley.md',
|
|
'10', PARENT), 'Should navigate to /c/42/10/wheatley.md');
|
|
element._path = 'wheatley.md';
|
|
assert.equal(element.changeViewState.selectedFileIndex, 2);
|
|
assert.isTrue(element._loading);
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(diffNavStub.lastCall.calledWith(element._change, 'glados.txt',
|
|
'10', PARENT), 'Should navigate to /c/42/10/glados.txt');
|
|
element._path = 'glados.txt';
|
|
assert.equal(element.changeViewState.selectedFileIndex, 1);
|
|
assert.isTrue(element._loading);
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(diffNavStub.lastCall.calledWith(element._change, 'chell.go', '10',
|
|
PARENT), 'Should navigate to /c/42/10/chell.go');
|
|
element._path = 'chell.go';
|
|
assert.equal(element.changeViewState.selectedFileIndex, 0);
|
|
assert.isTrue(element._loading);
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(changeNavStub.lastCall.calledWith(element._change),
|
|
'Should navigate to /c/42/');
|
|
assert.equal(element.changeViewState.selectedFileIndex, 0);
|
|
assert.isTrue(element._loading);
|
|
|
|
const showPrefsStub =
|
|
sandbox.stub(element.$.diffPreferences.$.prefsOverlay, 'open',
|
|
() => Promise.resolve());
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
|
assert(showPrefsStub.calledOnce);
|
|
|
|
let scrollStub = sandbox.stub(element.$.cursor, 'moveToNextChunk');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 78, null, 'n');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sandbox.stub(element.$.cursor, 'moveToPreviousChunk');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 80, null, 'p');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sandbox.stub(element.$.cursor, 'moveToNextCommentThread');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 78, 'shift', 'n');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sandbox.stub(element.$.cursor,
|
|
'moveToPreviousCommentThread');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 80, 'shift', 'p');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
const computeContainerClassStub = sandbox.stub(element.$.diff,
|
|
'_computeContainerClass');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 74, null, 'j');
|
|
assert(computeContainerClassStub.lastCall.calledWithExactly(
|
|
false, 'SIDE_BY_SIDE', true));
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 27, null, 'esc');
|
|
assert(computeContainerClassStub.lastCall.calledWithExactly(
|
|
false, 'SIDE_BY_SIDE', false));
|
|
});
|
|
|
|
test('keyboard shortcuts with patch range', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: '5',
|
|
patchNum: '10',
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
revisions: {
|
|
a: {_number: 10, commit: {parents: []}},
|
|
b: {_number: 5, commit: {parents: []}},
|
|
},
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
|
|
const diffNavStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
|
|
const changeNavStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
|
assert.isTrue(changeNavStub.notCalled, 'The `a` keyboard shortcut ' +
|
|
'should only work when the user is logged in.');
|
|
assert.isNull(window.sessionStorage.getItem(
|
|
'changeView.showReplyDialog'));
|
|
|
|
element._loggedIn = true;
|
|
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
|
assert.isTrue(element.changeViewState.showReplyDialog);
|
|
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '10',
|
|
'5'), 'Should navigate to /c/42/5..10');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '10',
|
|
'5'), 'Should navigate to /c/42/5..10');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 221, null, ']');
|
|
assert.isTrue(element._loading);
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
|
'wheatley.md', '10', '5'),
|
|
'Should navigate to /c/42/5..10/wheatley.md');
|
|
element._path = 'wheatley.md';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert.isTrue(element._loading);
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
|
'glados.txt', '10', '5'),
|
|
'Should navigate to /c/42/5..10/glados.txt');
|
|
element._path = 'glados.txt';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert.isTrue(element._loading);
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change, 'chell.go',
|
|
'10', '5'),
|
|
'Should navigate to /c/42/5..10/chell.go');
|
|
element._path = 'chell.go';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert.isTrue(element._loading);
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '10',
|
|
'5'),
|
|
'Should navigate to /c/42/5..10');
|
|
});
|
|
|
|
test('keyboard shortcuts with old patch number', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: '1',
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
revisions: {
|
|
a: {_number: 1, commit: {parents: []}},
|
|
b: {_number: 2, commit: {parents: []}},
|
|
},
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
|
|
const diffNavStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
|
|
const changeNavStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
|
assert.isTrue(changeNavStub.notCalled, 'The `a` keyboard shortcut ' +
|
|
'should only work when the user is logged in.');
|
|
assert.isNull(window.sessionStorage.getItem(
|
|
'changeView.showReplyDialog'));
|
|
|
|
element._loggedIn = true;
|
|
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
|
assert.isTrue(element.changeViewState.showReplyDialog);
|
|
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '1',
|
|
PARENT), 'Should navigate to /c/42/1');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '1',
|
|
PARENT), 'Should navigate to /c/42/1');
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 221, null, ']');
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
|
'wheatley.md', '1', PARENT),
|
|
'Should navigate to /c/42/1/wheatley.md');
|
|
element._path = 'wheatley.md';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
|
'glados.txt', '1', PARENT),
|
|
'Should navigate to /c/42/1/glados.txt');
|
|
element._path = 'glados.txt';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(diffNavStub.lastCall.calledWithExactly(element._change, 'chell.go',
|
|
'1', PARENT), 'Should navigate to /c/42/1/chell.go');
|
|
element._path = 'chell.go';
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, '1',
|
|
PARENT), 'Should navigate to /c/42/1');
|
|
});
|
|
|
|
test('Diff preferences hidden when no prefs or logged out', () => {
|
|
element._loggedIn = false;
|
|
flushAsynchronousOperations();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = true;
|
|
flushAsynchronousOperations();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = false;
|
|
element._prefs = {font_size: '12'};
|
|
flushAsynchronousOperations();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = true;
|
|
flushAsynchronousOperations();
|
|
assert.isFalse(element.$.diffPrefsContainer.hidden);
|
|
});
|
|
|
|
test('prefsButton opens gr-diff-preferences', () => {
|
|
const handlePrefsTapSpy = sandbox.spy(element, '_handlePrefsTap');
|
|
const overlayOpenStub = sandbox.stub(element.$.diffPreferences,
|
|
'open');
|
|
const prefsButton =
|
|
Polymer.dom(element.root).querySelector('.prefsButton');
|
|
|
|
MockInteractions.tap(prefsButton);
|
|
|
|
assert.isTrue(handlePrefsTapSpy.called);
|
|
assert.isTrue(overlayOpenStub.called);
|
|
});
|
|
|
|
test('_computeCommentString', done => {
|
|
loadCommentSpy = sandbox.spy(element.$.commentAPI, 'loadAll');
|
|
const path = '/test';
|
|
element.$.commentAPI.loadAll().then(comments => {
|
|
const commentCountStub =
|
|
sandbox.stub(comments, 'computeCommentCount');
|
|
const unresolvedCountStub =
|
|
sandbox.stub(comments, 'computeUnresolvedNum');
|
|
commentCountStub.withArgs(1, path).returns(0);
|
|
commentCountStub.withArgs(2, path).returns(1);
|
|
commentCountStub.withArgs(3, path).returns(2);
|
|
commentCountStub.withArgs(4, path).returns(0);
|
|
unresolvedCountStub.withArgs(1, path).returns(1);
|
|
unresolvedCountStub.withArgs(2, path).returns(0);
|
|
unresolvedCountStub.withArgs(3, path).returns(2);
|
|
unresolvedCountStub.withArgs(4, path).returns(0);
|
|
|
|
assert.equal(element._computeCommentString(comments, 1, path),
|
|
'1 unresolved');
|
|
assert.equal(element._computeCommentString(comments, 2, path),
|
|
'1 comment');
|
|
assert.equal(element._computeCommentString(comments, 3, path),
|
|
'2 comments, 2 unresolved');
|
|
assert.equal(element._computeCommentString(comments, 4, path), '');
|
|
done();
|
|
});
|
|
});
|
|
|
|
suite('url params', () => {
|
|
setup(() => {
|
|
sandbox.stub(Gerrit.Nav, 'getUrlForDiff', (c, p, pn, bpn) => {
|
|
return `${c._number}-${p}-${pn}-${bpn}`;
|
|
});
|
|
sandbox.stub(Gerrit.Nav, 'getUrlForChange', (c, pn, bpn) => {
|
|
return `${c._number}-${pn}-${bpn}`;
|
|
});
|
|
});
|
|
|
|
test('_formattedFiles', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: '10',
|
|
};
|
|
element._change = {_number: 42};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md',
|
|
'/COMMIT_MSG', '/MERGE_LIST'];
|
|
element._path = 'glados.txt';
|
|
const expectedFormattedFiles = [
|
|
{
|
|
text: 'chell.go',
|
|
mobileText: 'chell.go',
|
|
value: 'chell.go',
|
|
bottomText: '',
|
|
}, {
|
|
text: 'glados.txt',
|
|
mobileText: 'glados.txt',
|
|
value: 'glados.txt',
|
|
bottomText: '',
|
|
}, {
|
|
text: 'wheatley.md',
|
|
mobileText: 'wheatley.md',
|
|
value: 'wheatley.md',
|
|
bottomText: '',
|
|
},
|
|
{
|
|
text: 'Commit message',
|
|
mobileText: 'Commit message',
|
|
value: '/COMMIT_MSG',
|
|
bottomText: '',
|
|
},
|
|
{
|
|
text: 'Merge list',
|
|
mobileText: 'Merge list',
|
|
value: '/MERGE_LIST',
|
|
bottomText: '',
|
|
},
|
|
];
|
|
|
|
assert.deepEqual(element._formattedFiles, expectedFormattedFiles);
|
|
assert.equal(element._formattedFiles[1].value, element._path);
|
|
});
|
|
|
|
test('prev/up/next links', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: '10',
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
revisions: {
|
|
a: {_number: 10, commit: {parents: []}},
|
|
},
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
flushAsynchronousOperations();
|
|
const linkEls = Polymer.dom(element.root).querySelectorAll('.navLink');
|
|
assert.equal(linkEls.length, 3);
|
|
assert.equal(linkEls[0].getAttribute('href'), '42-chell.go-10-PARENT');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-undefined-undefined');
|
|
assert.equal(linkEls[2].getAttribute('href'),
|
|
'42-wheatley.md-10-PARENT');
|
|
element._path = 'wheatley.md';
|
|
flushAsynchronousOperations();
|
|
assert.equal(linkEls[0].getAttribute('href'),
|
|
'42-glados.txt-10-PARENT');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-undefined-undefined');
|
|
assert.isFalse(linkEls[2].hasAttribute('href'));
|
|
element._path = 'chell.go';
|
|
flushAsynchronousOperations();
|
|
assert.isFalse(linkEls[0].hasAttribute('href'));
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-undefined-undefined');
|
|
assert.equal(linkEls[2].getAttribute('href'),
|
|
'42-glados.txt-10-PARENT');
|
|
element._path = 'not_a_real_file';
|
|
flushAsynchronousOperations();
|
|
assert.equal(linkEls[0].getAttribute('href'),
|
|
'42-wheatley.md-10-PARENT');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-undefined-undefined');
|
|
assert.equal(linkEls[2].getAttribute('href'), '42-chell.go-10-PARENT');
|
|
});
|
|
|
|
test('prev/up/next links with patch range', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: '5',
|
|
patchNum: '10',
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
revisions: {
|
|
a: {_number: 5, commit: {parents: []}},
|
|
b: {_number: 10, commit: {parents: []}},
|
|
},
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
flushAsynchronousOperations();
|
|
const linkEls = Polymer.dom(element.root).querySelectorAll('.navLink');
|
|
assert.equal(linkEls.length, 3);
|
|
assert.equal(linkEls[0].getAttribute('href'), '42-chell.go-10-5');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-10-5');
|
|
assert.equal(linkEls[2].getAttribute('href'), '42-wheatley.md-10-5');
|
|
element._path = 'wheatley.md';
|
|
flushAsynchronousOperations();
|
|
assert.equal(linkEls[0].getAttribute('href'), '42-glados.txt-10-5');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-10-5');
|
|
assert.isFalse(linkEls[2].hasAttribute('href'));
|
|
element._path = 'chell.go';
|
|
flushAsynchronousOperations();
|
|
assert.isFalse(linkEls[0].hasAttribute('href'));
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-10-5');
|
|
assert.equal(linkEls[2].getAttribute('href'), '42-glados.txt-10-5');
|
|
});
|
|
});
|
|
|
|
test('_handlePatchChange calls navigateToDiff correctly', () => {
|
|
const navigateStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
|
|
element._change = {_number: 321, project: 'foo/bar'};
|
|
element._path = 'path/to/file.txt';
|
|
|
|
element._patchRange = {
|
|
basePatchNum: 'PARENT',
|
|
patchNum: '3',
|
|
};
|
|
|
|
const detail = {
|
|
basePatchNum: 'PARENT',
|
|
patchNum: '1',
|
|
};
|
|
|
|
element.$.rangeSelect.dispatchEvent(
|
|
new CustomEvent('patch-range-change', {detail, bubbles: false}));
|
|
|
|
assert(navigateStub.lastCall.calledWithExactly(element._change,
|
|
element._path, '1', 'PARENT'));
|
|
});
|
|
|
|
test('download link', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: '10',
|
|
};
|
|
element._fileList = ['chell.go', 'glados.txt', 'wheatley.md'];
|
|
element._path = 'glados.txt';
|
|
flushAsynchronousOperations();
|
|
const link = element.$$('.downloadLink');
|
|
assert.equal(link.getAttribute('href'),
|
|
'/changes/42/revisions/10/patch?zip&path=glados.txt');
|
|
assert.isTrue(link.hasAttribute('download'));
|
|
});
|
|
|
|
test('file review status', () => {
|
|
const saveReviewedStub = sandbox.stub(element, '_saveReviewedState',
|
|
() => Promise.resolve());
|
|
sandbox.stub(element.$.diff, 'reload');
|
|
|
|
element._loggedIn = true;
|
|
element.params = {
|
|
view: Gerrit.Nav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: '2',
|
|
basePatchNum: '1',
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
flushAsynchronousOperations();
|
|
|
|
const commitMsg = Polymer.dom(element.root).querySelector(
|
|
'input[type="checkbox"]');
|
|
|
|
assert.isTrue(commitMsg.checked);
|
|
MockInteractions.tap(commitMsg);
|
|
assert.isFalse(commitMsg.checked);
|
|
assert.isTrue(saveReviewedStub.lastCall.calledWithExactly(false));
|
|
|
|
MockInteractions.tap(commitMsg);
|
|
assert.isTrue(commitMsg.checked);
|
|
assert.isTrue(saveReviewedStub.lastCall.calledWithExactly(true));
|
|
const callCount = saveReviewedStub.callCount;
|
|
|
|
element.set('params.view', Gerrit.Nav.View.CHANGE);
|
|
flushAsynchronousOperations();
|
|
|
|
// saveReviewedState observer observes params, but should not fire when
|
|
// view !== Gerrit.Nav.View.DIFF.
|
|
assert.equal(saveReviewedStub.callCount, callCount);
|
|
});
|
|
|
|
test('file review status with edit loaded', () => {
|
|
const saveReviewedStub = sandbox.stub(element, '_saveReviewedState');
|
|
|
|
element._patchRange = {patchNum: element.EDIT_NAME};
|
|
flushAsynchronousOperations();
|
|
|
|
assert.isTrue(element._editMode);
|
|
element._setReviewed();
|
|
assert.isFalse(saveReviewedStub.called);
|
|
});
|
|
|
|
test('hash is determined from params', done => {
|
|
sandbox.stub(element.$.diff, 'reload');
|
|
sandbox.stub(element, '_initCursor');
|
|
|
|
element._loggedIn = true;
|
|
element.params = {
|
|
view: Gerrit.Nav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: '2',
|
|
basePatchNum: '1',
|
|
path: '/COMMIT_MSG',
|
|
hash: 10,
|
|
};
|
|
|
|
flush(() => {
|
|
assert.isTrue(element._initCursor.calledOnce);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('diff mode selector correctly toggles the diff', () => {
|
|
const select = element.$.modeSelect;
|
|
const diffDisplay = element.$.diff;
|
|
element._userPrefs = {default_diff_view: 'SIDE_BY_SIDE'};
|
|
|
|
// The mode selected in the view state reflects the selected option.
|
|
assert.equal(element._getDiffViewMode(), select.nativeSelect.value);
|
|
|
|
// The mode selected in the view state reflects the view rednered in the
|
|
// diff.
|
|
assert.equal(select.nativeSelect.value, diffDisplay.viewMode);
|
|
|
|
// We will simulate a user change of the selected mode.
|
|
const newMode = 'UNIFIED_DIFF';
|
|
// Set the actual value of the select, and simulate the change event.
|
|
select.nativeSelect.value = newMode;
|
|
element.fire('change', {}, {node: select.nativeSelect});
|
|
|
|
// Make sure the handler was called and the state is still coherent.
|
|
assert.equal(element._getDiffViewMode(), newMode);
|
|
assert.equal(element._getDiffViewMode(), select.nativeSelect.value);
|
|
assert.equal(element._getDiffViewMode(), diffDisplay.viewMode);
|
|
});
|
|
|
|
test('diff mode selector initializes from preferences', () => {
|
|
let resolvePrefs;
|
|
const prefsPromise = new Promise(resolve => {
|
|
resolvePrefs = resolve;
|
|
});
|
|
sandbox.stub(element.$.restAPI, 'getPreferences', () => prefsPromise);
|
|
|
|
// Attach a new gr-diff-view so we can intercept the preferences fetch.
|
|
const view = document.createElement('gr-diff-view');
|
|
const select = view.$.modeSelect;
|
|
fixture('blank').appendChild(view);
|
|
flushAsynchronousOperations();
|
|
|
|
// At this point the diff mode doesn't yet have the user's preference.
|
|
assert.equal(select.nativeSelect.value, 'SIDE_BY_SIDE');
|
|
|
|
// Receive the overriding preference.
|
|
resolvePrefs({default_diff_view: 'UNIFIED'});
|
|
flushAsynchronousOperations();
|
|
assert.equal(select.nativeSelect.value, 'SIDE_BY_SIDE');
|
|
});
|
|
|
|
test('_initCursor', () => {
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Does nothing when params specify no cursor address:
|
|
element._initCursor({});
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Does nothing when params specify side but no number:
|
|
element._initCursor({leftSide: true});
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Revision hash: specifies lineNum but not side.
|
|
element._initCursor({lineNum: 234});
|
|
assert.equal(element.$.cursor.initialLineNumber, 234);
|
|
assert.equal(element.$.cursor.side, 'right');
|
|
|
|
// Base hash: specifies lineNum and side.
|
|
element._initCursor({leftSide: true, lineNum: 345});
|
|
assert.equal(element.$.cursor.initialLineNumber, 345);
|
|
assert.equal(element.$.cursor.side, 'left');
|
|
|
|
// Specifies right side:
|
|
element._initCursor({leftSide: false, lineNum: 123});
|
|
assert.equal(element.$.cursor.initialLineNumber, 123);
|
|
assert.equal(element.$.cursor.side, 'right');
|
|
});
|
|
|
|
test('_getLineOfInterest', () => {
|
|
assert.isNull(element._getLineOfInterest({}));
|
|
|
|
let result = element._getLineOfInterest({lineNum: 12});
|
|
assert.equal(result.number, 12);
|
|
assert.isNotOk(result.leftSide);
|
|
|
|
result = element._getLineOfInterest({lineNum: 12, leftSide: true});
|
|
assert.equal(result.number, 12);
|
|
assert.isOk(result.leftSide);
|
|
});
|
|
|
|
test('_onLineSelected', () => {
|
|
const getUrlStub = sandbox.stub(Gerrit.Nav, 'getUrlForDiffById');
|
|
const replaceStateStub = sandbox.stub(history, 'replaceState');
|
|
const moveStub = sandbox.stub(element.$.cursor, 'moveToLineNumber');
|
|
sandbox.stub(element.$.cursor, 'getAddress')
|
|
.returns({number: 123, isLeftSide: false});
|
|
|
|
element._changeNum = 321;
|
|
element._change = {_number: 321, project: 'foo/bar'};
|
|
element._patchRange = {
|
|
basePatchNum: '3',
|
|
patchNum: '5',
|
|
};
|
|
const e = {};
|
|
const detail = {number: 123, side: 'right'};
|
|
|
|
element._onLineSelected(e, detail);
|
|
|
|
assert.isTrue(moveStub.called);
|
|
assert.equal(moveStub.lastCall.args[0], detail.number);
|
|
assert.equal(moveStub.lastCall.args[1], detail.side);
|
|
|
|
assert.isTrue(replaceStateStub.called);
|
|
assert.isTrue(getUrlStub.called);
|
|
});
|
|
|
|
test('_onLineSelected w/o line address', () => {
|
|
const getUrlStub = sandbox.stub(Gerrit.Nav, 'getUrlForDiffById');
|
|
sandbox.stub(history, 'replaceState');
|
|
sandbox.stub(element.$.cursor, 'moveToLineNumber');
|
|
sandbox.stub(element.$.cursor, 'getAddress').returns(null);
|
|
element._changeNum = 321;
|
|
element._change = {_number: 321, project: 'foo/bar'};
|
|
element._patchRange = {basePatchNum: '3', patchNum: '5'};
|
|
element._onLineSelected({}, {number: 123, side: 'right'});
|
|
assert.isTrue(getUrlStub.calledOnce);
|
|
assert.isUndefined(getUrlStub.lastCall.args[5]);
|
|
assert.isUndefined(getUrlStub.lastCall.args[6]);
|
|
});
|
|
|
|
test('_getDiffViewMode', () => {
|
|
// No user prefs or change view state set.
|
|
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
|
|
// User prefs but no change view state set.
|
|
element._userPrefs = {default_diff_view: 'UNIFIED_DIFF'};
|
|
assert.equal(element._getDiffViewMode(), 'UNIFIED_DIFF');
|
|
|
|
// User prefs and change view state set.
|
|
element.changeViewState = {diffMode: 'SIDE_BY_SIDE'};
|
|
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
});
|
|
|
|
suite('_loadComments', () => {
|
|
test('empty', done => {
|
|
element._loadComments().then(() => {
|
|
assert.equal(Object.keys(element._commentMap).length, 0);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('has paths', done => {
|
|
sandbox.stub(element, '_getPaths').returns({
|
|
'path/to/file/one.cpp': [{patch_set: 3, message: 'lorem'}],
|
|
'path-to/file/two.py': [{patch_set: 5, message: 'ipsum'}],
|
|
});
|
|
sandbox.stub(element, '_getCommentsForPath').returns({meta: {}});
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: '3',
|
|
patchNum: '5',
|
|
};
|
|
element._loadComments().then(() => {
|
|
assert.deepEqual(Object.keys(element._commentMap),
|
|
['path/to/file/one.cpp', 'path-to/file/two.py']);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('_computeCommentSkips', () => {
|
|
test('empty file list', () => {
|
|
const commentMap = {
|
|
'path/one.jpg': true,
|
|
'path/three.wav': true,
|
|
};
|
|
const path = 'path/two.m4v';
|
|
const fileList = [];
|
|
const result = element._computeCommentSkips(commentMap, fileList, path);
|
|
assert.isNull(result.previous);
|
|
assert.isNull(result.next);
|
|
});
|
|
|
|
test('finds skips', () => {
|
|
const fileList = ['path/one.jpg', 'path/two.m4v', 'path/three.wav'];
|
|
let path = fileList[1];
|
|
const commentMap = {};
|
|
commentMap[fileList[0]] = true;
|
|
commentMap[fileList[1]] = false;
|
|
commentMap[fileList[2]] = true;
|
|
|
|
let result = element._computeCommentSkips(commentMap, fileList, path);
|
|
assert.equal(result.previous, fileList[0]);
|
|
assert.equal(result.next, fileList[2]);
|
|
|
|
commentMap[fileList[1]] = true;
|
|
|
|
result = element._computeCommentSkips(commentMap, fileList, path);
|
|
assert.equal(result.previous, fileList[0]);
|
|
assert.equal(result.next, fileList[2]);
|
|
|
|
path = fileList[0];
|
|
|
|
result = element._computeCommentSkips(commentMap, fileList, path);
|
|
assert.isNull(result.previous);
|
|
assert.equal(result.next, fileList[1]);
|
|
|
|
path = fileList[2];
|
|
|
|
result = element._computeCommentSkips(commentMap, fileList, path);
|
|
assert.equal(result.previous, fileList[1]);
|
|
assert.isNull(result.next);
|
|
});
|
|
|
|
suite('skip next/previous', () => {
|
|
let navToChangeStub;
|
|
let navToDiffStub;
|
|
|
|
setup(() => {
|
|
navToChangeStub = sandbox.stub(element, '_navToChangeView');
|
|
navToDiffStub = sandbox.stub(Gerrit.Nav, 'navigateToDiff');
|
|
element._fileList = [
|
|
'path/one.jpg', 'path/two.m4v', 'path/three.wav',
|
|
];
|
|
element._patchRange = {patchNum: '2', basePatchNum: '1'};
|
|
});
|
|
|
|
suite('_moveToPreviousFileWithComment', () => {
|
|
test('no skips', () => {
|
|
element._moveToPreviousFileWithComment();
|
|
assert.isFalse(navToChangeStub.called);
|
|
assert.isFalse(navToDiffStub.called);
|
|
});
|
|
|
|
test('no previous', () => {
|
|
const commentMap = {};
|
|
commentMap[element._fileList[0]] = false;
|
|
commentMap[element._fileList[1]] = false;
|
|
commentMap[element._fileList[2]] = true;
|
|
element._commentMap = commentMap;
|
|
element._path = element._fileList[1];
|
|
|
|
element._moveToPreviousFileWithComment();
|
|
assert.isTrue(navToChangeStub.calledOnce);
|
|
assert.isFalse(navToDiffStub.called);
|
|
});
|
|
|
|
test('w/ previous', () => {
|
|
const commentMap = {};
|
|
commentMap[element._fileList[0]] = true;
|
|
commentMap[element._fileList[1]] = false;
|
|
commentMap[element._fileList[2]] = true;
|
|
element._commentMap = commentMap;
|
|
element._path = element._fileList[1];
|
|
|
|
element._moveToPreviousFileWithComment();
|
|
assert.isFalse(navToChangeStub.called);
|
|
assert.isTrue(navToDiffStub.calledOnce);
|
|
});
|
|
});
|
|
|
|
suite('_moveToNextFileWithComment', () => {
|
|
test('no skips', () => {
|
|
element._moveToNextFileWithComment();
|
|
assert.isFalse(navToChangeStub.called);
|
|
assert.isFalse(navToDiffStub.called);
|
|
});
|
|
|
|
test('no previous', () => {
|
|
const commentMap = {};
|
|
commentMap[element._fileList[0]] = true;
|
|
commentMap[element._fileList[1]] = false;
|
|
commentMap[element._fileList[2]] = false;
|
|
element._commentMap = commentMap;
|
|
element._path = element._fileList[1];
|
|
|
|
element._moveToNextFileWithComment();
|
|
assert.isTrue(navToChangeStub.calledOnce);
|
|
assert.isFalse(navToDiffStub.called);
|
|
});
|
|
|
|
test('w/ previous', () => {
|
|
const commentMap = {};
|
|
commentMap[element._fileList[0]] = true;
|
|
commentMap[element._fileList[1]] = false;
|
|
commentMap[element._fileList[2]] = true;
|
|
element._commentMap = commentMap;
|
|
element._path = element._fileList[1];
|
|
|
|
element._moveToNextFileWithComment();
|
|
assert.isFalse(navToChangeStub.called);
|
|
assert.isTrue(navToDiffStub.calledOnce);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
test('_computeEditMode', () => {
|
|
const callCompute = range => element._computeEditMode({base: range});
|
|
assert.isFalse(callCompute({}));
|
|
assert.isFalse(callCompute({basePatchNum: 'PARENT', patchNum: 1}));
|
|
assert.isFalse(callCompute({basePatchNum: 'edit', patchNum: 1}));
|
|
assert.isTrue(callCompute({basePatchNum: 1, patchNum: 'edit'}));
|
|
});
|
|
|
|
suite('editMode behavior', () => {
|
|
setup(() => {
|
|
element._loggedIn = true;
|
|
});
|
|
|
|
const isVisible = el => {
|
|
assert.ok(el);
|
|
return getComputedStyle(el).getPropertyValue('display') !== 'none';
|
|
};
|
|
|
|
test('reviewed checkbox', () => {
|
|
sandbox.stub(element, '_handlePatchChange');
|
|
element._patchRange = {patchNum: '1'};
|
|
// Reviewed checkbox should be shown.
|
|
assert.isTrue(isVisible(element.$.reviewed));
|
|
element.set('_patchRange.patchNum', element.EDIT_NAME);
|
|
flushAsynchronousOperations();
|
|
|
|
assert.isFalse(isVisible(element.$.reviewed));
|
|
});
|
|
});
|
|
});
|
|
</script>
|