1873 lines
63 KiB
JavaScript
1873 lines
63 KiB
JavaScript
/**
|
|
* @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.
|
|
*/
|
|
|
|
import '../../../test/common-test-setup-karma.js';
|
|
import './gr-diff-view.js';
|
|
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
|
|
import {ChangeStatus} from '../../../constants/constants.js';
|
|
import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
|
|
import {Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
|
|
import {_testOnly_findCommentById} from '../gr-comment-api/gr-comment-api.js';
|
|
import {GerritView} from '../../../services/router/router-model.js';
|
|
import {
|
|
createChange,
|
|
createRevisions,
|
|
createComment,
|
|
} from '../../../test/test-data-generators.js';
|
|
import {stubRestApi} from '../../../test/test-utils.js';
|
|
import {EditPatchSetNum} from '../../../types/common.js';
|
|
|
|
const basicFixture = fixtureFromElement('gr-diff-view');
|
|
|
|
const blankFixture = fixtureFromElement('div');
|
|
|
|
suite('gr-diff-view tests', () => {
|
|
suite('basic tests', () => {
|
|
let element;
|
|
let clock;
|
|
|
|
suiteSetup(() => {
|
|
const kb = TestKeyboardShortcutBinder.push();
|
|
kb.bindShortcut(Shortcut.LEFT_PANE, 'shift+left');
|
|
kb.bindShortcut(Shortcut.RIGHT_PANE, 'shift+right');
|
|
kb.bindShortcut(Shortcut.NEXT_LINE, 'j', 'down');
|
|
kb.bindShortcut(Shortcut.PREV_LINE, 'k', 'up');
|
|
kb.bindShortcut(Shortcut.NEXT_FILE_WITH_COMMENTS, 'shift+j');
|
|
kb.bindShortcut(Shortcut.PREV_FILE_WITH_COMMENTS, 'shift+k');
|
|
kb.bindShortcut(Shortcut.NEW_COMMENT, 'c');
|
|
kb.bindShortcut(Shortcut.SAVE_COMMENT, 'ctrl+s');
|
|
kb.bindShortcut(Shortcut.NEXT_FILE, ']');
|
|
kb.bindShortcut(Shortcut.PREV_FILE, '[');
|
|
kb.bindShortcut(Shortcut.NEXT_CHUNK, 'n');
|
|
kb.bindShortcut(Shortcut.NEXT_COMMENT_THREAD, 'shift+n');
|
|
kb.bindShortcut(Shortcut.PREV_CHUNK, 'p');
|
|
kb.bindShortcut(Shortcut.PREV_COMMENT_THREAD, 'shift+p');
|
|
kb.bindShortcut(Shortcut.OPEN_REPLY_DIALOG, 'a');
|
|
kb.bindShortcut(Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
|
|
kb.bindShortcut(Shortcut.TOGGLE_LEFT_PANE, 'shift+a');
|
|
kb.bindShortcut(Shortcut.UP_TO_CHANGE, 'u');
|
|
kb.bindShortcut(Shortcut.OPEN_DIFF_PREFS, ',');
|
|
kb.bindShortcut(Shortcut.TOGGLE_DIFF_MODE, 'm');
|
|
kb.bindShortcut(Shortcut.TOGGLE_FILE_REVIEWED, 'r');
|
|
kb.bindShortcut(Shortcut.EXPAND_ALL_DIFF_CONTEXT, 'shift+x');
|
|
kb.bindShortcut(Shortcut.EXPAND_ALL_COMMENT_THREADS, 'e');
|
|
kb.bindShortcut(Shortcut.TOGGLE_HIDE_ALL_COMMENT_THREADS, 'h');
|
|
kb.bindShortcut(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, 'shift+e');
|
|
kb.bindShortcut(Shortcut.NEXT_UNREVIEWED_FILE, 'shift+m');
|
|
kb.bindShortcut(Shortcut.TOGGLE_BLAME, 'b');
|
|
kb.bindShortcut(Shortcut.OPEN_FILE_LIST, 'f');
|
|
});
|
|
|
|
suiteTeardown(() => {
|
|
TestKeyboardShortcutBinder.pop();
|
|
});
|
|
|
|
const PARENT = 'PARENT';
|
|
|
|
function getFilesFromFileList(fileList) {
|
|
const changeFilesByPath = fileList.reduce((files, path) => {
|
|
files[path] = {};
|
|
return files;
|
|
}, {});
|
|
return {
|
|
sortedFileList: fileList,
|
|
changeFilesByPath,
|
|
};
|
|
}
|
|
|
|
let getDiffChangeDetailStub;
|
|
let getReviewedFilesStub;
|
|
setup(async () => {
|
|
clock = sinon.useFakeTimers();
|
|
stubRestApi('getConfig').returns(Promise.resolve({change: {}}));
|
|
stubRestApi('getLoggedIn').returns(Promise.resolve(false));
|
|
stubRestApi('getProjectConfig').returns(Promise.resolve({}));
|
|
getDiffChangeDetailStub = stubRestApi('getDiffChangeDetail').returns(
|
|
Promise.resolve({}));
|
|
stubRestApi('getChangeFiles').returns(Promise.resolve({}));
|
|
stubRestApi('saveFileReviewed').returns(Promise.resolve());
|
|
stubRestApi('getDiffComments').returns(Promise.resolve({}));
|
|
stubRestApi('getDiffRobotComments').returns(Promise.resolve({}));
|
|
stubRestApi('getDiffDrafts').returns(Promise.resolve({}));
|
|
stubRestApi('getPortedComments').returns(Promise.resolve({}));
|
|
getReviewedFilesStub = stubRestApi('getReviewedFiles').returns(
|
|
Promise.resolve([]));
|
|
|
|
element = basicFixture.instantiate();
|
|
element._changeNum = '42';
|
|
element._path = 'some/path.txt';
|
|
element._change = {};
|
|
element._diff = {content: []};
|
|
element._patchRange = {
|
|
patchNum: 77,
|
|
basePatchNum: 'PARENT',
|
|
};
|
|
sinon.stub(element.$.commentAPI, 'loadAll').returns(Promise.resolve({
|
|
_comments: {'/COMMIT_MSG': [
|
|
{
|
|
...createComment(),
|
|
id: 'c1',
|
|
line: 10,
|
|
patch_set: 2,
|
|
path: '/COMMIT_MSG',
|
|
}, {
|
|
...createComment(),
|
|
id: 'c3',
|
|
line: 10,
|
|
patch_set: 'PARENT',
|
|
path: '/COMMIT_MSG',
|
|
},
|
|
]},
|
|
computeCommentThreadCount: () => {},
|
|
computeCommentsString: () => '',
|
|
computeUnresolvedNum: () => {},
|
|
getPaths: () => {},
|
|
getThreadsBySideForFile: () => [],
|
|
findCommentById: _testOnly_findCommentById,
|
|
|
|
}));
|
|
await element._loadComments();
|
|
await flush();
|
|
});
|
|
|
|
teardown(() => {
|
|
clock.restore();
|
|
sinon.restore();
|
|
});
|
|
|
|
test('params change triggers diffViewDisplayed()', () => {
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.stub(element, '_initPatchRange');
|
|
sinon.stub(element, '_getFiles');
|
|
sinon.spy(element, '_paramsChanged');
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._path = '/COMMIT_MSG';
|
|
element._patchRange = {};
|
|
return element._paramsChanged.returnValues[0].then(() => {
|
|
assert.isTrue(element.reporting.diffViewDisplayed.calledOnce);
|
|
});
|
|
});
|
|
|
|
suite('comment route', () => {
|
|
let initLineOfInterestAndCursorStub; let getUrlStub; let replaceStateStub;
|
|
setup(() => {
|
|
initLineOfInterestAndCursorStub =
|
|
sinon.stub(element, '_initLineOfInterestAndCursor');
|
|
getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
|
|
replaceStateStub = sinon.stub(history, 'replaceState');
|
|
sinon.stub(element, '_getFiles');
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.spy(element, '_paramsChanged');
|
|
sinon.stub(element, '_getChangeDetail').returns(Promise.resolve({
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
}));
|
|
});
|
|
|
|
test('comment url resolves to comment.patch_set vs latest', () => {
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
commentLink: true,
|
|
commentId: 'c1',
|
|
};
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
};
|
|
return element._paramsChanged.returnValues[0].then(() => {
|
|
assert.isTrue(initLineOfInterestAndCursorStub.
|
|
calledWithExactly(true));
|
|
assert.equal(element._focusLineNum, 10);
|
|
assert.equal(element._patchRange.patchNum, 11);
|
|
assert.equal(element._patchRange.basePatchNum, 2);
|
|
assert.isTrue(replaceStateStub.called);
|
|
assert.isTrue(getUrlStub.calledWithExactly('42', 'test-project',
|
|
'/COMMIT_MSG', 11, 2, 10, true));
|
|
});
|
|
});
|
|
});
|
|
|
|
test('params change causes blame to load if it was set to true', () => {
|
|
// Blame loads for subsequent files if it was loaded for one file
|
|
element._isBlameLoaded = true;
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element, '_loadBlame');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.spy(element, '_paramsChanged');
|
|
sinon.stub(element, '_initPatchRange');
|
|
sinon.stub(element, '_getFiles');
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._path = '/COMMIT_MSG';
|
|
element._patchRange = {};
|
|
return element._paramsChanged.returnValues[0].then(() => {
|
|
assert.isTrue(element._isBlameLoaded);
|
|
assert.isTrue(element._loadBlame.calledOnce);
|
|
});
|
|
});
|
|
|
|
test('unchanged diff X vs latest from comment links navigates to base vs X'
|
|
, () => {
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element, '_loadBlame');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.stub(element, '_isFileUnchanged').returns(true);
|
|
sinon.spy(element, '_paramsChanged');
|
|
sinon.stub(element, '_getChangeDetail').returns(Promise.resolve({
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
}));
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
path: '/COMMIT_MSG',
|
|
commentLink: true,
|
|
commentId: 'c1',
|
|
};
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
};
|
|
return element._paramsChanged.returnValues[0].then(() => {
|
|
assert.isTrue(diffNavStub.lastCall.calledWithExactly(
|
|
element._change, '/COMMIT_MSG', 2, 'PARENT', 10));
|
|
});
|
|
});
|
|
|
|
test('unchanged diff Base vs latest from comment does not navigate'
|
|
, () => {
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element, '_loadBlame');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.stub(element, '_isFileUnchanged').returns(true);
|
|
sinon.spy(element, '_paramsChanged');
|
|
sinon.stub(element, '_getChangeDetail').returns(Promise.resolve({
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
}));
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
path: '/COMMIT_MSG',
|
|
commentLink: true,
|
|
commentId: 'c3',
|
|
};
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
};
|
|
return element._paramsChanged.returnValues[0].then(() => {
|
|
assert.isFalse(diffNavStub.called);
|
|
});
|
|
});
|
|
|
|
test('_isFileUnchanged', () => {
|
|
let diff = {
|
|
content: [
|
|
{a: 'abcd', ab: 'ef'},
|
|
{b: 'ancd', a: 'xx'},
|
|
],
|
|
};
|
|
assert.equal(element._isFileUnchanged(diff), false);
|
|
diff = {
|
|
content: [
|
|
{ab: 'abcd'},
|
|
{ab: 'ancd'},
|
|
],
|
|
};
|
|
assert.equal(element._isFileUnchanged(diff), true);
|
|
diff = {
|
|
content: [
|
|
{a: 'abcd', ab: 'ef', common: true},
|
|
{b: 'ancd', ab: 'xx'},
|
|
],
|
|
};
|
|
assert.equal(element._isFileUnchanged(diff), false);
|
|
diff = {
|
|
content: [
|
|
{a: 'abcd', ab: 'ef', common: true},
|
|
{b: 'ancd', ab: 'xx', common: true},
|
|
],
|
|
};
|
|
assert.equal(element._isFileUnchanged(diff), true);
|
|
});
|
|
|
|
test('diff toast to go to latest is shown and not base', async () => {
|
|
sinon.stub(element.reporting, 'diffViewDisplayed');
|
|
sinon.stub(element, '_loadBlame');
|
|
sinon.stub(element.$.diffHost, 'reload').returns(Promise.resolve());
|
|
sinon.spy(element, '_paramsChanged');
|
|
getDiffChangeDetailStub.returns(
|
|
Promise.resolve({
|
|
...createChange(),
|
|
revisions: createRevisions(11),
|
|
}));
|
|
element._patchRange = {
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
};
|
|
sinon.stub(element, '_isFileUnchanged').returns(false);
|
|
const toastStub =
|
|
sinon.stub(element, '_displayDiffBaseAgainstLeftToast');
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
project: 'p',
|
|
commentId: 'c1',
|
|
commentLink: true,
|
|
};
|
|
await element._paramsChanged.returnValues[0];
|
|
assert.isTrue(toastStub.called);
|
|
});
|
|
|
|
test('toggle left diff with a hotkey', () => {
|
|
const toggleLeftDiffStub = sinon.stub(
|
|
element.$.diffHost, '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._files = getFilesFromFileList(
|
|
['chell.go', 'glados.txt', 'wheatley.md']);
|
|
element._path = 'glados.txt';
|
|
element.changeViewState.selectedFileIndex = 1;
|
|
element._loggedIn = true;
|
|
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
const changeNavStub = sinon.stub(GerritNav, '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 =
|
|
sinon.stub(element.$.diffPreferencesDialog, 'open').callsFake(
|
|
() => Promise.resolve());
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
|
assert(showPrefsStub.calledOnce);
|
|
|
|
element.disableDiffPrefs = true;
|
|
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
|
assert(showPrefsStub.calledOnce);
|
|
|
|
let scrollStub = sinon.stub(element.$.cursor, 'moveToNextChunk');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 78, null, 'n');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sinon.stub(element.$.cursor, 'moveToPreviousChunk');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 80, null, 'p');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sinon.stub(element.$.cursor, 'moveToNextCommentThread');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 78, 'shift', 'n');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
scrollStub = sinon.stub(element.$.cursor,
|
|
'moveToPreviousCommentThread');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 80, 'shift', 'p');
|
|
assert(scrollStub.calledOnce);
|
|
|
|
const computeContainerClassStub = sinon.stub(element.$.diffHost.$.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));
|
|
|
|
sinon.stub(element, '_setReviewed');
|
|
sinon.spy(element, '_handleToggleFileReviewed');
|
|
element.$.reviewed.checked = false;
|
|
MockInteractions.pressAndReleaseKeyOn(element, 82, 'shift', 'r');
|
|
assert.isFalse(element._setReviewed.called);
|
|
assert.isTrue(element._handleToggleFileReviewed.calledOnce);
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 82, null, 'r');
|
|
assert.isTrue(element._handleToggleFileReviewed.calledOnce);
|
|
|
|
clock.tick(1000);
|
|
|
|
MockInteractions.pressAndReleaseKeyOn(element, 82, null, 'r');
|
|
assert.isTrue(element._handleToggleFileReviewed.calledTwice);
|
|
assert.isTrue(element._setReviewed.called);
|
|
assert.equal(element._setReviewed.lastCall.args[0], true);
|
|
});
|
|
|
|
test('shift+x shortcut expands all diff context', () => {
|
|
const expandStub = sinon.stub(element.$.diffHost, 'expandAllContext');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 88, 'shift', 'x');
|
|
flush();
|
|
assert.isTrue(expandStub.called);
|
|
});
|
|
|
|
test('diff against base', () => {
|
|
element._patchRange = {
|
|
basePatchNum: 5,
|
|
patchNum: 10,
|
|
};
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffAgainstBase(new CustomEvent(''));
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 10);
|
|
assert.isNotOk(args[3]);
|
|
});
|
|
|
|
test('diff against latest', () => {
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(12),
|
|
};
|
|
element._patchRange = {
|
|
basePatchNum: 5,
|
|
patchNum: 10,
|
|
};
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffAgainstLatest(new CustomEvent(''));
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 12);
|
|
assert.equal(args[3], 5);
|
|
});
|
|
|
|
test('_handleDiffBaseAgainstLeft', () => {
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(10),
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 3,
|
|
basePatchNum: 1,
|
|
};
|
|
element.params = {};
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffBaseAgainstLeft(new CustomEvent(''));
|
|
assert(diffNavStub.called);
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 1);
|
|
assert.equal(args[3], 'PARENT');
|
|
assert.isNotOk(args[4]);
|
|
});
|
|
|
|
test('_handleDiffBaseAgainstLeft when initially navigating to a comment',
|
|
() => {
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(10),
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 3,
|
|
basePatchNum: 1,
|
|
};
|
|
sinon.stub(element, '_paramsChanged');
|
|
element.params = {commentLink: true, view: GerritView.DIFF};
|
|
element._focusLineNum = 10;
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffBaseAgainstLeft(new CustomEvent(''));
|
|
assert(diffNavStub.called);
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 1);
|
|
assert.equal(args[3], 'PARENT');
|
|
assert.equal(args[4], 10);
|
|
});
|
|
|
|
test('_handleDiffRightAgainstLatest', () => {
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(10),
|
|
};
|
|
element._patchRange = {
|
|
basePatchNum: 1,
|
|
patchNum: 3,
|
|
};
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffRightAgainstLatest(new CustomEvent(''));
|
|
assert(diffNavStub.called);
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 10);
|
|
assert.equal(args[3], 3);
|
|
});
|
|
|
|
test('_handleDiffBaseAgainstLatest', () => {
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(10),
|
|
};
|
|
element._patchRange = {
|
|
basePatchNum: 1,
|
|
patchNum: 3,
|
|
};
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._handleDiffBaseAgainstLatest(new CustomEvent(''));
|
|
assert(diffNavStub.called);
|
|
const args = diffNavStub.getCall(0).args;
|
|
assert.equal(args[2], 10);
|
|
assert.isNotOk(args[3]);
|
|
});
|
|
|
|
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._files = getFilesFromFileList(
|
|
['chell.go', 'glados.txt', 'wheatley.md']);
|
|
element._path = 'glados.txt';
|
|
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
const changeNavStub = sinon.stub(GerritNav, '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');
|
|
|
|
assert.isUndefined(element.changeViewState.showDownloadDialog);
|
|
MockInteractions.pressAndReleaseKeyOn(element, 68, null, 'd');
|
|
assert.isTrue(element.changeViewState.showDownloadDialog);
|
|
});
|
|
|
|
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._files = getFilesFromFileList(
|
|
['chell.go', 'glados.txt', 'wheatley.md']);
|
|
element._path = 'glados.txt';
|
|
|
|
const diffNavStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
const changeNavStub = sinon.stub(GerritNav, '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';
|
|
|
|
changeNavStub.reset();
|
|
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
|
assert(changeNavStub.lastCall.calledWithExactly(element._change, 1,
|
|
PARENT), 'Should navigate to /c/42/1');
|
|
assert.isTrue(changeNavStub.calledOnce);
|
|
});
|
|
|
|
test('edit should redirect to edit page', done => {
|
|
element._loggedIn = true;
|
|
element._path = 't.txt';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: 1,
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
project: 'gerrit',
|
|
status: ChangeStatus.NEW,
|
|
revisions: {
|
|
a: {_number: 1, commit: {parents: []}},
|
|
b: {_number: 2, commit: {parents: []}},
|
|
},
|
|
};
|
|
const redirectStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
|
|
flush(() => {
|
|
const editBtn = element.shadowRoot
|
|
.querySelector('.editButton gr-button');
|
|
assert.isTrue(!!editBtn);
|
|
MockInteractions.tap(editBtn);
|
|
assert.isTrue(redirectStub.called);
|
|
assert.isTrue(redirectStub.lastCall.calledWithExactly(
|
|
GerritNav.getEditUrlForDiff(
|
|
element._change,
|
|
element._path,
|
|
element._patchRange.patchNum
|
|
)));
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('edit should redirect to edit page with line number', done => {
|
|
const lineNumber = 42;
|
|
element._loggedIn = true;
|
|
element._path = 't.txt';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: 1,
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
project: 'gerrit',
|
|
status: ChangeStatus.NEW,
|
|
revisions: {
|
|
a: {_number: 1, commit: {parents: []}},
|
|
b: {_number: 2, commit: {parents: []}},
|
|
},
|
|
};
|
|
sinon.stub(element.$.cursor, 'getAddress')
|
|
.returns({number: lineNumber, isLeftSide: false});
|
|
const redirectStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
|
|
flush(() => {
|
|
const editBtn = element.shadowRoot
|
|
.querySelector('.editButton gr-button');
|
|
assert.isTrue(!!editBtn);
|
|
MockInteractions.tap(editBtn);
|
|
assert.isTrue(redirectStub.called);
|
|
assert.isTrue(redirectStub.lastCall.calledWithExactly(
|
|
GerritNav.getEditUrlForDiff(
|
|
element._change,
|
|
element._path,
|
|
element._patchRange.patchNum,
|
|
lineNumber
|
|
)));
|
|
done();
|
|
});
|
|
});
|
|
|
|
function isEditVisibile({loggedIn, changeStatus}) {
|
|
return new Promise(resolve => {
|
|
element._loggedIn = loggedIn;
|
|
element._path = 't.txt';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: 1,
|
|
};
|
|
element._change = {
|
|
_number: 42,
|
|
status: changeStatus,
|
|
revisions: {
|
|
a: {_number: 1, commit: {parents: []}},
|
|
b: {_number: 2, commit: {parents: []}},
|
|
},
|
|
};
|
|
flush(() => {
|
|
const editBtn = element.shadowRoot
|
|
.querySelector('.editButton gr-button');
|
|
resolve(!!editBtn);
|
|
});
|
|
});
|
|
}
|
|
|
|
test('edit visible only when logged and status NEW', async () => {
|
|
for (const changeStatus of Object.keys(ChangeStatus)) {
|
|
assert.isFalse(await isEditVisibile({loggedIn: false, changeStatus}),
|
|
`loggedIn: false, changeStatus: ${changeStatus}`);
|
|
|
|
if (changeStatus !== ChangeStatus.NEW) {
|
|
assert.isFalse(await isEditVisibile({loggedIn: true, changeStatus}),
|
|
`loggedIn: true, changeStatus: ${changeStatus}`);
|
|
} else {
|
|
assert.isTrue(await isEditVisibile({loggedIn: true, changeStatus}),
|
|
`loggedIn: true, changeStatus: ${changeStatus}`);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('edit visible when logged and status NEW', async () => {
|
|
assert.isTrue(await isEditVisibile(
|
|
{loggedIn: true, changeStatus: ChangeStatus.NEW}));
|
|
});
|
|
|
|
test('edit hidden when logged and status ABANDONED', async () => {
|
|
assert.isFalse(await isEditVisibile(
|
|
{loggedIn: true, changeStatus: ChangeStatus.ABANDONED}));
|
|
});
|
|
|
|
test('edit hidden when logged and status MERGED', async () => {
|
|
assert.isFalse(await isEditVisibile(
|
|
{loggedIn: true, changeStatus: ChangeStatus.MERGED}));
|
|
});
|
|
|
|
suite('diff prefs hidden', () => {
|
|
test('when no prefs or logged out', () => {
|
|
element.disableDiffPrefs = false;
|
|
element._loggedIn = false;
|
|
flush();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = true;
|
|
flush();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = false;
|
|
element._prefs = {font_size: '12'};
|
|
flush();
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
|
|
element._loggedIn = true;
|
|
flush();
|
|
assert.isFalse(element.$.diffPrefsContainer.hidden);
|
|
});
|
|
|
|
test('when disableDiffPrefs is set', () => {
|
|
element._loggedIn = true;
|
|
element._prefs = {font_size: '12'};
|
|
element.disableDiffPrefs = false;
|
|
flush();
|
|
|
|
assert.isFalse(element.$.diffPrefsContainer.hidden);
|
|
element.disableDiffPrefs = true;
|
|
flush();
|
|
|
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
});
|
|
});
|
|
|
|
test('prefsButton opens gr-diff-preferences', () => {
|
|
const handlePrefsTapSpy = sinon.spy(element, '_handlePrefsTap');
|
|
const overlayOpenStub = sinon.stub(element.$.diffPreferencesDialog,
|
|
'open');
|
|
const prefsButton =
|
|
element.root.querySelector('.prefsButton');
|
|
|
|
MockInteractions.tap(prefsButton);
|
|
|
|
assert.isTrue(handlePrefsTapSpy.called);
|
|
assert.isTrue(overlayOpenStub.called);
|
|
});
|
|
|
|
suite('url params', () => {
|
|
setup(() => {
|
|
sinon.stub(element, '_getFiles');
|
|
sinon.stub(
|
|
GerritNav,
|
|
'getUrlForDiff')
|
|
.callsFake((c, p, pn, bpn) => `${c._number}-${p}-${pn}-${bpn}`);
|
|
sinon.stub(
|
|
GerritNav
|
|
, 'getUrlForChange')
|
|
.callsFake((c, pn, bpn) => `${c._number}-${pn}-${bpn}`);
|
|
});
|
|
|
|
test('_formattedFiles', () => {
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: PARENT,
|
|
patchNum: 10,
|
|
};
|
|
element._change = {_number: 42};
|
|
element._files = getFilesFromFileList(
|
|
['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: '',
|
|
file: {
|
|
__path: 'chell.go',
|
|
},
|
|
}, {
|
|
text: 'glados.txt',
|
|
mobileText: 'glados.txt',
|
|
value: 'glados.txt',
|
|
bottomText: '',
|
|
file: {
|
|
__path: 'glados.txt',
|
|
},
|
|
}, {
|
|
text: 'wheatley.md',
|
|
mobileText: 'wheatley.md',
|
|
value: 'wheatley.md',
|
|
bottomText: '',
|
|
file: {
|
|
__path: 'wheatley.md',
|
|
},
|
|
},
|
|
{
|
|
text: 'Commit message',
|
|
mobileText: 'Commit message',
|
|
value: '/COMMIT_MSG',
|
|
bottomText: '',
|
|
file: {
|
|
__path: '/COMMIT_MSG',
|
|
},
|
|
},
|
|
{
|
|
text: 'Merge list',
|
|
mobileText: 'Merge list',
|
|
value: '/MERGE_LIST',
|
|
bottomText: '',
|
|
file: {
|
|
__path: '/MERGE_LIST',
|
|
},
|
|
},
|
|
];
|
|
|
|
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._files = getFilesFromFileList(
|
|
['chell.go', 'glados.txt', 'wheatley.md']);
|
|
element._path = 'glados.txt';
|
|
flush();
|
|
const linkEls = 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';
|
|
flush();
|
|
assert.equal(linkEls[0].getAttribute('href'),
|
|
'42-glados.txt-10-PARENT');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-undefined-undefined');
|
|
assert.equal(linkEls[2].getAttribute('href'), '42-undefined-undefined');
|
|
element._path = 'chell.go';
|
|
flush();
|
|
assert.equal(linkEls[0].getAttribute('href'), '42-undefined-undefined');
|
|
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';
|
|
flush();
|
|
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._files = getFilesFromFileList(
|
|
['chell.go', 'glados.txt', 'wheatley.md']);
|
|
element._path = 'glados.txt';
|
|
flush();
|
|
const linkEls = 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';
|
|
flush();
|
|
assert.equal(linkEls[0].getAttribute('href'), '42-glados.txt-10-5');
|
|
assert.equal(linkEls[1].getAttribute('href'), '42-10-5');
|
|
assert.equal(linkEls[2].getAttribute('href'), '42-10-5');
|
|
element._path = 'chell.go';
|
|
flush();
|
|
assert.equal(linkEls[0].getAttribute('href'),
|
|
'42-10-5');
|
|
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 = sinon.stub(GerritNav, '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('_prefs.manual_review is respected', () => {
|
|
const saveReviewedStub = sinon.stub(element, '_saveReviewedState')
|
|
.callsFake(() => Promise.resolve());
|
|
const getReviewedStub = sinon.stub(element, '_getReviewedStatus')
|
|
.callsFake(() => Promise.resolve());
|
|
|
|
sinon.stub(element.$.diffHost, 'reload');
|
|
element._loggedIn = true;
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
};
|
|
element._prefs = {manual_review: true};
|
|
flush();
|
|
|
|
assert.isFalse(saveReviewedStub.called);
|
|
assert.isTrue(getReviewedStub.called);
|
|
|
|
element._prefs = {};
|
|
flush();
|
|
|
|
assert.isTrue(saveReviewedStub.called);
|
|
assert.isTrue(getReviewedStub.calledOnce);
|
|
});
|
|
|
|
test('file review status', () => {
|
|
const saveReviewedStub = sinon.stub(element, '_saveReviewedState')
|
|
.callsFake(() => Promise.resolve());
|
|
sinon.stub(element.$.diffHost, 'reload');
|
|
|
|
element._loggedIn = true;
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
};
|
|
element._prefs = {};
|
|
flush();
|
|
|
|
const commitMsg = 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', GerritNav.View.CHANGE);
|
|
flush();
|
|
|
|
// saveReviewedState observer observes params, but should not fire when
|
|
// view !== GerritNav.View.DIFF.
|
|
assert.equal(saveReviewedStub.callCount, callCount);
|
|
});
|
|
|
|
test('file review status with edit loaded', () => {
|
|
const saveReviewedStub = sinon.stub(element, '_saveReviewedState');
|
|
|
|
element._patchRange = {patchNum: EditPatchSetNum};
|
|
flush();
|
|
|
|
assert.isTrue(element._editMode);
|
|
element._setReviewed();
|
|
assert.isFalse(saveReviewedStub.called);
|
|
});
|
|
|
|
test('hash is determined from params', done => {
|
|
sinon.stub(element.$.diffHost, 'reload');
|
|
sinon.stub(element, '_initLineOfInterestAndCursor');
|
|
|
|
element._loggedIn = true;
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 2,
|
|
basePatchNum: 1,
|
|
path: '/COMMIT_MSG',
|
|
hash: 10,
|
|
};
|
|
|
|
flush(() => {
|
|
assert.isTrue(element._initLineOfInterestAndCursor.calledOnce);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('diff mode selector correctly toggles the diff', () => {
|
|
const select = element.$.modeSelect;
|
|
const diffDisplay = element.$.diffHost;
|
|
element._userPrefs = {default_diff_view: 'SIDE_BY_SIDE'};
|
|
|
|
// The mode selected in the view state reflects the selected option.
|
|
assert.equal(element._getDiffViewMode(), select.mode);
|
|
|
|
// The mode selected in the view state reflects the view rednered in the
|
|
// diff.
|
|
assert.equal(select.mode, diffDisplay.viewMode);
|
|
|
|
// We will simulate a user change of the selected mode.
|
|
const newMode = 'UNIFIED_DIFF';
|
|
|
|
// Set the mode, and simulate the change event.
|
|
element.set('changeViewState.diffMode', newMode);
|
|
|
|
// Make sure the handler was called and the state is still coherent.
|
|
assert.equal(element._getDiffViewMode(), newMode);
|
|
assert.equal(element._getDiffViewMode(), select.mode);
|
|
assert.equal(element._getDiffViewMode(), diffDisplay.viewMode);
|
|
});
|
|
|
|
test('diff mode selector initializes from preferences', () => {
|
|
let resolvePrefs;
|
|
const prefsPromise = new Promise(resolve => {
|
|
resolvePrefs = resolve;
|
|
});
|
|
stubRestApi('getPreferences')
|
|
.callsFake(() => prefsPromise);
|
|
|
|
// Attach a new gr-diff-view so we can intercept the preferences fetch.
|
|
const view = document.createElement('gr-diff-view');
|
|
blankFixture.instantiate().appendChild(view);
|
|
flush();
|
|
|
|
// At this point the diff mode doesn't yet have the user's preference.
|
|
assert.equal(view._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
|
|
// Receive the overriding preference.
|
|
resolvePrefs({default_diff_view: 'UNIFIED'});
|
|
flush();
|
|
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
});
|
|
|
|
test('diff mode selector should be hidden for binary', done => {
|
|
element._diff = {binary: true, content: []};
|
|
|
|
flush(() => {
|
|
const diffModeSelector = element.shadowRoot
|
|
.querySelector('.diffModeSelector');
|
|
assert.isTrue(diffModeSelector.classList.contains('hide'));
|
|
done();
|
|
});
|
|
});
|
|
|
|
suite('_commitRange', () => {
|
|
const change = {
|
|
_number: 42,
|
|
revisions: {
|
|
'commit-sha-1': {
|
|
_number: 1,
|
|
commit: {
|
|
parents: [{commit: 'sha-1-parent'}],
|
|
},
|
|
},
|
|
'commit-sha-2': {_number: 2, commit: {parents: []}},
|
|
'commit-sha-3': {_number: 3, commit: {parents: []}},
|
|
'commit-sha-4': {_number: 4, commit: {parents: []}},
|
|
'commit-sha-5': {
|
|
_number: 5,
|
|
commit: {
|
|
parents: [{commit: 'sha-5-parent'}],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
setup(() => {
|
|
sinon.stub(element.$.diffHost, 'reload');
|
|
sinon.stub(element, '_initCursor');
|
|
element._change = change;
|
|
sinon.stub(element, '_getChangeDetail').returns(Promise.resolve(
|
|
change));
|
|
});
|
|
|
|
test('uses the patchNum and basePatchNum ', done => {
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 4,
|
|
basePatchNum: 2,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._change = change;
|
|
flush(() => {
|
|
assert.deepEqual(element._commitRange, {
|
|
baseCommit: 'commit-sha-2',
|
|
commit: 'commit-sha-4',
|
|
});
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('uses the parent when there is no base patch num ', done => {
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 5,
|
|
path: '/COMMIT_MSG',
|
|
};
|
|
element._change = change;
|
|
flush(() => {
|
|
assert.deepEqual(element._commitRange, {
|
|
commit: 'commit-sha-5',
|
|
baseCommit: 'sha-5-parent',
|
|
});
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
test('_initCursor', () => {
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Does nothing when params specify no cursor address:
|
|
element._initCursor(false);
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Does nothing when params specify side but no number:
|
|
element._initCursor(true);
|
|
assert.isNotOk(element.$.cursor.initialLineNumber);
|
|
|
|
// Revision hash: specifies lineNum but not side.
|
|
|
|
element._focusLineNum = 234;
|
|
element._initCursor(false);
|
|
assert.equal(element.$.cursor.initialLineNumber, 234);
|
|
assert.equal(element.$.cursor.side, 'right');
|
|
|
|
// Base hash: specifies lineNum and side.
|
|
element._focusLineNum = 345;
|
|
element._initCursor(true);
|
|
assert.equal(element.$.cursor.initialLineNumber, 345);
|
|
assert.equal(element.$.cursor.side, 'left');
|
|
|
|
// Specifies right side:
|
|
element._focusLineNum = 123;
|
|
element._initCursor(false);
|
|
assert.equal(element.$.cursor.initialLineNumber, 123);
|
|
assert.equal(element.$.cursor.side, 'right');
|
|
});
|
|
|
|
test('_getLineOfInterest', () => {
|
|
assert.isUndefined(element._getLineOfInterest(false));
|
|
|
|
element._focusLineNum = 12;
|
|
let result = element._getLineOfInterest(false);
|
|
assert.equal(result.number, 12);
|
|
assert.isNotOk(result.leftSide);
|
|
|
|
result = element._getLineOfInterest(true);
|
|
assert.equal(result.number, 12);
|
|
assert.isOk(result.leftSide);
|
|
});
|
|
|
|
test('_onLineSelected', () => {
|
|
const getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
|
|
const replaceStateStub = sinon.stub(history, 'replaceState');
|
|
sinon.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(replaceStateStub.called);
|
|
assert.isTrue(getUrlStub.called);
|
|
assert.isFalse(getUrlStub.lastCall.args[6]);
|
|
});
|
|
|
|
test('line selected on left side', () => {
|
|
const getUrlStub = sinon.stub(GerritNav, 'getUrlForDiffById');
|
|
const replaceStateStub = sinon.stub(history, 'replaceState');
|
|
sinon.stub(element.$.cursor, 'getAddress')
|
|
.returns({number: 123, isLeftSide: true});
|
|
|
|
element._changeNum = 321;
|
|
element._change = {_number: 321, project: 'foo/bar'};
|
|
element._patchRange = {
|
|
basePatchNum: 3,
|
|
patchNum: 5,
|
|
};
|
|
const e = {};
|
|
const detail = {number: 123, side: 'left'};
|
|
|
|
element._onLineSelected(e, detail);
|
|
|
|
assert.isTrue(replaceStateStub.called);
|
|
assert.isTrue(getUrlStub.called);
|
|
assert.isTrue(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');
|
|
});
|
|
|
|
test('_handleToggleDiffMode', () => {
|
|
sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
|
const e = {preventDefault: () => {}};
|
|
// Initial state.
|
|
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
|
|
element._handleToggleDiffMode(e);
|
|
assert.equal(element._getDiffViewMode(), 'UNIFIED_DIFF');
|
|
|
|
element._handleToggleDiffMode(e);
|
|
assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
|
|
});
|
|
|
|
suite('_initPatchRange', () => {
|
|
setup(async () => {
|
|
element.params = {
|
|
view: GerritView.DIFF,
|
|
changeNum: '42',
|
|
patchNum: 3,
|
|
};
|
|
await flush();
|
|
});
|
|
test('empty', () => {
|
|
sinon.stub(element, '_getPaths').returns(new Map());
|
|
element._initPatchRange();
|
|
assert.equal(Object.keys(element._commentMap).length, 0);
|
|
});
|
|
|
|
test('has paths', () => {
|
|
sinon.stub(element, '_getFiles');
|
|
sinon.stub(element, '_getPaths').returns({
|
|
'path/to/file/one.cpp': [{patch_set: 3, message: 'lorem'}],
|
|
'path-to/file/two.py': [{patch_set: 5, message: 'ipsum'}],
|
|
});
|
|
element._changeNum = '42';
|
|
element._patchRange = {
|
|
basePatchNum: 3,
|
|
patchNum: 5,
|
|
};
|
|
element._initPatchRange();
|
|
assert.deepEqual(Object.keys(element._commentMap),
|
|
['path/to/file/one.cpp', 'path-to/file/two.py']);
|
|
});
|
|
});
|
|
|
|
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 = sinon.stub(element, '_navToChangeView');
|
|
navToDiffStub = sinon.stub(GerritNav, 'navigateToDiff');
|
|
element._files = getFilesFromFileList([
|
|
'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'}));
|
|
});
|
|
|
|
test('_computeFileNum', () => {
|
|
assert.equal(element._computeFileNum('/foo',
|
|
[{value: '/foo'}, {value: '/bar'}]), 1);
|
|
assert.equal(element._computeFileNum('/bar',
|
|
[{value: '/foo'}, {value: '/bar'}]), 2);
|
|
});
|
|
|
|
test('_computeFileNumClass', () => {
|
|
assert.equal(element._computeFileNumClass(0, []), '');
|
|
assert.equal(element._computeFileNumClass(1,
|
|
[{value: '/foo'}, {value: '/bar'}]), 'show');
|
|
});
|
|
|
|
test('_getReviewedStatus', () => {
|
|
const promises = [];
|
|
getReviewedFilesStub.returns(Promise.resolve(['path']));
|
|
|
|
promises.push(element._getReviewedStatus(true, null, null, 'path')
|
|
.then(reviewed => assert.isFalse(reviewed)));
|
|
|
|
promises.push(element._getReviewedStatus(false, null, null, 'otherPath')
|
|
.then(reviewed => assert.isFalse(reviewed)));
|
|
|
|
promises.push(element._getReviewedStatus(false, null, null, 'path')
|
|
.then(reviewed => assert.isFalse(reviewed)));
|
|
|
|
promises.push(element._getReviewedStatus(false, 3, 5, 'path')
|
|
.then(reviewed => assert.isTrue(reviewed)));
|
|
|
|
return Promise.all(promises);
|
|
});
|
|
|
|
test('f open file dropdown', () => {
|
|
assert.isFalse(element.$.dropdown.$.dropdown.opened);
|
|
MockInteractions.pressAndReleaseKeyOn(element, 70, null, 'f');
|
|
flush();
|
|
assert.isTrue(element.$.dropdown.$.dropdown.opened);
|
|
});
|
|
|
|
suite('blame', () => {
|
|
test('toggle blame with button', () => {
|
|
const toggleBlame = sinon.stub(
|
|
element.$.diffHost, 'loadBlame')
|
|
.callsFake(() => Promise.resolve());
|
|
MockInteractions.tap(element.$.toggleBlame);
|
|
assert.isTrue(toggleBlame.calledOnce);
|
|
});
|
|
test('toggle blame with shortcut', () => {
|
|
const toggleBlame = sinon.stub(
|
|
element.$.diffHost, 'loadBlame').callsFake(() => Promise.resolve());
|
|
MockInteractions.pressAndReleaseKeyOn(element, 66, null, 'b');
|
|
assert.isTrue(toggleBlame.calledOnce);
|
|
});
|
|
});
|
|
|
|
suite('editMode behavior', () => {
|
|
setup(() => {
|
|
element._loggedIn = true;
|
|
});
|
|
|
|
const isVisible = el => {
|
|
assert.ok(el);
|
|
return getComputedStyle(el).getPropertyValue('display') !== 'none';
|
|
};
|
|
|
|
test('reviewed checkbox', () => {
|
|
sinon.stub(element, '_handlePatchChange');
|
|
element._patchRange = {patchNum: 1};
|
|
// Reviewed checkbox should be shown.
|
|
assert.isTrue(isVisible(element.$.reviewed));
|
|
element.set('_patchRange.patchNum', EditPatchSetNum);
|
|
flush();
|
|
|
|
assert.isFalse(isVisible(element.$.reviewed));
|
|
});
|
|
});
|
|
|
|
test('_paramsChanged sets in projectLookup', () => {
|
|
sinon.stub(element, '_initLineOfInterestAndCursor');
|
|
const setStub = stubRestApi('setInProjectLookup');
|
|
element._paramsChanged({
|
|
view: GerritNav.View.DIFF,
|
|
changeNum: 101,
|
|
project: 'test-project',
|
|
path: '',
|
|
});
|
|
assert.isTrue(setStub.calledOnce);
|
|
assert.isTrue(setStub.calledWith(101, 'test-project'));
|
|
});
|
|
|
|
test('shift+m navigates to next unreviewed file', () => {
|
|
element._files = getFilesFromFileList(['file1', 'file2', 'file3']);
|
|
element._reviewedFiles = new Set(['file1', 'file2']);
|
|
element._path = 'file1';
|
|
const reviewedStub = sinon.stub(element, '_setReviewed');
|
|
const navStub = sinon.stub(element, '_navToFile');
|
|
MockInteractions.pressAndReleaseKeyOn(element, 77, 'shift', 'm');
|
|
flush();
|
|
|
|
assert.isTrue(reviewedStub.lastCall.args[0]);
|
|
assert.deepEqual(navStub.lastCall.args, [
|
|
'file1',
|
|
['file1', 'file3'],
|
|
1,
|
|
]);
|
|
});
|
|
|
|
test('File change should trigger navigateToDiff once', done => {
|
|
element._files = getFilesFromFileList(['file1', 'file2', 'file3']);
|
|
sinon.stub(element, '_initLineOfInterestAndCursor');
|
|
sinon.stub(GerritNav, 'navigateToDiff');
|
|
|
|
// Load file1
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
patchNum: 1,
|
|
changeNum: 101,
|
|
project: 'test-project',
|
|
path: 'file1',
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 1,
|
|
basePatchNum: 'PARENT',
|
|
};
|
|
element._change = {
|
|
...createChange(),
|
|
revisions: createRevisions(1),
|
|
};
|
|
flush();
|
|
assert.isTrue(GerritNav.navigateToDiff.notCalled);
|
|
|
|
// Switch to file2
|
|
element._handleFileChange({detail: {value: 'file2'}});
|
|
assert.isTrue(GerritNav.navigateToDiff.calledOnce);
|
|
|
|
// This is to mock the param change triggered by above navigate
|
|
element.params = {
|
|
view: GerritNav.View.DIFF,
|
|
patchNum: 1,
|
|
changeNum: 101,
|
|
project: 'test-project',
|
|
path: 'file2',
|
|
};
|
|
element._patchRange = {
|
|
patchNum: 1,
|
|
basePatchNum: 'PARENT',
|
|
};
|
|
|
|
// No extra call
|
|
assert.isTrue(GerritNav.navigateToDiff.calledOnce);
|
|
done();
|
|
});
|
|
|
|
test('_computeDownloadDropdownLinks', () => {
|
|
const downloadLinks = [
|
|
{
|
|
url: '/changes/test~12/revisions/1/patch?zip&path=index.php',
|
|
name: 'Patch',
|
|
},
|
|
{
|
|
url: '/changes/test~12/revisions/1' +
|
|
'/files/index.php/download?parent=1',
|
|
name: 'Left Content',
|
|
},
|
|
{
|
|
url: '/changes/test~12/revisions/1' +
|
|
'/files/index.php/download',
|
|
name: 'Right Content',
|
|
},
|
|
];
|
|
|
|
const side = {
|
|
meta_a: true,
|
|
meta_b: true,
|
|
};
|
|
|
|
const base = {
|
|
patchNum: 1,
|
|
basePatchNum: 'PARENT',
|
|
};
|
|
|
|
assert.deepEqual(
|
|
element._computeDownloadDropdownLinks(
|
|
'test', 12, base, 'index.php', side),
|
|
downloadLinks);
|
|
});
|
|
|
|
test('_computeDownloadDropdownLinks diff returns renamed', () => {
|
|
const downloadLinks = [
|
|
{
|
|
url: '/changes/test~12/revisions/3/patch?zip&path=index.php',
|
|
name: 'Patch',
|
|
},
|
|
{
|
|
url: '/changes/test~12/revisions/2' +
|
|
'/files/index2.php/download',
|
|
name: 'Left Content',
|
|
},
|
|
{
|
|
url: '/changes/test~12/revisions/3' +
|
|
'/files/index.php/download',
|
|
name: 'Right Content',
|
|
},
|
|
];
|
|
|
|
const side = {
|
|
change_type: 'RENAMED',
|
|
meta_a: {
|
|
name: 'index2.php',
|
|
},
|
|
meta_b: true,
|
|
};
|
|
|
|
const base = {
|
|
patchNum: 3,
|
|
basePatchNum: 2,
|
|
};
|
|
|
|
assert.deepEqual(
|
|
element._computeDownloadDropdownLinks(
|
|
'test', 12, base, 'index.php', side),
|
|
downloadLinks);
|
|
});
|
|
|
|
test('_computeDownloadFileLink', () => {
|
|
const base = {
|
|
patchNum: 1,
|
|
basePatchNum: 'PARENT',
|
|
};
|
|
|
|
assert.equal(
|
|
element._computeDownloadFileLink(
|
|
'test', 12, base, 'index.php', true),
|
|
'/changes/test~12/revisions/1/files/index.php/download?parent=1');
|
|
|
|
assert.equal(
|
|
element._computeDownloadFileLink(
|
|
'test', 12, base, 'index.php', false),
|
|
'/changes/test~12/revisions/1/files/index.php/download');
|
|
});
|
|
|
|
test('_computeDownloadPatchLink', () => {
|
|
assert.equal(
|
|
element._computeDownloadPatchLink(
|
|
'test', 12, {patchNum: 1}, 'index.php'),
|
|
'/changes/test~12/revisions/1/patch?zip&path=index.php');
|
|
});
|
|
});
|
|
|
|
suite('gr-diff-view tests unmodified files with comments', () => {
|
|
let element;
|
|
setup(() => {
|
|
const changedFiles = {
|
|
'file1.txt': {},
|
|
'a/b/test.c': {},
|
|
};
|
|
stubRestApi('getConfig').returns(Promise.resolve({change: {}}));
|
|
stubRestApi('getLoggedIn').returns(Promise.resolve(true));
|
|
stubRestApi('getProjectConfig').returns(Promise.resolve({}));
|
|
stubRestApi('getDiffChangeDetail').returns(Promise.resolve({}));
|
|
stubRestApi('getChangeFiles').returns(Promise.resolve(changedFiles));
|
|
stubRestApi('saveFileReviewed').returns(Promise.resolve());
|
|
stubRestApi('getDiffComments').returns(Promise.resolve({}));
|
|
stubRestApi('getDiffRobotComments').returns(Promise.resolve({}));
|
|
stubRestApi('getDiffDrafts').returns(Promise.resolve({}));
|
|
stubRestApi('getReviewedFiles').returns(
|
|
Promise.resolve([]));
|
|
element = basicFixture.instantiate();
|
|
element._changeNum = '42';
|
|
return element._loadComments();
|
|
});
|
|
|
|
test('_getFiles add files with comments without changes', () => {
|
|
const patchChangeRecord = {
|
|
base: {
|
|
basePatchNum: 5,
|
|
patchNum: 10,
|
|
},
|
|
};
|
|
const changeComments = {
|
|
getPaths: sinon.stub().returns({
|
|
'file2.txt': {},
|
|
'file1.txt': {},
|
|
}),
|
|
};
|
|
return element._getFiles(23, patchChangeRecord, changeComments)
|
|
.then(() => {
|
|
assert.deepEqual(element._files, {
|
|
sortedFileList: ['a/b/test.c', 'file1.txt', 'file2.txt'],
|
|
changeFilesByPath: {
|
|
'file1.txt': {},
|
|
'file2.txt': {status: 'U'},
|
|
'a/b/test.c': {},
|
|
},
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|