
Fixed all tests and added more tests to plugin loader.
This also adds https://gerrit-review.googlesource.com/c/gerrit/+/243179.
Change-Id: I97cb3779117d9b29b40e1107e39d6d1c953fcfdf
(cherry picked from commit fd41e5566f
)
1840 lines
66 KiB
HTML
1840 lines
66 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-change-view</title>
|
||
<script src="/test/common-test-setup.js"></script>
|
||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||
|
||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.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>
|
||
|
||
<link rel="import" href="../../edit/gr-edit-constants.html">
|
||
<link rel="import" href="gr-change-view.html">
|
||
|
||
<script>void(0);</script>
|
||
|
||
<test-fixture id="basic">
|
||
<template>
|
||
<gr-change-view></gr-change-view>
|
||
</template>
|
||
</test-fixture>
|
||
|
||
<test-fixture id="blank">
|
||
<template>
|
||
<div></div>
|
||
</template>
|
||
</test-fixture>
|
||
|
||
<script>
|
||
suite('gr-change-view tests', () => {
|
||
const kb = window.Gerrit.KeyboardShortcutBinder;
|
||
kb.bindShortcut(kb.Shortcut.SEND_REPLY, 'ctrl+enter');
|
||
kb.bindShortcut(kb.Shortcut.REFRESH_CHANGE, 'shift+r');
|
||
kb.bindShortcut(kb.Shortcut.OPEN_REPLY_DIALOG, 'a');
|
||
kb.bindShortcut(kb.Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
|
||
kb.bindShortcut(kb.Shortcut.TOGGLE_DIFF_MODE, 'm');
|
||
kb.bindShortcut(kb.Shortcut.TOGGLE_CHANGE_STAR, 's');
|
||
kb.bindShortcut(kb.Shortcut.UP_TO_DASHBOARD, 'u');
|
||
kb.bindShortcut(kb.Shortcut.EXPAND_ALL_MESSAGES, 'x');
|
||
kb.bindShortcut(kb.Shortcut.COLLAPSE_ALL_MESSAGES, 'z');
|
||
kb.bindShortcut(kb.Shortcut.OPEN_DIFF_PREFS, ',');
|
||
kb.bindShortcut(kb.Shortcut.EDIT_TOPIC, 't');
|
||
|
||
let element;
|
||
let sandbox;
|
||
let navigateToChangeStub;
|
||
const TEST_SCROLL_TOP_PX = 100;
|
||
|
||
setup(() => {
|
||
sandbox = sinon.sandbox.create();
|
||
stub('gr-endpoint-decorator', {
|
||
_import: sandbox.stub().returns(Promise.resolve()),
|
||
});
|
||
// Since _endpoints are global, must reset state.
|
||
Gerrit._endpoints = new GrPluginEndpoints();
|
||
navigateToChangeStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
||
stub('gr-rest-api-interface', {
|
||
getConfig() { return Promise.resolve({test: 'config'}); },
|
||
getAccount() { return Promise.resolve(null); },
|
||
getDiffComments() { return Promise.resolve({}); },
|
||
getDiffRobotComments() { return Promise.resolve({}); },
|
||
getDiffDrafts() { return Promise.resolve({}); },
|
||
_fetchSharedCacheURL() { return Promise.resolve({}); },
|
||
});
|
||
element = fixture('basic');
|
||
sandbox.stub(element.$.actions, 'reload').returns(Promise.resolve());
|
||
Gerrit._loadPlugins([]);
|
||
});
|
||
|
||
teardown(done => {
|
||
flush(() => {
|
||
sandbox.restore();
|
||
done();
|
||
});
|
||
});
|
||
|
||
getCustomCssValue = cssParam => {
|
||
return util.getComputedStyleValue(cssParam, element);
|
||
};
|
||
|
||
test('_handleMessageAnchorTap', () => {
|
||
element._changeNum = '1';
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
const getUrlStub = sandbox.stub(Gerrit.Nav, 'getUrlForChange');
|
||
const replaceStateStub = sandbox.stub(history, 'replaceState');
|
||
element._handleMessageAnchorTap({detail: {id: 'a12345'}});
|
||
|
||
assert.equal(getUrlStub.lastCall.args[4], '#message-a12345');
|
||
assert.isTrue(replaceStateStub.called);
|
||
});
|
||
|
||
suite('keyboard shortcuts', () => {
|
||
test('t to add topic', () => {
|
||
const editStub = sandbox.stub(element.$.metadata, 'editTopic');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 83, null, 't');
|
||
assert(editStub.called);
|
||
});
|
||
|
||
test('S should toggle the CL star', () => {
|
||
const starStub = sandbox.stub(element.$.changeStar, 'toggleStar');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 83, null, 's');
|
||
assert(starStub.called);
|
||
});
|
||
|
||
test('U should navigate to root if no backPage set', () => {
|
||
const relativeNavStub = sandbox.stub(Gerrit.Nav,
|
||
'navigateToRelativeUrl');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
|
||
assert.isTrue(relativeNavStub.called);
|
||
assert.isTrue(relativeNavStub.lastCall.calledWithExactly(
|
||
Gerrit.Nav.getUrlForRoot()));
|
||
});
|
||
|
||
test('U should navigate to backPage if set', () => {
|
||
const relativeNavStub = sandbox.stub(Gerrit.Nav,
|
||
'navigateToRelativeUrl');
|
||
element.backPage = '/dashboard/self';
|
||
MockInteractions.pressAndReleaseKeyOn(element, 85, null, 'u');
|
||
assert.isTrue(relativeNavStub.called);
|
||
assert.isTrue(relativeNavStub.lastCall.calledWithExactly(
|
||
'/dashboard/self'));
|
||
});
|
||
|
||
test('A fires an error event when not logged in', done => {
|
||
sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(false));
|
||
const loggedInErrorSpy = sandbox.spy();
|
||
element.addEventListener('show-auth-required', loggedInErrorSpy);
|
||
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
||
flush(() => {
|
||
assert.isFalse(element.$.replyOverlay.opened);
|
||
assert.isTrue(loggedInErrorSpy.called);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('shift A does not open reply overlay', done => {
|
||
sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
|
||
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift', 'a');
|
||
flush(() => {
|
||
assert.isFalse(element.$.replyOverlay.opened);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('A toggles overlay when logged in', done => {
|
||
sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
|
||
sandbox.stub(element.$.replyDialog, 'fetchChangeUpdates')
|
||
.returns(Promise.resolve({isLatest: true}));
|
||
element._change = {labels: {}};
|
||
const openSpy = sandbox.spy(element, '_openReplyDialog');
|
||
|
||
MockInteractions.pressAndReleaseKeyOn(element, 65, null, 'a');
|
||
flush(() => {
|
||
assert.isTrue(element.$.replyOverlay.opened);
|
||
element.$.replyOverlay.close();
|
||
assert.isFalse(element.$.replyOverlay.opened);
|
||
assert(openSpy.lastCall.calledWithExactly(
|
||
element.$.replyDialog.FocusTarget.ANY),
|
||
'_openReplyDialog should have been passed ANY');
|
||
assert.equal(openSpy.callCount, 1);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('fullscreen-overlay-opened hides content', () => {
|
||
element._loggedIn = true;
|
||
element._loading = false;
|
||
element._change = {
|
||
owner: {_account_id: 1},
|
||
labels: {},
|
||
actions: {
|
||
abandon: {
|
||
enabled: true,
|
||
label: 'Abandon',
|
||
method: 'POST',
|
||
title: 'Abandon',
|
||
},
|
||
},
|
||
};
|
||
sandbox.spy(element, '_handleHideBackgroundContent');
|
||
element.$.replyDialog.fire('fullscreen-overlay-opened');
|
||
assert.isTrue(element._handleHideBackgroundContent.called);
|
||
assert.isTrue(element.$.mainContent.classList.contains('overlayOpen'));
|
||
assert.equal(getComputedStyle(element.$.actions).display, 'flex');
|
||
});
|
||
|
||
test('fullscreen-overlay-closed shows content', () => {
|
||
element._loggedIn = true;
|
||
element._loading = false;
|
||
element._change = {
|
||
owner: {_account_id: 1},
|
||
labels: {},
|
||
actions: {
|
||
abandon: {
|
||
enabled: true,
|
||
label: 'Abandon',
|
||
method: 'POST',
|
||
title: 'Abandon',
|
||
},
|
||
},
|
||
};
|
||
sandbox.spy(element, '_handleShowBackgroundContent');
|
||
element.$.replyDialog.fire('fullscreen-overlay-closed');
|
||
assert.isTrue(element._handleShowBackgroundContent.called);
|
||
assert.isFalse(element.$.mainContent.classList.contains('overlayOpen'));
|
||
});
|
||
|
||
test('expand all messages when expand-diffs fired', () => {
|
||
const handleExpand =
|
||
sandbox.stub(element.$.fileList, 'expandAllDiffs');
|
||
element.$.fileListHeader.fire('expand-diffs');
|
||
assert.isTrue(handleExpand.called);
|
||
});
|
||
|
||
test('collapse all messages when collapse-diffs fired', () => {
|
||
const handleCollapse =
|
||
sandbox.stub(element.$.fileList, 'collapseAllDiffs');
|
||
element.$.fileListHeader.fire('collapse-diffs');
|
||
assert.isTrue(handleCollapse.called);
|
||
});
|
||
|
||
test('X should expand all messages', done => {
|
||
flush(() => {
|
||
const handleExpand = sandbox.stub(element.messagesList,
|
||
'handleExpandCollapse');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 88, null, 'x');
|
||
assert(handleExpand.calledWith(true));
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('Z should collapse all messages', done => {
|
||
flush(() => {
|
||
const handleExpand = sandbox.stub(element.messagesList,
|
||
'handleExpandCollapse');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 90, null, 'z');
|
||
assert(handleExpand.calledWith(false));
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('shift + R should fetch and navigate to the latest patch set',
|
||
done => {
|
||
element._changeNum = '42';
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
_number: 42,
|
||
revisions: {
|
||
rev1: {_number: 1, commit: {parents: []}},
|
||
},
|
||
current_revision: 'rev1',
|
||
status: 'NEW',
|
||
labels: {},
|
||
actions: {},
|
||
};
|
||
|
||
navigateToChangeStub.restore();
|
||
navigateToChangeStub = sandbox.stub(Gerrit.Nav, 'navigateToChange',
|
||
(change, patchNum, basePatchNum) => {
|
||
assert.equal(change, element._change);
|
||
assert.isUndefined(patchNum);
|
||
assert.isUndefined(basePatchNum);
|
||
done();
|
||
});
|
||
|
||
MockInteractions.pressAndReleaseKeyOn(element, 82, 'shift', 'r');
|
||
});
|
||
|
||
test('d should open download overlay', () => {
|
||
const stub = sandbox.stub(element.$.downloadOverlay, 'open');
|
||
MockInteractions.pressAndReleaseKeyOn(element, 68, null, 'd');
|
||
assert.isTrue(stub.called);
|
||
});
|
||
|
||
test(', should open diff preferences', () => {
|
||
const stub = sandbox.stub(
|
||
element.$.fileList.$.diffPreferencesDialog, 'open');
|
||
element._loggedIn = false;
|
||
element.disableDiffPrefs = true;
|
||
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
||
assert.isFalse(stub.called);
|
||
|
||
element._loggedIn = true;
|
||
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
||
assert.isFalse(stub.called);
|
||
|
||
element.disableDiffPrefs = false;
|
||
MockInteractions.pressAndReleaseKeyOn(element, 188, null, ',');
|
||
assert.isTrue(stub.called);
|
||
});
|
||
|
||
test('m should toggle diff mode', () => {
|
||
sandbox.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
|
||
const setModeStub = sandbox.stub(element.$.fileListHeader,
|
||
'setDiffViewMode');
|
||
const e = {preventDefault: () => {}};
|
||
flushAsynchronousOperations();
|
||
|
||
element.viewState.diffMode = 'SIDE_BY_SIDE';
|
||
element._handleToggleDiffMode(e);
|
||
assert.isTrue(setModeStub.calledWith('UNIFIED_DIFF'));
|
||
|
||
element.viewState.diffMode = 'UNIFIED_DIFF';
|
||
element._handleToggleDiffMode(e);
|
||
assert.isTrue(setModeStub.calledWith('SIDE_BY_SIDE'));
|
||
});
|
||
});
|
||
|
||
suite('reloading drafts', () => {
|
||
let reloadStub;
|
||
const drafts = {
|
||
'testfile.txt': [
|
||
{
|
||
patch_set: 5,
|
||
id: 'dd2982f5_c01c9e6a',
|
||
line: 1,
|
||
updated: '2017-11-08 18:47:45.000000000',
|
||
message: 'test',
|
||
unresolved: true,
|
||
},
|
||
],
|
||
};
|
||
setup(() => {
|
||
// Fake computeDraftCount as its required for ChangeComments,
|
||
// see gr-comment-api#reloadDrafts.
|
||
reloadStub = sandbox.stub(element.$.commentAPI, 'reloadDrafts')
|
||
.returns(Promise.resolve({drafts, computeDraftCount: () => 1}));
|
||
});
|
||
|
||
test('drafts are reloaded when reload-drafts fired', done => {
|
||
element.$.fileList.fire('reload-drafts', {
|
||
resolve: () => {
|
||
assert.isTrue(reloadStub.called);
|
||
assert.deepEqual(element._diffDrafts, drafts);
|
||
done();
|
||
},
|
||
});
|
||
});
|
||
|
||
test('drafts are reloaded when comment-refresh fired', () => {
|
||
element.fire('comment-refresh');
|
||
assert.isTrue(reloadStub.called);
|
||
});
|
||
});
|
||
|
||
test('diff comments modified', () => {
|
||
sandbox.spy(element, '_handleReloadCommentThreads');
|
||
return element._reloadComments().then(() => {
|
||
element.fire('diff-comments-modified');
|
||
assert.isTrue(element._handleReloadCommentThreads.called);
|
||
});
|
||
});
|
||
|
||
test('thread list modified', () => {
|
||
sandbox.spy(element, '_handleReloadDiffComments');
|
||
element._showMessagesView = false;
|
||
flushAsynchronousOperations();
|
||
|
||
return element._reloadComments().then(() => {
|
||
element.threadList.fire('thread-list-modified');
|
||
assert.isTrue(element._handleReloadDiffComments.called);
|
||
|
||
let draftStub = sinon.stub(element._changeComments, 'computeDraftCount')
|
||
.returns(1);
|
||
assert.equal(element._computeTotalCommentCounts(5,
|
||
element._changeComments), '5 unresolved, 1 draft');
|
||
assert.equal(element._computeTotalCommentCounts(0,
|
||
element._changeComments), '1 draft');
|
||
draftStub.restore();
|
||
draftStub = sinon.stub(element._changeComments, 'computeDraftCount')
|
||
.returns(0);
|
||
assert.equal(element._computeTotalCommentCounts(0,
|
||
element._changeComments), '');
|
||
assert.equal(element._computeTotalCommentCounts(1,
|
||
element._changeComments), '1 unresolved');
|
||
draftStub.restore();
|
||
draftStub = sinon.stub(element._changeComments, 'computeDraftCount')
|
||
.returns(2);
|
||
assert.equal(element._computeTotalCommentCounts(1,
|
||
element._changeComments), '1 unresolved, 2 drafts');
|
||
draftStub.restore();
|
||
});
|
||
});
|
||
|
||
test('thread list and change log tabs', done => {
|
||
element._changeNum = '1';
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
revisions: {
|
||
rev2: {_number: 2, commit: {parents: []}},
|
||
rev1: {_number: 1, commit: {parents: []}},
|
||
rev13: {_number: 13, commit: {parents: []}},
|
||
rev3: {_number: 3, commit: {parents: []}},
|
||
},
|
||
current_revision: 'rev3',
|
||
status: 'NEW',
|
||
labels: {
|
||
test: {
|
||
all: [],
|
||
default_value: 0,
|
||
values: [],
|
||
approved: {},
|
||
},
|
||
},
|
||
};
|
||
sandbox.stub(element.$.relatedChanges, 'reload');
|
||
sandbox.stub(element, '_reload').returns(Promise.resolve());
|
||
sandbox.spy(element, '_paramsChanged');
|
||
element.params = {view: 'change', changeNum: '1'};
|
||
|
||
// When the change is hard reloaded, paramsChanged will not set the tab.
|
||
// It will be set in postLoadTasks, which requires the flush() to detect.
|
||
assert.isTrue(element._paramsChanged.called);
|
||
assert.isUndefined(element.$.commentTabs.selected);
|
||
|
||
// Wait for tab to get selected
|
||
flush(() => {
|
||
assert.equal(element.$.commentTabs.selected, 0);
|
||
assert.isTrue(element._showMessagesView);
|
||
// Switch to comment thread tab
|
||
MockInteractions.tap(element.$$('paper-tab.commentThreads'));
|
||
assert.equal(element.$.commentTabs.selected, 1);
|
||
assert.isFalse(element._showMessagesView);
|
||
|
||
// When the change is partially reloaded (ex: Shift+R), the content
|
||
// is swapped out before the tab, so messages list will display even
|
||
// though the tab for comment threads is still temporarily selected.
|
||
element._paramsChanged(element.params);
|
||
assert.equal(element.$.commentTabs.selected, 1);
|
||
assert.isTrue(element._showMessagesView);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('reply button is not visible when logged out', () => {
|
||
assert.equal(getComputedStyle(element.$.replyBtn).display, 'none');
|
||
element._loggedIn = true;
|
||
assert.notEqual(getComputedStyle(element.$.replyBtn).display, 'none');
|
||
});
|
||
|
||
test('download tap calls _handleOpenDownloadDialog', () => {
|
||
sandbox.stub(element, '_handleOpenDownloadDialog');
|
||
element.$.actions.fire('download-tap');
|
||
assert.isTrue(element._handleOpenDownloadDialog.called);
|
||
});
|
||
|
||
test('fetches the server config on attached', done => {
|
||
flush(() => {
|
||
assert.equal(element._serverConfig.test, 'config');
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('_changeStatuses', () => {
|
||
sandbox.stub(element, 'changeStatuses').returns(
|
||
['Merged', 'WIP']);
|
||
element._loading = false;
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
revisions: {
|
||
rev2: {_number: 2},
|
||
rev1: {_number: 1},
|
||
rev13: {_number: 13},
|
||
rev3: {_number: 3},
|
||
},
|
||
current_revision: 'rev3',
|
||
labels: {
|
||
test: {
|
||
all: [],
|
||
default_value: 0,
|
||
values: [],
|
||
approved: {},
|
||
},
|
||
},
|
||
};
|
||
element._mergeable = true;
|
||
expectedStatuses = ['Merged', 'WIP'];
|
||
assert.deepEqual(element._changeStatuses, expectedStatuses);
|
||
assert.equal(element._changeStatus, expectedStatuses.join(', '));
|
||
flushAsynchronousOperations();
|
||
const statusChips = Polymer.dom(element.root)
|
||
.querySelectorAll('gr-change-status');
|
||
assert.equal(statusChips.length, 2);
|
||
});
|
||
|
||
test('diff preferences open when open-diff-prefs is fired', () => {
|
||
const overlayOpenStub = sandbox.stub(element.$.fileList,
|
||
'openDiffPrefs');
|
||
element.$.fileListHeader.fire('open-diff-prefs');
|
||
assert.isTrue(overlayOpenStub.called);
|
||
});
|
||
|
||
test('_prepareCommitMsgForLinkify', () => {
|
||
let commitMessage = 'R=test@google.com';
|
||
let result = element._prepareCommitMsgForLinkify(commitMessage);
|
||
assert.equal(result, 'R=\u200Btest@google.com');
|
||
|
||
commitMessage = 'R=test@google.com\nR=test@google.com';
|
||
result = element._prepareCommitMsgForLinkify(commitMessage);
|
||
assert.equal(result, 'R=\u200Btest@google.com\nR=\u200Btest@google.com');
|
||
|
||
commitMessage = 'CC=test@google.com';
|
||
result = element._prepareCommitMsgForLinkify(commitMessage);
|
||
assert.equal(result, 'CC=\u200Btest@google.com');
|
||
}),
|
||
|
||
test('_isSubmitEnabled', () => {
|
||
assert.isFalse(element._isSubmitEnabled({}));
|
||
assert.isFalse(element._isSubmitEnabled({submit: {}}));
|
||
assert.isTrue(element._isSubmitEnabled(
|
||
{submit: {enabled: true}}));
|
||
});
|
||
|
||
test('_reload is called when an approved label is removed', () => {
|
||
const vote = {_account_id: 1, name: 'bojack', value: 1};
|
||
element._changeNum = '42';
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
owner: {email: 'abc@def'},
|
||
revisions: {
|
||
rev2: {_number: 2, commit: {parents: []}},
|
||
rev1: {_number: 1, commit: {parents: []}},
|
||
rev13: {_number: 13, commit: {parents: []}},
|
||
rev3: {_number: 3, commit: {parents: []}},
|
||
},
|
||
current_revision: 'rev3',
|
||
status: 'NEW',
|
||
labels: {
|
||
test: {
|
||
all: [vote],
|
||
default_value: 0,
|
||
values: [],
|
||
approved: {},
|
||
},
|
||
},
|
||
};
|
||
flushAsynchronousOperations();
|
||
const reloadStub = sandbox.stub(element, '_reload');
|
||
element.splice('_change.labels.test.all', 0, 1);
|
||
assert.isFalse(reloadStub.called);
|
||
element._change.labels.test.all.push(vote);
|
||
element._change.labels.test.all.push(vote);
|
||
element._change.labels.test.approved = vote;
|
||
flushAsynchronousOperations();
|
||
element.splice('_change.labels.test.all', 0, 2);
|
||
assert.isTrue(reloadStub.called);
|
||
assert.isTrue(reloadStub.calledOnce);
|
||
});
|
||
|
||
test('reply button has updated count when there are drafts', () => {
|
||
const getLabel = element._computeReplyButtonLabel;
|
||
|
||
assert.equal(getLabel(null, false), 'Reply');
|
||
assert.equal(getLabel(null, true), 'Start review');
|
||
|
||
const changeRecord = {base: null};
|
||
assert.equal(getLabel(changeRecord, false), 'Reply');
|
||
|
||
changeRecord.base = {};
|
||
assert.equal(getLabel(changeRecord, false), 'Reply');
|
||
|
||
changeRecord.base = {
|
||
'file1.txt': [{}],
|
||
'file2.txt': [{}, {}],
|
||
};
|
||
assert.equal(getLabel(changeRecord, false), 'Reply (3)');
|
||
});
|
||
|
||
test('start review button when owner of WIP change', () => {
|
||
assert.equal(
|
||
element._computeReplyButtonLabel(null, true),
|
||
'Start review');
|
||
});
|
||
|
||
test('comment events properly update diff drafts', () => {
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 2,
|
||
};
|
||
const draft = {
|
||
__draft: true,
|
||
id: 'id1',
|
||
path: '/foo/bar.txt',
|
||
text: 'hello',
|
||
};
|
||
element._handleCommentSave({detail: {comment: draft}});
|
||
draft.patch_set = 2;
|
||
assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]});
|
||
draft.patch_set = null;
|
||
draft.text = 'hello, there';
|
||
element._handleCommentSave({detail: {comment: draft}});
|
||
draft.patch_set = 2;
|
||
assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft]});
|
||
const draft2 = {
|
||
__draft: true,
|
||
id: 'id2',
|
||
path: '/foo/bar.txt',
|
||
text: 'hola',
|
||
};
|
||
element._handleCommentSave({detail: {comment: draft2}});
|
||
draft2.patch_set = 2;
|
||
assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft, draft2]});
|
||
draft.patch_set = null;
|
||
element._handleCommentDiscard({detail: {comment: draft}});
|
||
draft.patch_set = 2;
|
||
assert.deepEqual(element._diffDrafts, {'/foo/bar.txt': [draft2]});
|
||
element._handleCommentDiscard({detail: {comment: draft2}});
|
||
assert.deepEqual(element._diffDrafts, {});
|
||
});
|
||
|
||
test('change num change', () => {
|
||
element._changeNum = null;
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 2,
|
||
};
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
labels: {},
|
||
};
|
||
element.viewState.changeNum = null;
|
||
element.viewState.diffMode = 'UNIFIED';
|
||
assert.equal(element.viewState.numFilesShown, 200);
|
||
assert.equal(element._numFilesShown, 200);
|
||
element._numFilesShown = 150;
|
||
flushAsynchronousOperations();
|
||
assert.equal(element.viewState.diffMode, 'UNIFIED');
|
||
assert.equal(element.viewState.numFilesShown, 150);
|
||
|
||
element._changeNum = '1';
|
||
element.params = {changeNum: '1'};
|
||
element._change.newProp = '1';
|
||
flushAsynchronousOperations();
|
||
assert.equal(element.viewState.diffMode, 'UNIFIED');
|
||
assert.equal(element.viewState.changeNum, '1');
|
||
|
||
element._changeNum = '2';
|
||
element.params = {changeNum: '2'};
|
||
element._change.newProp = '2';
|
||
flushAsynchronousOperations();
|
||
assert.equal(element.viewState.diffMode, 'UNIFIED');
|
||
assert.equal(element.viewState.changeNum, '2');
|
||
assert.equal(element.viewState.numFilesShown, 200);
|
||
assert.equal(element._numFilesShown, 200);
|
||
});
|
||
|
||
test('_setDiffViewMode is called with reset when new change is loaded',
|
||
() => {
|
||
sandbox.stub(element, '_setDiffViewMode');
|
||
element.viewState = {changeNum: 1};
|
||
element._changeNum = 2;
|
||
element._resetFileListViewState();
|
||
assert.isTrue(
|
||
element._setDiffViewMode.lastCall.calledWithExactly(true));
|
||
});
|
||
|
||
test('diffViewMode is propagated from file list header', () => {
|
||
element.viewState = {diffMode: 'UNIFIED'};
|
||
element.$.fileListHeader.diffViewMode = 'SIDE_BY_SIDE';
|
||
assert.equal(element.viewState.diffMode, 'SIDE_BY_SIDE');
|
||
});
|
||
|
||
test('diffMode defaults to side by side without preferences', done => {
|
||
sandbox.stub(element.$.restAPI, 'getPreferences').returns(
|
||
Promise.resolve({}));
|
||
// No user prefs or diff view mode set.
|
||
|
||
element._setDiffViewMode().then(() => {
|
||
assert.equal(element.viewState.diffMode, 'SIDE_BY_SIDE');
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('diffMode defaults to preference when not already set', done => {
|
||
sandbox.stub(element.$.restAPI, 'getPreferences').returns(
|
||
Promise.resolve({default_diff_view: 'UNIFIED'}));
|
||
|
||
element._setDiffViewMode().then(() => {
|
||
assert.equal(element.viewState.diffMode, 'UNIFIED');
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('existing diffMode overrides preference', done => {
|
||
element.viewState.diffMode = 'SIDE_BY_SIDE';
|
||
sandbox.stub(element.$.restAPI, 'getPreferences').returns(
|
||
Promise.resolve({default_diff_view: 'UNIFIED'}));
|
||
element._setDiffViewMode().then(() => {
|
||
assert.equal(element.viewState.diffMode, 'SIDE_BY_SIDE');
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('don’t reload entire page when patchRange changes', () => {
|
||
const reloadStub = sandbox.stub(element, '_reload',
|
||
() => { return Promise.resolve(); });
|
||
const reloadPatchDependentStub = sandbox.stub(element,
|
||
'_reloadPatchNumDependentResources',
|
||
() => { return Promise.resolve(); });
|
||
const relatedClearSpy = sandbox.spy(element.$.relatedChanges, 'clear');
|
||
const collapseStub = sandbox.stub(element.$.fileList, 'collapseAllDiffs');
|
||
|
||
const value = {
|
||
view: Gerrit.Nav.View.CHANGE,
|
||
patchNum: '1',
|
||
};
|
||
element._paramsChanged(value);
|
||
assert.isTrue(reloadStub.calledOnce);
|
||
assert.isTrue(relatedClearSpy.calledOnce);
|
||
|
||
element._initialLoadComplete = true;
|
||
|
||
value.basePatchNum = '1';
|
||
value.patchNum = '2';
|
||
element._paramsChanged(value);
|
||
assert.isFalse(reloadStub.calledTwice);
|
||
assert.isTrue(reloadPatchDependentStub.calledOnce);
|
||
assert.isTrue(relatedClearSpy.calledOnce);
|
||
assert.isTrue(collapseStub.calledTwice);
|
||
});
|
||
|
||
test('reload entire page when patchRange doesnt change', () => {
|
||
const reloadStub = sandbox.stub(element, '_reload',
|
||
() => { return Promise.resolve(); });
|
||
const collapseStub = sandbox.stub(element.$.fileList, 'collapseAllDiffs');
|
||
const value = {
|
||
view: Gerrit.Nav.View.CHANGE,
|
||
};
|
||
element._paramsChanged(value);
|
||
assert.isTrue(reloadStub.calledOnce);
|
||
element._initialLoadComplete = true;
|
||
element._paramsChanged(value);
|
||
assert.isTrue(reloadStub.calledTwice);
|
||
assert.isTrue(collapseStub.calledTwice);
|
||
});
|
||
|
||
test('related changes are updated and new patch selected after rebase',
|
||
done => {
|
||
element._changeNum = '42';
|
||
sandbox.stub(element, 'computeLatestPatchNum', () => {
|
||
return 1;
|
||
});
|
||
sandbox.stub(element, '_reload',
|
||
() => { return Promise.resolve(); });
|
||
const e = {detail: {action: 'rebase'}};
|
||
element._handleReloadChange(e).then(() => {
|
||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||
element._change));
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('related changes are not updated after other action', done => {
|
||
sandbox.stub(element, '_reload', () => { return Promise.resolve(); });
|
||
sandbox.stub(element.$.relatedChanges, 'reload');
|
||
const e = {detail: {action: 'abandon'}};
|
||
element._handleReloadChange(e).then(() => {
|
||
assert.isFalse(navigateToChangeStub.called);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('_computeMergedCommitInfo', () => {
|
||
const dummyRevs = {
|
||
1: {commit: {commit: 1}},
|
||
2: {commit: {}},
|
||
};
|
||
assert.deepEqual(element._computeMergedCommitInfo(0, dummyRevs), {});
|
||
assert.deepEqual(element._computeMergedCommitInfo(1, dummyRevs),
|
||
dummyRevs[1].commit);
|
||
|
||
// Regression test for issue 5337.
|
||
const commit = element._computeMergedCommitInfo(2, dummyRevs);
|
||
assert.notDeepEqual(commit, dummyRevs[2]);
|
||
assert.deepEqual(commit, {commit: 2});
|
||
});
|
||
|
||
test('get latest revision', () => {
|
||
let change = {
|
||
revisions: {
|
||
rev1: {_number: 1},
|
||
rev3: {_number: 3},
|
||
},
|
||
current_revision: 'rev3',
|
||
};
|
||
assert.equal(element._getLatestRevisionSHA(change), 'rev3');
|
||
change = {
|
||
revisions: {
|
||
rev1: {_number: 1},
|
||
},
|
||
};
|
||
assert.equal(element._getLatestRevisionSHA(change), 'rev1');
|
||
});
|
||
|
||
test('show commit message edit button', () => {
|
||
const _change = {
|
||
status: element.ChangeStatus.MERGED,
|
||
};
|
||
assert.isTrue(element._computeHideEditCommitMessage(false, false, {}));
|
||
assert.isTrue(element._computeHideEditCommitMessage(true, true, {}));
|
||
assert.isTrue(element._computeHideEditCommitMessage(false, true, {}));
|
||
assert.isFalse(element._computeHideEditCommitMessage(true, false, {}));
|
||
assert.isTrue(element._computeHideEditCommitMessage(true, false,
|
||
_change));
|
||
assert.isTrue(element._computeHideEditCommitMessage(true, false, {},
|
||
true));
|
||
assert.isFalse(element._computeHideEditCommitMessage(true, false, {},
|
||
false));
|
||
});
|
||
|
||
test('_handleCommitMessageSave trims trailing whitespace', () => {
|
||
const putStub = sandbox.stub(element.$.restAPI, 'putChangeCommitMessage')
|
||
.returns(Promise.resolve({}));
|
||
|
||
const mockEvent = content => { return {detail: {content}}; };
|
||
|
||
element._handleCommitMessageSave(mockEvent('test \n test '));
|
||
assert.equal(putStub.lastCall.args[1], 'test\n test');
|
||
|
||
element._handleCommitMessageSave(mockEvent(' test\ntest'));
|
||
assert.equal(putStub.lastCall.args[1], ' test\ntest');
|
||
|
||
element._handleCommitMessageSave(mockEvent('\n\n\n\n\n\n\n\n'));
|
||
assert.equal(putStub.lastCall.args[1], '\n\n\n\n\n\n\n\n');
|
||
});
|
||
|
||
test('_computeChangeIdCommitMessageError', () => {
|
||
let commitMessage =
|
||
'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483';
|
||
let change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
null);
|
||
|
||
change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
'mismatch');
|
||
|
||
commitMessage = 'This is the greatest change.';
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
'missing');
|
||
});
|
||
|
||
test('multiple change Ids in commit message picks last', () => {
|
||
const commitMessage = [
|
||
'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282484',
|
||
'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483',
|
||
].join('\n');
|
||
let change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
null);
|
||
change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
'mismatch');
|
||
});
|
||
|
||
test('does not count change Id that starts mid line', () => {
|
||
const commitMessage = [
|
||
'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282484',
|
||
'Change-Id: I4ce18b2395bca69d7a9aa48bf4554faa56282483',
|
||
].join(' and ');
|
||
let change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282484'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
null);
|
||
change = {change_id: 'I4ce18b2395bca69d7a9aa48bf4554faa56282483'};
|
||
assert.equal(
|
||
element._computeChangeIdCommitMessageError(commitMessage, change),
|
||
'mismatch');
|
||
});
|
||
|
||
test('_computeTitleAttributeWarning', () => {
|
||
let changeIdCommitMessageError = 'missing';
|
||
assert.equal(
|
||
element._computeTitleAttributeWarning(changeIdCommitMessageError),
|
||
'No Change-Id in commit message');
|
||
|
||
changeIdCommitMessageError = 'mismatch';
|
||
assert.equal(
|
||
element._computeTitleAttributeWarning(changeIdCommitMessageError),
|
||
'Change-Id mismatch');
|
||
});
|
||
|
||
test('_computeChangeIdClass', () => {
|
||
let changeIdCommitMessageError = 'missing';
|
||
assert.equal(
|
||
element._computeChangeIdClass(changeIdCommitMessageError), '');
|
||
|
||
changeIdCommitMessageError = 'mismatch';
|
||
assert.equal(
|
||
element._computeChangeIdClass(changeIdCommitMessageError), 'warning');
|
||
});
|
||
|
||
test('topic is coalesced to null', done => {
|
||
sandbox.stub(element, '_changeChanged');
|
||
sandbox.stub(element.$.restAPI, 'getChangeDetail', () => {
|
||
return Promise.resolve({
|
||
id: '123456789',
|
||
labels: {},
|
||
current_revision: 'foo',
|
||
revisions: {foo: {commit: {}}},
|
||
});
|
||
});
|
||
|
||
element._getChangeDetail().then(() => {
|
||
assert.isNull(element._change.topic);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('commit sha is populated from getChangeDetail', done => {
|
||
sandbox.stub(element, '_changeChanged');
|
||
sandbox.stub(element.$.restAPI, 'getChangeDetail', () => {
|
||
return Promise.resolve({
|
||
id: '123456789',
|
||
labels: {},
|
||
current_revision: 'foo',
|
||
revisions: {foo: {commit: {}}},
|
||
});
|
||
});
|
||
|
||
element._getChangeDetail().then(() => {
|
||
assert.equal('foo', element._commitInfo.commit);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('edit is added to change', () => {
|
||
sandbox.stub(element, '_changeChanged');
|
||
sandbox.stub(element.$.restAPI, 'getChangeDetail', () => {
|
||
return Promise.resolve({
|
||
id: '123456789',
|
||
labels: {},
|
||
current_revision: 'foo',
|
||
revisions: {foo: {commit: {}}},
|
||
});
|
||
});
|
||
sandbox.stub(element, '_getEdit', () => {
|
||
return Promise.resolve({
|
||
base_patch_set_number: 1,
|
||
commit: {commit: 'bar'},
|
||
});
|
||
});
|
||
element._patchRange = {};
|
||
|
||
return element._getChangeDetail().then(() => {
|
||
const revs = element._change.revisions;
|
||
assert.equal(Object.keys(revs).length, 2);
|
||
assert.deepEqual(revs['foo'], {commit: {commit: 'foo'}});
|
||
assert.deepEqual(revs['bar'], {
|
||
_number: element.EDIT_NAME,
|
||
basePatchNum: 1,
|
||
commit: {commit: 'bar'},
|
||
fetch: undefined,
|
||
});
|
||
});
|
||
});
|
||
|
||
test('_getBasePatchNum', () => {
|
||
const _change = {
|
||
_number: 42,
|
||
revisions: {
|
||
'98da160735fb81604b4c40e93c368f380539dd0e': {
|
||
_number: 1,
|
||
commit: {
|
||
parents: [],
|
||
},
|
||
},
|
||
},
|
||
};
|
||
const _patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
};
|
||
assert.equal(element._getBasePatchNum(_change, _patchRange), 'PARENT');
|
||
|
||
element._prefs = {
|
||
default_base_for_merges: 'FIRST_PARENT',
|
||
};
|
||
|
||
const _change2 = {
|
||
_number: 42,
|
||
revisions: {
|
||
'98da160735fb81604b4c40e93c368f380539dd0e': {
|
||
_number: 1,
|
||
commit: {
|
||
parents: [
|
||
{
|
||
commit: '6e12bdf1176eb4ab24d8491ba3b6d0704409cde8',
|
||
subject: 'test',
|
||
},
|
||
{
|
||
commit: '22f7db4754b5d9816fc581f3d9a6c0ef8429c841',
|
||
subject: 'test3',
|
||
},
|
||
],
|
||
},
|
||
},
|
||
},
|
||
};
|
||
assert.equal(element._getBasePatchNum(_change2, _patchRange), -1);
|
||
|
||
_patchRange.patchNum = 1;
|
||
assert.equal(element._getBasePatchNum(_change2, _patchRange), 'PARENT');
|
||
});
|
||
|
||
test('_openReplyDialog called with `ANY` when coming from tap event',
|
||
() => {
|
||
const openStub = sandbox.stub(element, '_openReplyDialog');
|
||
element._serverConfig = {};
|
||
MockInteractions.tap(element.$.replyBtn);
|
||
assert(openStub.lastCall.calledWithExactly(
|
||
element.$.replyDialog.FocusTarget.ANY),
|
||
'_openReplyDialog should have been passed ANY');
|
||
assert.equal(openStub.callCount, 1);
|
||
});
|
||
|
||
test('_openReplyDialog called with `BODY` when coming from message reply' +
|
||
'event', done => {
|
||
flush(() => {
|
||
const openStub = sandbox.stub(element, '_openReplyDialog');
|
||
element.messagesList.fire('reply',
|
||
{message: {message: 'text'}});
|
||
assert(openStub.lastCall.calledWithExactly(
|
||
element.$.replyDialog.FocusTarget.BODY),
|
||
'_openReplyDialog should have been passed BODY');
|
||
assert.equal(openStub.callCount, 1);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('reply dialog focus can be controlled', () => {
|
||
const FocusTarget = element.$.replyDialog.FocusTarget;
|
||
const openStub = sandbox.stub(element, '_openReplyDialog');
|
||
|
||
const e = {detail: {}};
|
||
element._handleShowReplyDialog(e);
|
||
assert(openStub.lastCall.calledWithExactly(FocusTarget.REVIEWERS),
|
||
'_openReplyDialog should have been passed REVIEWERS');
|
||
assert.equal(openStub.callCount, 1);
|
||
|
||
e.detail.value = {ccsOnly: true};
|
||
element._handleShowReplyDialog(e);
|
||
assert(openStub.lastCall.calledWithExactly(FocusTarget.CCS),
|
||
'_openReplyDialog should have been passed CCS');
|
||
assert.equal(openStub.callCount, 2);
|
||
});
|
||
|
||
test('getUrlParameter functionality', () => {
|
||
const locationStub = sandbox.stub(element, '_getLocationSearch');
|
||
|
||
locationStub.returns('?test');
|
||
assert.equal(element._getUrlParameter('test'), 'test');
|
||
locationStub.returns('?test2=12&test=3');
|
||
assert.equal(element._getUrlParameter('test'), 'test');
|
||
locationStub.returns('');
|
||
assert.isNull(element._getUrlParameter('test'));
|
||
locationStub.returns('?');
|
||
assert.isNull(element._getUrlParameter('test'));
|
||
locationStub.returns('?test2');
|
||
assert.isNull(element._getUrlParameter('test'));
|
||
});
|
||
|
||
test('revert dialog opened with revert param', done => {
|
||
sandbox.stub(element.$.restAPI, 'getLoggedIn', () => {
|
||
return Promise.resolve(true);
|
||
});
|
||
sandbox.stub(Gerrit, 'awaitPluginsLoaded', () => {
|
||
return Promise.resolve();
|
||
});
|
||
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 2,
|
||
};
|
||
element._change = {
|
||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||
revisions: {
|
||
rev1: {_number: 1, commit: {parents: []}},
|
||
rev2: {_number: 2, commit: {parents: []}},
|
||
},
|
||
current_revision: 'rev1',
|
||
status: element.ChangeStatus.MERGED,
|
||
labels: {},
|
||
actions: {},
|
||
};
|
||
|
||
sandbox.stub(element, '_getUrlParameter',
|
||
param => {
|
||
assert.equal(param, 'revert');
|
||
return param;
|
||
});
|
||
|
||
sandbox.stub(element.$.actions, 'showRevertDialog',
|
||
done);
|
||
|
||
element._maybeShowRevertDialog();
|
||
assert.isTrue(Gerrit.awaitPluginsLoaded.called);
|
||
});
|
||
|
||
suite('scroll related tests', () => {
|
||
test('document scrolling calls function to set scroll height', done => {
|
||
const originalHeight = document.body.scrollHeight;
|
||
const scrollStub = sandbox.stub(element, '_handleScroll',
|
||
() => {
|
||
assert.isTrue(scrollStub.called);
|
||
document.body.style.height = originalHeight + 'px';
|
||
scrollStub.restore();
|
||
done();
|
||
});
|
||
document.body.style.height = '10000px';
|
||
element._handleScroll();
|
||
});
|
||
|
||
test('scrollTop is set correctly', () => {
|
||
element.viewState = {scrollTop: TEST_SCROLL_TOP_PX};
|
||
|
||
sandbox.stub(element, '_reload', () => {
|
||
// When element is reloaded, ensure that the history
|
||
// state has the scrollTop set earlier. This will then
|
||
// be reset.
|
||
assert.isTrue(element.viewState.scrollTop == TEST_SCROLL_TOP_PX);
|
||
return Promise.resolve({});
|
||
});
|
||
|
||
// simulate reloading component, which is done when route
|
||
// changes to match a regex of change view type.
|
||
element._paramsChanged({view: Gerrit.Nav.View.CHANGE});
|
||
});
|
||
|
||
test('scrollTop is reset when new change is loaded', () => {
|
||
element._resetFileListViewState();
|
||
assert.equal(element.viewState.scrollTop, 0);
|
||
});
|
||
});
|
||
|
||
suite('reply dialog tests', () => {
|
||
setup(() => {
|
||
sandbox.stub(element.$.replyDialog, '_draftChanged');
|
||
sandbox.stub(element.$.replyDialog, 'fetchChangeUpdates',
|
||
() => { return Promise.resolve({isLatest: true}); });
|
||
element._change = {labels: {}};
|
||
});
|
||
|
||
test('reply from comment adds quote text', () => {
|
||
const e = {detail: {message: {message: 'quote text'}}};
|
||
element._handleMessageReply(e);
|
||
assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
|
||
});
|
||
|
||
test('reply from comment replaces quote text', () => {
|
||
element.$.replyDialog.draft = '> old quote text\n\n some draft text';
|
||
element.$.replyDialog.quote = '> old quote text\n\n';
|
||
const e = {detail: {message: {message: 'quote text'}}};
|
||
element._handleMessageReply(e);
|
||
assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
|
||
});
|
||
|
||
test('reply from same comment preserves quote text', () => {
|
||
element.$.replyDialog.draft = '> quote text\n\n some draft text';
|
||
element.$.replyDialog.quote = '> quote text\n\n';
|
||
const e = {detail: {message: {message: 'quote text'}}};
|
||
element._handleMessageReply(e);
|
||
assert.equal(element.$.replyDialog.draft,
|
||
'> quote text\n\n some draft text');
|
||
assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
|
||
});
|
||
|
||
test('reply from top of page contains previous draft', () => {
|
||
const div = document.createElement('div');
|
||
element.$.replyDialog.draft = '> quote text\n\n some draft text';
|
||
element.$.replyDialog.quote = '> quote text\n\n';
|
||
const e = {target: div, preventDefault: sandbox.spy()};
|
||
element._handleReplyTap(e);
|
||
assert.equal(element.$.replyDialog.draft,
|
||
'> quote text\n\n some draft text');
|
||
assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
|
||
});
|
||
});
|
||
|
||
test('reply button is disabled until server config is loaded', () => {
|
||
assert.isTrue(element._replyDisabled);
|
||
element._serverConfig = {};
|
||
assert.isFalse(element._replyDisabled);
|
||
});
|
||
|
||
suite('commit message expand/collapse', () => {
|
||
setup(() => {
|
||
sandbox.stub(element, 'fetchChangeUpdates',
|
||
() => { return Promise.resolve({isLatest: false}); });
|
||
});
|
||
|
||
test('commitCollapseToggle hidden for short commit message', () => {
|
||
element._latestCommitMessage = '';
|
||
assert.isTrue(element.$.commitCollapseToggle.hasAttribute('hidden'));
|
||
});
|
||
|
||
test('commitCollapseToggle shown for long commit message', () => {
|
||
element._latestCommitMessage = _.times(31, String).join('\n');
|
||
assert.isFalse(element.$.commitCollapseToggle.hasAttribute('hidden'));
|
||
});
|
||
|
||
test('commitCollapseToggle functions', () => {
|
||
element._latestCommitMessage = _.times(31, String).join('\n');
|
||
assert.isTrue(element._commitCollapsed);
|
||
assert.isTrue(
|
||
element.$.commitMessage.classList.contains('collapsed'));
|
||
MockInteractions.tap(element.$.commitCollapseToggleButton);
|
||
assert.isFalse(element._commitCollapsed);
|
||
assert.isFalse(
|
||
element.$.commitMessage.classList.contains('collapsed'));
|
||
});
|
||
});
|
||
|
||
suite('related changes expand/collapse', () => {
|
||
let updateHeightSpy;
|
||
setup(() => {
|
||
updateHeightSpy = sandbox.spy(element, '_updateRelatedChangeMaxHeight');
|
||
});
|
||
|
||
test('relatedChangesToggle shown height greater than changeInfo height',
|
||
() => {
|
||
assert.isFalse(element.$.relatedChangesToggle.classList
|
||
.contains('showToggle'));
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getScrollHeight', () => 60);
|
||
sandbox.stub(element, '_getLineHeight', () => 5);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: true}));
|
||
element.$.relatedChanges.dispatchEvent(
|
||
new CustomEvent('new-section-loaded'));
|
||
assert.isTrue(element.$.relatedChangesToggle.classList
|
||
.contains('showToggle'));
|
||
assert.equal(updateHeightSpy.callCount, 1);
|
||
});
|
||
|
||
test('relatedChangesToggle hidden height less than changeInfo height',
|
||
() => {
|
||
assert.isFalse(element.$.relatedChangesToggle.classList
|
||
.contains('showToggle'));
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getScrollHeight', () => 40);
|
||
sandbox.stub(element, '_getLineHeight', () => 5);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: true}));
|
||
element.$.relatedChanges.dispatchEvent(
|
||
new CustomEvent('new-section-loaded'));
|
||
assert.isFalse(element.$.relatedChangesToggle.classList
|
||
.contains('showToggle'));
|
||
assert.equal(updateHeightSpy.callCount, 1);
|
||
});
|
||
|
||
test('relatedChangesToggle functions', () => {
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: false}));
|
||
element._relatedChangesLoading = false;
|
||
assert.isTrue(element._relatedChangesCollapsed);
|
||
assert.isTrue(
|
||
element.$.relatedChanges.classList.contains('collapsed'));
|
||
MockInteractions.tap(element.$.relatedChangesToggleButton);
|
||
assert.isFalse(element._relatedChangesCollapsed);
|
||
assert.isFalse(
|
||
element.$.relatedChanges.classList.contains('collapsed'));
|
||
});
|
||
|
||
test('_updateRelatedChangeMaxHeight without commit toggle', () => {
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getLineHeight', () => 12);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: false}));
|
||
|
||
// 50 (existing height) - 30 (extra height) = 20 (adjusted height).
|
||
// 20 (max existing height) % 12 (line height) = 6 (remainder).
|
||
// 20 (adjusted height) - 8 (remainder) = 12 (max height to set).
|
||
|
||
element._updateRelatedChangeMaxHeight();
|
||
assert.equal(getCustomCssValue('--relation-chain-max-height'),
|
||
'12px');
|
||
assert.equal(getCustomCssValue('--related-change-btn-top-padding'),
|
||
'');
|
||
});
|
||
|
||
test('_updateRelatedChangeMaxHeight with commit toggle', () => {
|
||
element._latestCommitMessage = _.times(31, String).join('\n');
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getLineHeight', () => 12);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: false}));
|
||
|
||
// 50 (existing height) % 12 (line height) = 2 (remainder).
|
||
// 50 (existing height) - 2 (remainder) = 48 (max height to set).
|
||
|
||
element._updateRelatedChangeMaxHeight();
|
||
assert.equal(getCustomCssValue('--relation-chain-max-height'),
|
||
'48px');
|
||
assert.equal(getCustomCssValue('--related-change-btn-top-padding'),
|
||
'2px');
|
||
});
|
||
|
||
test('_updateRelatedChangeMaxHeight in small screen mode', () => {
|
||
element._latestCommitMessage = _.times(31, String).join('\n');
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getLineHeight', () => 12);
|
||
sandbox.stub(window, 'matchMedia', () => ({matches: true}));
|
||
|
||
element._updateRelatedChangeMaxHeight();
|
||
|
||
// 400 (new height) % 12 (line height) = 4 (remainder).
|
||
// 400 (new height) - 4 (remainder) = 396.
|
||
|
||
assert.equal(getCustomCssValue('--relation-chain-max-height'),
|
||
'396px');
|
||
});
|
||
|
||
test('_updateRelatedChangeMaxHeight in medium screen mode', () => {
|
||
element._latestCommitMessage = _.times(31, String).join('\n');
|
||
sandbox.stub(element, '_getOffsetHeight', () => 50);
|
||
sandbox.stub(element, '_getLineHeight', () => 12);
|
||
sandbox.stub(window, 'matchMedia', () => {
|
||
if (window.matchMedia.lastCall.args[0] === '(max-width: 75em)') {
|
||
return {matches: true};
|
||
} else {
|
||
return {matches: false};
|
||
}
|
||
});
|
||
|
||
// 100 (new height) % 12 (line height) = 4 (remainder).
|
||
// 100 (new height) - 4 (remainder) = 96.
|
||
element._updateRelatedChangeMaxHeight();
|
||
assert.equal(getCustomCssValue('--relation-chain-max-height'),
|
||
'96px');
|
||
});
|
||
|
||
|
||
suite('update checks', () => {
|
||
setup(() => {
|
||
sandbox.spy(element, '_startUpdateCheckTimer');
|
||
sandbox.stub(element, 'async', f => {
|
||
// Only fire the async callback one time.
|
||
if (element.async.callCount > 1) { return; }
|
||
f.call(element);
|
||
});
|
||
});
|
||
|
||
test('_startUpdateCheckTimer negative delay', () => {
|
||
sandbox.stub(element, 'fetchChangeUpdates');
|
||
|
||
element._serverConfig = {change: {update_delay: -1}};
|
||
|
||
assert.isTrue(element._startUpdateCheckTimer.called);
|
||
assert.isFalse(element.fetchChangeUpdates.called);
|
||
});
|
||
|
||
test('_startUpdateCheckTimer up-to-date', () => {
|
||
sandbox.stub(element, 'fetchChangeUpdates',
|
||
() => { return Promise.resolve({isLatest: true}); });
|
||
|
||
element._serverConfig = {change: {update_delay: 12345}};
|
||
|
||
assert.isTrue(element._startUpdateCheckTimer.called);
|
||
assert.isTrue(element.fetchChangeUpdates.called);
|
||
assert.equal(element.async.lastCall.args[1], 12345 * 1000);
|
||
});
|
||
|
||
test('_startUpdateCheckTimer out-of-date shows an alert', done => {
|
||
sandbox.stub(element, 'fetchChangeUpdates',
|
||
() => { return Promise.resolve({isLatest: false}); });
|
||
element.addEventListener('show-alert', e => {
|
||
assert.equal(e.detail.message,
|
||
'A newer patch set has been uploaded');
|
||
done();
|
||
});
|
||
element._serverConfig = {change: {update_delay: 12345}};
|
||
});
|
||
|
||
test('_startUpdateCheckTimer new status shows an alert', done => {
|
||
sandbox.stub(element, 'fetchChangeUpdates')
|
||
.returns(Promise.resolve({
|
||
isLatest: true,
|
||
newStatus: element.ChangeStatus.MERGED,
|
||
}));
|
||
element.addEventListener('show-alert', e => {
|
||
assert.equal(e.detail.message, 'This change has been merged');
|
||
done();
|
||
});
|
||
element._serverConfig = {change: {update_delay: 12345}};
|
||
});
|
||
|
||
test('_startUpdateCheckTimer new messages shows an alert', done => {
|
||
sandbox.stub(element, 'fetchChangeUpdates')
|
||
.returns(Promise.resolve({
|
||
isLatest: true,
|
||
newMessages: true,
|
||
}));
|
||
element.addEventListener('show-alert', e => {
|
||
assert.equal(e.detail.message,
|
||
'There are new messages on this change');
|
||
done();
|
||
});
|
||
element._serverConfig = {change: {update_delay: 12345}};
|
||
});
|
||
});
|
||
|
||
test('canStartReview computation', () => {
|
||
const change1 = {};
|
||
const change2 = {
|
||
actions: {
|
||
ready: {
|
||
enabled: true,
|
||
},
|
||
},
|
||
};
|
||
const change3 = {
|
||
actions: {
|
||
ready: {
|
||
label: 'Ready for Review',
|
||
},
|
||
},
|
||
};
|
||
assert.isFalse(element._computeCanStartReview(change1));
|
||
assert.isTrue(element._computeCanStartReview(change2));
|
||
assert.isFalse(element._computeCanStartReview(change3));
|
||
});
|
||
});
|
||
|
||
test('header class computation', () => {
|
||
assert.equal(element._computeHeaderClass(), 'header');
|
||
assert.equal(element._computeHeaderClass(true), 'header editMode');
|
||
});
|
||
|
||
test('_maybeScrollToMessage', done => {
|
||
flush(() => {
|
||
const scrollStub = sandbox.stub(element.messagesList,
|
||
'scrollToMessage');
|
||
|
||
element._maybeScrollToMessage('');
|
||
assert.isFalse(scrollStub.called);
|
||
element._maybeScrollToMessage('message');
|
||
assert.isFalse(scrollStub.called);
|
||
element._maybeScrollToMessage('#message-TEST');
|
||
assert.isTrue(scrollStub.called);
|
||
assert.equal(scrollStub.lastCall.args[0], 'TEST');
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('topic update reloads related changes', () => {
|
||
sandbox.stub(element.$.relatedChanges, 'reload');
|
||
element.dispatchEvent(new CustomEvent('topic-changed'));
|
||
assert.isTrue(element.$.relatedChanges.reload.calledOnce);
|
||
});
|
||
|
||
test('_computeEditMode', () => {
|
||
const callCompute = (range, params) =>
|
||
element._computeEditMode({base: range}, {base: params});
|
||
assert.isFalse(callCompute({}, {}));
|
||
assert.isTrue(callCompute({}, {edit: true}));
|
||
assert.isFalse(callCompute({basePatchNum: 'PARENT', patchNum: 1}, {}));
|
||
assert.isFalse(callCompute({basePatchNum: 'edit', patchNum: 1}, {}));
|
||
assert.isTrue(callCompute({basePatchNum: 1, patchNum: 'edit'}, {}));
|
||
});
|
||
|
||
test('_processEdit', () => {
|
||
element._patchRange = {};
|
||
const change = {
|
||
current_revision: 'foo',
|
||
revisions: {foo: {commit: {}, actions: {cherrypick: {enabled: true}}}},
|
||
};
|
||
let mockChange;
|
||
|
||
// With no edit, mockChange should be unmodified.
|
||
element._processEdit(mockChange = _.cloneDeep(change), null);
|
||
assert.deepEqual(mockChange, change);
|
||
|
||
// When edit is not based on the latest PS, current_revision should be
|
||
// unmodified.
|
||
const edit = {
|
||
base_patch_set_number: 1,
|
||
commit: {commit: 'bar'},
|
||
fetch: true,
|
||
};
|
||
element._processEdit(mockChange = _.cloneDeep(change), edit);
|
||
assert.notDeepEqual(mockChange, change);
|
||
assert.equal(mockChange.revisions.bar._number, element.EDIT_NAME);
|
||
assert.equal(mockChange.current_revision, change.current_revision);
|
||
assert.deepEqual(mockChange.revisions.bar.commit, {commit: 'bar'});
|
||
assert.notOk(mockChange.revisions.bar.actions);
|
||
|
||
edit.base_revision = 'foo';
|
||
element._processEdit(mockChange = _.cloneDeep(change), edit);
|
||
assert.notDeepEqual(mockChange, change);
|
||
assert.equal(mockChange.current_revision, 'bar');
|
||
assert.deepEqual(mockChange.revisions.bar.actions,
|
||
mockChange.revisions.foo.actions);
|
||
|
||
// If _patchRange.patchNum is defined, do not load edit.
|
||
element._patchRange.patchNum = 'baz';
|
||
change.current_revision = 'baz';
|
||
element._processEdit(mockChange = _.cloneDeep(change), edit);
|
||
assert.equal(element._patchRange.patchNum, 'baz');
|
||
assert.notOk(mockChange.revisions.bar.actions);
|
||
});
|
||
|
||
test('file-action-tap handling', () => {
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
const fileList = element.$.fileList;
|
||
const Actions = GrEditConstants.Actions;
|
||
const controls = element.$.fileListHeader.$.editControls;
|
||
sandbox.stub(controls, 'openDeleteDialog');
|
||
sandbox.stub(controls, 'openRenameDialog');
|
||
sandbox.stub(controls, 'openRestoreDialog');
|
||
sandbox.stub(Gerrit.Nav, 'getEditUrlForDiff');
|
||
sandbox.stub(Gerrit.Nav, 'navigateToRelativeUrl');
|
||
|
||
// Delete
|
||
fileList.dispatchEvent(new CustomEvent('file-action-tap', {
|
||
detail: {action: Actions.DELETE.id, path: 'foo'},
|
||
bubbles: true,
|
||
composed: true,
|
||
}));
|
||
flushAsynchronousOperations();
|
||
|
||
assert.isTrue(controls.openDeleteDialog.called);
|
||
assert.equal(controls.openDeleteDialog.lastCall.args[0], 'foo');
|
||
|
||
// Restore
|
||
fileList.dispatchEvent(new CustomEvent('file-action-tap', {
|
||
detail: {action: Actions.RESTORE.id, path: 'foo'},
|
||
bubbles: true,
|
||
composed: true,
|
||
}));
|
||
flushAsynchronousOperations();
|
||
|
||
assert.isTrue(controls.openRestoreDialog.called);
|
||
assert.equal(controls.openRestoreDialog.lastCall.args[0], 'foo');
|
||
|
||
// Rename
|
||
fileList.dispatchEvent(new CustomEvent('file-action-tap', {
|
||
detail: {action: Actions.RENAME.id, path: 'foo'},
|
||
bubbles: true,
|
||
composed: true,
|
||
}));
|
||
flushAsynchronousOperations();
|
||
|
||
assert.isTrue(controls.openRenameDialog.called);
|
||
assert.equal(controls.openRenameDialog.lastCall.args[0], 'foo');
|
||
|
||
// Open
|
||
fileList.dispatchEvent(new CustomEvent('file-action-tap', {
|
||
detail: {action: Actions.OPEN.id, path: 'foo'},
|
||
bubbles: true,
|
||
composed: true,
|
||
}));
|
||
flushAsynchronousOperations();
|
||
|
||
assert.isTrue(Gerrit.Nav.getEditUrlForDiff.called);
|
||
assert.equal(Gerrit.Nav.getEditUrlForDiff.lastCall.args[1], 'foo');
|
||
assert.equal(Gerrit.Nav.getEditUrlForDiff.lastCall.args[2], '1');
|
||
assert.isTrue(Gerrit.Nav.navigateToRelativeUrl.called);
|
||
});
|
||
|
||
test('_selectedRevision updates when patchNum is changed', () => {
|
||
const revision1 = {_number: 1, commit: {parents: []}};
|
||
const revision2 = {_number: 2, commit: {parents: []}};
|
||
sandbox.stub(element.$.restAPI, 'getChangeDetail').returns(
|
||
Promise.resolve({
|
||
revisions: {
|
||
aaa: revision1,
|
||
bbb: revision2,
|
||
},
|
||
labels: {},
|
||
actions: {},
|
||
current_revision: 'bbb',
|
||
change_id: 'loremipsumdolorsitamet',
|
||
}));
|
||
sandbox.stub(element, '_getEdit').returns(Promise.resolve());
|
||
sandbox.stub(element, '_getPreferences').returns(Promise.resolve({}));
|
||
element._patchRange = {patchNum: '2'};
|
||
return element._getChangeDetail().then(() => {
|
||
assert.strictEqual(element._selectedRevision, revision2);
|
||
|
||
element.set('_patchRange.patchNum', '1');
|
||
assert.strictEqual(element._selectedRevision, revision1);
|
||
});
|
||
});
|
||
|
||
test('_sendShowChangeEvent', () => {
|
||
element._change = {labels: {}};
|
||
element._patchRange = {patchNum: 4};
|
||
element._mergeable = true;
|
||
const showStub = sandbox.stub(element.$.jsAPI, 'handleEvent');
|
||
element._sendShowChangeEvent();
|
||
assert.isTrue(showStub.calledOnce);
|
||
assert.equal(
|
||
showStub.lastCall.args[0], element.$.jsAPI.EventType.SHOW_CHANGE);
|
||
assert.deepEqual(showStub.lastCall.args[1], {
|
||
change: {labels: {}},
|
||
patchNum: 4,
|
||
info: {mergeable: true},
|
||
});
|
||
});
|
||
|
||
suite('_handleEditTap', () => {
|
||
let fireEdit;
|
||
|
||
setup(() => {
|
||
fireEdit = () => {
|
||
element.$.actions.dispatchEvent(new CustomEvent('edit-tap'));
|
||
};
|
||
navigateToChangeStub.restore();
|
||
|
||
element._change = {revisions: {rev1: {_number: 1}}};
|
||
});
|
||
|
||
test('edit exists in revisions', done => {
|
||
sandbox.stub(Gerrit.Nav, 'navigateToChange', (...args) => {
|
||
assert.equal(args.length, 2);
|
||
assert.equal(args[1], element.EDIT_NAME); // patchNum
|
||
done();
|
||
});
|
||
|
||
element.set('_change.revisions.rev2', {_number: element.EDIT_NAME});
|
||
flushAsynchronousOperations();
|
||
|
||
fireEdit();
|
||
});
|
||
|
||
test('no edit exists in revisions, non-latest patchset', done => {
|
||
sandbox.stub(Gerrit.Nav, 'navigateToChange', (...args) => {
|
||
assert.equal(args.length, 4);
|
||
assert.equal(args[1], 1); // patchNum
|
||
assert.equal(args[3], true); // opt_isEdit
|
||
done();
|
||
});
|
||
|
||
element.set('_change.revisions.rev2', {_number: 2});
|
||
element._patchRange = {patchNum: 1};
|
||
flushAsynchronousOperations();
|
||
|
||
fireEdit();
|
||
});
|
||
|
||
test('no edit exists in revisions, latest patchset', done => {
|
||
sandbox.stub(Gerrit.Nav, 'navigateToChange', (...args) => {
|
||
assert.equal(args.length, 4);
|
||
// No patch should be specified when patchNum == latest.
|
||
assert.isNotOk(args[1]); // patchNum
|
||
assert.equal(args[3], true); // opt_isEdit
|
||
done();
|
||
});
|
||
|
||
element.set('_change.revisions.rev2', {_number: 2});
|
||
element._patchRange = {patchNum: 2};
|
||
flushAsynchronousOperations();
|
||
|
||
fireEdit();
|
||
});
|
||
});
|
||
|
||
test('_handleStopEditTap', done => {
|
||
sandbox.stub(element.$.metadata, '_computeLabelNames');
|
||
navigateToChangeStub.restore();
|
||
sandbox.stub(element, 'computeLatestPatchNum').returns(1);
|
||
sandbox.stub(Gerrit.Nav, 'navigateToChange', (...args) => {
|
||
assert.equal(args.length, 2);
|
||
assert.equal(args[1], 1); // patchNum
|
||
done();
|
||
});
|
||
|
||
element._patchRange = {patchNum: 1};
|
||
element.$.actions.dispatchEvent(new CustomEvent('stop-edit-tap',
|
||
{bubbles: false}));
|
||
});
|
||
|
||
suite('plugin endpoints', () => {
|
||
test('endpoint params', done => {
|
||
element._change = {labels: {}};
|
||
element._selectedRevision = {};
|
||
let hookEl;
|
||
let plugin;
|
||
Gerrit.install(
|
||
p => {
|
||
plugin = p;
|
||
plugin.hook('change-view-integration').getLastAttached().then(
|
||
el => hookEl = el);
|
||
},
|
||
'0.1',
|
||
'http://some/plugins/url.html');
|
||
flush(() => {
|
||
assert.strictEqual(hookEl.plugin, plugin);
|
||
assert.strictEqual(hookEl.change, element._change);
|
||
assert.strictEqual(hookEl.revision, element._selectedRevision);
|
||
done();
|
||
});
|
||
});
|
||
});
|
||
|
||
suite('_getMergeability', () => {
|
||
let getMergeableStub;
|
||
|
||
setup(() => {
|
||
element._change = {labels: {}};
|
||
getMergeableStub = sandbox.stub(element.$.restAPI, 'getMergeable')
|
||
.returns(Promise.resolve({mergeable: true}));
|
||
});
|
||
|
||
test('merged change', () => {
|
||
element._mergeable = null;
|
||
element._change.status = element.ChangeStatus.MERGED;
|
||
return element._getMergeability().then(() => {
|
||
assert.isFalse(element._mergeable);
|
||
assert.isFalse(getMergeableStub.called);
|
||
});
|
||
});
|
||
|
||
test('abandoned change', () => {
|
||
element._mergeable = null;
|
||
element._change.status = element.ChangeStatus.ABANDONED;
|
||
return element._getMergeability().then(() => {
|
||
assert.isFalse(element._mergeable);
|
||
assert.isFalse(getMergeableStub.called);
|
||
});
|
||
});
|
||
|
||
test('open change', () => {
|
||
element._mergeable = null;
|
||
return element._getMergeability().then(() => {
|
||
assert.isTrue(element._mergeable);
|
||
assert.isTrue(getMergeableStub.called);
|
||
});
|
||
});
|
||
});
|
||
|
||
test('_paramsChanged sets in projectLookup', () => {
|
||
sandbox.stub(element.$.relatedChanges, 'reload');
|
||
sandbox.stub(element, '_reload').returns(Promise.resolve());
|
||
const setStub = sandbox.stub(element.$.restAPI, 'setInProjectLookup');
|
||
element._paramsChanged({
|
||
view: Gerrit.Nav.View.CHANGE,
|
||
changeNum: 101,
|
||
project: 'test-project',
|
||
});
|
||
assert.isTrue(setStub.calledOnce);
|
||
assert.isTrue(setStub.calledWith(101, 'test-project'));
|
||
});
|
||
|
||
test('_handleToggleStar called when star is tapped', () => {
|
||
element._change = {
|
||
owner: {_account_id: 1},
|
||
starred: false,
|
||
};
|
||
element._loggedIn = true;
|
||
const stub = sandbox.stub(element, '_handleToggleStar');
|
||
flushAsynchronousOperations();
|
||
|
||
MockInteractions.tap(element.$.changeStar.$$('button'));
|
||
assert.isTrue(stub.called);
|
||
});
|
||
|
||
suite('gr-reporting tests', () => {
|
||
setup(() => {
|
||
element._patchRange = {
|
||
basePatchNum: 'PARENT',
|
||
patchNum: 1,
|
||
};
|
||
sandbox.stub(element, '_getChangeDetail').returns(Promise.resolve());
|
||
sandbox.stub(element, '_getProjectConfig').returns(Promise.resolve());
|
||
sandbox.stub(element, '_reloadComments').returns(Promise.resolve());
|
||
sandbox.stub(element, '_getMergeability').returns(Promise.resolve());
|
||
sandbox.stub(element, '_getLatestCommitMessage')
|
||
.returns(Promise.resolve());
|
||
});
|
||
|
||
test('don\'t report changedDisplayed on reply', done => {
|
||
const changeDisplayStub =
|
||
sandbox.stub(element.$.reporting, 'changeDisplayed');
|
||
const changeFullyLoadedStub =
|
||
sandbox.stub(element.$.reporting, 'changeFullyLoaded');
|
||
element._handleReplySent();
|
||
flush(() => {
|
||
assert.isFalse(changeDisplayStub.called);
|
||
assert.isFalse(changeFullyLoadedStub.called);
|
||
done();
|
||
});
|
||
});
|
||
|
||
test('report changedDisplayed on _paramsChanged', done => {
|
||
const changeDisplayStub =
|
||
sandbox.stub(element.$.reporting, 'changeDisplayed');
|
||
const changeFullyLoadedStub =
|
||
sandbox.stub(element.$.reporting, 'changeFullyLoaded');
|
||
element._paramsChanged({
|
||
view: Gerrit.Nav.View.CHANGE,
|
||
changeNum: 101,
|
||
project: 'test-project',
|
||
});
|
||
flush(() => {
|
||
assert.isTrue(changeDisplayStub.called);
|
||
assert.isTrue(changeFullyLoadedStub.called);
|
||
done();
|
||
});
|
||
});
|
||
});
|
||
});
|
||
</script>
|