Separate file list header into new component
Change-Id: I45619dfaaf005a89f8de6d3e9dc39a2bcbca1893
This commit is contained in:
@@ -21,12 +21,10 @@ limitations under the License.
|
|||||||
<link rel="import" href="../../core/gr-navigation/gr-navigation.html">
|
<link rel="import" href="../../core/gr-navigation/gr-navigation.html">
|
||||||
<link rel="import" href="../../diff/gr-diff-preferences/gr-diff-preferences.html">
|
<link rel="import" href="../../diff/gr-diff-preferences/gr-diff-preferences.html">
|
||||||
<link rel="import" href="../../shared/gr-account-link/gr-account-link.html">
|
<link rel="import" href="../../shared/gr-account-link/gr-account-link.html">
|
||||||
<link rel="import" href="../../shared/gr-select/gr-select.html">
|
|
||||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||||
<link rel="import" href="../../shared/gr-change-star/gr-change-star.html">
|
<link rel="import" href="../../shared/gr-change-star/gr-change-star.html">
|
||||||
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
|
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
|
||||||
<link rel="import" href="../../shared/gr-editable-content/gr-editable-content.html">
|
<link rel="import" href="../../shared/gr-editable-content/gr-editable-content.html">
|
||||||
<link rel="import" href="../../shared/gr-editable-label/gr-editable-label.html">
|
|
||||||
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
|
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
|
||||||
<link rel="import" href="../../shared/gr-linked-text/gr-linked-text.html">
|
<link rel="import" href="../../shared/gr-linked-text/gr-linked-text.html">
|
||||||
<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
|
<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
|
||||||
@@ -37,6 +35,7 @@ limitations under the License.
|
|||||||
<link rel="import" href="../gr-commit-info/gr-commit-info.html">
|
<link rel="import" href="../gr-commit-info/gr-commit-info.html">
|
||||||
<link rel="import" href="../gr-download-dialog/gr-download-dialog.html">
|
<link rel="import" href="../gr-download-dialog/gr-download-dialog.html">
|
||||||
<link rel="import" href="../gr-file-list/gr-file-list.html">
|
<link rel="import" href="../gr-file-list/gr-file-list.html">
|
||||||
|
<link rel="import" href="../gr-file-list-header/gr-file-list-header.html">
|
||||||
<link rel="import" href="../gr-messages-list/gr-messages-list.html">
|
<link rel="import" href="../gr-messages-list/gr-messages-list.html">
|
||||||
<link rel="import" href="../gr-related-changes-list/gr-related-changes-list.html">
|
<link rel="import" href="../gr-related-changes-list/gr-related-changes-list.html">
|
||||||
<link rel="import" href="../gr-reply-dialog/gr-reply-dialog.html">
|
<link rel="import" href="../gr-reply-dialog/gr-reply-dialog.html">
|
||||||
@@ -80,9 +79,6 @@ limitations under the License.
|
|||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.prefsButton {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
gr-change-star {
|
gr-change-star {
|
||||||
margin-right: .25em;
|
margin-right: .25em;
|
||||||
vertical-align: -.425em;
|
vertical-align: -.425em;
|
||||||
@@ -152,45 +148,10 @@ limitations under the License.
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
.collapseToggleButton {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.relatedChanges {
|
.relatedChanges {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.patchInfo {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
margin: 1em var(--default-horizontal-margin);
|
|
||||||
}
|
|
||||||
.patchInfoEdit .patchInfo-header {
|
|
||||||
background-color: #fcfad6;
|
|
||||||
}
|
|
||||||
.patchInfoOldPatchSet .patchInfo-header {
|
|
||||||
background-color: #fff9c4;
|
|
||||||
}
|
|
||||||
.patchInfoOldPatchSet .latestPatchContainer {
|
|
||||||
display: initial;
|
|
||||||
}
|
|
||||||
.patchInfo-header,
|
|
||||||
.fileList {
|
|
||||||
padding: .5em calc(var(--default-horizontal-margin) / 2);
|
|
||||||
}
|
|
||||||
.patchInfo-header {
|
|
||||||
background-color: #f6f6f6;
|
|
||||||
border-bottom: 1px solid #ebebeb;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.latestPatchContainer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.patchSetSelect {
|
|
||||||
max-width: 8em;
|
|
||||||
}
|
|
||||||
gr-editable-label.descriptionLabel {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
.mobile {
|
.mobile {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -203,13 +164,6 @@ limitations under the License.
|
|||||||
height: 0;
|
height: 0;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
#diffPrefsContainer,
|
|
||||||
.rightControls {
|
|
||||||
margin: auto 0 auto auto;
|
|
||||||
}
|
|
||||||
.patchInfo-header-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
#commitMessage.collapsed {
|
#commitMessage.collapsed {
|
||||||
max-height: 36em;
|
max-height: 36em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -246,32 +200,12 @@ limitations under the License.
|
|||||||
.showOnEdit {
|
.showOnEdit {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.editLoaded .hideOnEdit {
|
.patchInfo {
|
||||||
display: none;
|
border: 1px solid #ddd;
|
||||||
|
margin: 1em var(--default-horizontal-margin);
|
||||||
}
|
}
|
||||||
.editLoaded .showOnEdit {
|
#fileList {
|
||||||
display: initial;
|
padding: .5em calc(var(--default-horizontal-margin) / 2);
|
||||||
}
|
|
||||||
.fileList-header {
|
|
||||||
display: flex;
|
|
||||||
font-weight: bold;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: .5em;
|
|
||||||
}
|
|
||||||
.rightControls {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
font-weight: normal;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
.separator {
|
|
||||||
margin: 0 .25em;
|
|
||||||
}
|
|
||||||
.expandInline {
|
|
||||||
padding-right: .25em;
|
|
||||||
}
|
|
||||||
.patchSetSelect {
|
|
||||||
max-width: 8em;
|
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 80em) {
|
@media screen and (min-width: 80em) {
|
||||||
.commitMessage {
|
.commitMessage {
|
||||||
@@ -357,7 +291,7 @@ limitations under the License.
|
|||||||
<div class="container loading" hidden$="[[!_loading]]">Loading...</div>
|
<div class="container loading" hidden$="[[!_loading]]">Loading...</div>
|
||||||
<div
|
<div
|
||||||
id="mainContent"
|
id="mainContent"
|
||||||
class$="container [[_computeEditLoadedClass(_editLoaded)]]"
|
class="container"
|
||||||
hidden$="{{_loading}}">
|
hidden$="{{_loading}}">
|
||||||
<div class$="hideOnMobileOverlay [[_computeHeaderClass(_change)]]">
|
<div class$="hideOnMobileOverlay [[_computeHeaderClass(_change)]]">
|
||||||
<span class="header-title">
|
<span class="header-title">
|
||||||
@@ -486,138 +420,44 @@ limitations under the License.
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class$="patchInfo hideOnMobileOverlay [[_computePatchInfoClass(_patchRange.patchNum,
|
<section class="patchInfo hideOnMobileOverlay">
|
||||||
_allPatchSets)]]">
|
<gr-file-list-header
|
||||||
<div class="patchInfo-header">
|
id="fileListHeader"
|
||||||
<div class="patchInfo-header-wrapper">
|
account="[[_account]]"
|
||||||
<label class="patchSelectLabel" for="patchSetSelect">
|
all-patch-sets="[[_allPatchSets]]"
|
||||||
Patch set
|
change="[[_change]]"
|
||||||
</label>
|
change-num="[[_changeNum]]"
|
||||||
<gr-select
|
comments="[[_comments]]"
|
||||||
id="patchSetSelect"
|
commit-info="[[_commitInfo]]"
|
||||||
bind-value="{{_selectedPatchSet}}"
|
change-url="[[_computeChangeUrl(_change)]]"
|
||||||
class="patchSetSelect"
|
edit-loaded="[[_editLoaded]]"
|
||||||
on-change="_handlePatchChange">
|
logged-in="[[_loggedIn]]"
|
||||||
<select>
|
server-config="[[_serverConfig]]"
|
||||||
<template is="dom-repeat" items="[[_allPatchSets]]"
|
shown-file-count="[[_shownFileCount]]"
|
||||||
as="patchNum">
|
diff-prefs="[[_diffPrefs]]"
|
||||||
<option
|
diff-view-mode="{{viewState.diffMode}}"
|
||||||
value$="[[patchNum.num]]"
|
patch-range="{{_patchRange}}"
|
||||||
disabled$="[[_computePatchSetDisabled(patchNum.num, _patchRange.basePatchNum, _sortedRevisions)]]">
|
revisions="[[_sortedRevisions]]"
|
||||||
[[patchNum.num]]
|
on-open-diff-prefs="_handleOpenDiffPrefs"
|
||||||
/
|
on-open-download-dialog="_handleOpenDownloadDialog"
|
||||||
[[computeLatestPatchNum(_allPatchSets)]]
|
on-expand-diffs="_expandAllDiffs"
|
||||||
[[_computePatchSetCommentsString(_comments, patchNum.num)]]
|
on-collapse-diffs="_collapseAllDiffs">
|
||||||
[[_computePatchSetDescription(_change, patchNum.num)]]
|
</gr-file-list-header>
|
||||||
</option>
|
<gr-file-list id="fileList"
|
||||||
</template>
|
diff-prefs="{{_diffPrefs}}"
|
||||||
</select>
|
change="[[_change]]"
|
||||||
</gr-select>
|
change-num="[[_changeNum]]"
|
||||||
/
|
patch-range="{{_patchRange}}"
|
||||||
<gr-commit-info
|
comments="[[_comments]]"
|
||||||
change="[[_change]]"
|
drafts="[[_diffDrafts]]"
|
||||||
server-config="[[_serverConfig]]"
|
revisions="[[_sortedRevisions]]"
|
||||||
commit-info="[[_commitInfo]]"></gr-commit-info>
|
project-config="[[_projectConfig]]"
|
||||||
<span class="latestPatchContainer">
|
selected-index="{{viewState.selectedFileIndex}}"
|
||||||
/
|
diff-view-mode="[[viewState.diffMode]]"
|
||||||
<a href$="[[_computeChangeUrl(_change)]]">Go to latest patch set</a>
|
edit-loaded="[[_editLoaded]]"
|
||||||
</span>
|
num-files-shown="{{_numFilesShown}}"
|
||||||
<span class="downloadContainer desktop">
|
file-list-increment="{{_numFilesShown}}"
|
||||||
/
|
on-files-shown-changed="_setShownFiles"></gr-file-list>
|
||||||
<gr-button link
|
|
||||||
class="download"
|
|
||||||
on-tap="_handleDownloadTap">Download</gr-button>
|
|
||||||
</span>
|
|
||||||
<span class="descriptionContainer hideOnEdit">
|
|
||||||
/
|
|
||||||
<gr-editable-label
|
|
||||||
id="descriptionLabel"
|
|
||||||
class="descriptionLabel"
|
|
||||||
value="[[_computePatchSetDescription(_change, _selectedPatchSet)]]"
|
|
||||||
placeholder="[[_computeDescriptionPlaceholder(_descriptionReadOnly)]]"
|
|
||||||
read-only="[[_descriptionReadOnly]]"
|
|
||||||
on-changed="_handleDescriptionChanged"></gr-editable-label>
|
|
||||||
</span>
|
|
||||||
<span id="diffPrefsContainer"
|
|
||||||
class="hideOnEdit"
|
|
||||||
hidden$="[[_computePrefsButtonHidden(_diffPrefs, _loggedIn)]]"
|
|
||||||
hidden>
|
|
||||||
<gr-button link
|
|
||||||
class="prefsButton desktop"
|
|
||||||
on-tap="_handlePrefsTap">Diff Preferences</gr-button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="fileList">
|
|
||||||
<div class="fileList-header">
|
|
||||||
<div>Files</div>
|
|
||||||
<div class="rightControls">
|
|
||||||
<template is="dom-if"
|
|
||||||
if="[[_fileListActionsVisible(_shownFileCount, _maxFilesForBulkActions)]]">
|
|
||||||
<gr-button
|
|
||||||
id="expandBtn"
|
|
||||||
link
|
|
||||||
on-tap="_expandAllDiffs">Show diffs</gr-button>
|
|
||||||
<span class="separator">/</span>
|
|
||||||
<gr-button
|
|
||||||
id="collapseBtn"
|
|
||||||
link
|
|
||||||
on-tap="_collapseAllDiffs">Hide diffs</gr-button>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if"
|
|
||||||
if="[[!_fileListActionsVisible(_shownFileCount, _maxFilesForBulkActions)]]">
|
|
||||||
<div class="warning">
|
|
||||||
Bulk actions disabled because there are too many files.
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<span class="separator">/</span>
|
|
||||||
<gr-select
|
|
||||||
id="modeSelect"
|
|
||||||
bind-value="{{viewState.diffMode}}">
|
|
||||||
<select>
|
|
||||||
<option value="SIDE_BY_SIDE">Side By Side</option>
|
|
||||||
<option value="UNIFIED_DIFF">Unified</option>
|
|
||||||
</select>
|
|
||||||
</gr-select>
|
|
||||||
<span class="separator">/</span>
|
|
||||||
<label>
|
|
||||||
Diff against
|
|
||||||
<gr-select id="patchChange" bind-value="{{_diffAgainst}}"
|
|
||||||
class="patchSetSelect" on-change="_handleBasePatchChange">
|
|
||||||
<select>
|
|
||||||
<option value="PARENT">Base</option>
|
|
||||||
<template
|
|
||||||
is="dom-repeat"
|
|
||||||
items="[[_allPatchSets]]"
|
|
||||||
as="patchNum">
|
|
||||||
<option
|
|
||||||
disabled$="[[_computeBasePatchDisabled(patchNum.num, _patchRange.patchNum, _sortedRevisions)]]"
|
|
||||||
value$="[[patchNum.num]]">
|
|
||||||
[[patchNum.num]]
|
|
||||||
[[patchNum.desc]]
|
|
||||||
</option>
|
|
||||||
</template>
|
|
||||||
</select>
|
|
||||||
</gr-select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<gr-file-list id="fileList"
|
|
||||||
diff-prefs="{{_diffPrefs}}"
|
|
||||||
change="[[_change]]"
|
|
||||||
change-num="[[_changeNum]]"
|
|
||||||
patch-range="{{_patchRange}}"
|
|
||||||
comments="[[_comments]]"
|
|
||||||
drafts="[[_diffDrafts]]"
|
|
||||||
revisions="[[_sortedRevisions]]"
|
|
||||||
project-config="[[_projectConfig]]"
|
|
||||||
selected-index="{{viewState.selectedFileIndex}}"
|
|
||||||
diff-view-mode="[[viewState.diffMode]]"
|
|
||||||
edit-loaded="[[_editLoaded]]"
|
|
||||||
num-files-shown="{{_numFilesShown}}"
|
|
||||||
file-list-increment="{{_numFilesShown}}"
|
|
||||||
on-files-shown-changed="_setShownFiles"></gr-file-list>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
<gr-messages-list id="messageList"
|
<gr-messages-list id="messageList"
|
||||||
class="hideOnMobileOverlay"
|
class="hideOnMobileOverlay"
|
||||||
|
@@ -23,8 +23,6 @@
|
|||||||
const MIN_LINES_FOR_COMMIT_COLLAPSE = 30;
|
const MIN_LINES_FOR_COMMIT_COLLAPSE = 30;
|
||||||
const DEFAULT_NUM_FILES_SHOWN = 200;
|
const DEFAULT_NUM_FILES_SHOWN = 200;
|
||||||
|
|
||||||
// Maximum length for patch set descriptions.
|
|
||||||
const PATCH_DESC_MAX_LENGTH = 500;
|
|
||||||
const REVIEWERS_REGEX = /^(R|CC)=/gm;
|
const REVIEWERS_REGEX = /^(R|CC)=/gm;
|
||||||
const MIN_CHECK_INTERVAL_SECS = 0;
|
const MIN_CHECK_INTERVAL_SECS = 0;
|
||||||
|
|
||||||
@@ -134,18 +132,10 @@
|
|||||||
type: String,
|
type: String,
|
||||||
computed:
|
computed:
|
||||||
'_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
|
'_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
|
||||||
},
|
|
||||||
// Caps the number of files that can be shown and have the 'show diffs' /
|
|
||||||
// 'hide diffs' buttons still be functional.
|
|
||||||
_maxFilesForBulkActions: {
|
|
||||||
type: Number,
|
|
||||||
readOnly: true,
|
|
||||||
value: 225,
|
|
||||||
},
|
},
|
||||||
/** @type {?} */
|
/** @type {?} */
|
||||||
_patchRange: {
|
_patchRange: {
|
||||||
type: Object,
|
type: Object,
|
||||||
observer: '_updateSelected',
|
|
||||||
},
|
},
|
||||||
_relatedChangesLoading: {
|
_relatedChangesLoading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -175,10 +165,6 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
_descriptionReadOnly: {
|
|
||||||
type: Boolean,
|
|
||||||
computed: '_computeDescriptionReadOnly(_loggedIn, _change, _account)',
|
|
||||||
},
|
|
||||||
_replyDisabled: {
|
_replyDisabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: true,
|
value: true,
|
||||||
@@ -293,10 +279,6 @@
|
|||||||
this._sortedRevisions = this.sortRevisions(Object.values(revisions));
|
this._sortedRevisions = this.sortRevisions(Object.values(revisions));
|
||||||
},
|
},
|
||||||
|
|
||||||
_computePrefsButtonHidden(prefs, loggedIn) {
|
|
||||||
return !loggedIn || !prefs;
|
|
||||||
},
|
|
||||||
|
|
||||||
_handleEditCommitMessage(e) {
|
_handleEditCommitMessage(e) {
|
||||||
this._editingCommitMessage = true;
|
this._editingCommitMessage = true;
|
||||||
this.$.commitMessageEditor.focusTextarea();
|
this.$.commitMessageEditor.focusTextarea();
|
||||||
@@ -338,11 +320,6 @@
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_handlePrefsTap(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.$.fileList.openDiffPrefs();
|
|
||||||
},
|
|
||||||
|
|
||||||
_handleCommentSave(e) {
|
_handleCommentSave(e) {
|
||||||
if (!e.target.comment.__draft) { return; }
|
if (!e.target.comment.__draft) { return; }
|
||||||
|
|
||||||
@@ -409,21 +386,16 @@
|
|||||||
this._diffDrafts = diffDrafts;
|
this._diffDrafts = diffDrafts;
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleBasePatchChange(e) {
|
|
||||||
this._changePatchNum(this._selectedPatchSet, e.target.value, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_handlePatchChange(e) {
|
|
||||||
this._changePatchNum(e.target.value, this._diffAgainst, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
_handleReplyTap(e) {
|
_handleReplyTap(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._openReplyDialog();
|
this._openReplyDialog();
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleDownloadTap(e) {
|
_handleOpenDiffPrefs() {
|
||||||
e.preventDefault();
|
this.$.fileList.openDiffPrefs();
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleOpenDownloadDialog() {
|
||||||
this.$.downloadOverlay.open().then(() => {
|
this.$.downloadOverlay.open().then(() => {
|
||||||
this.$.downloadOverlay
|
this.$.downloadOverlay
|
||||||
.setFocusStops(this.$.downloadDialog.getFocusStops());
|
.setFocusStops(this.$.downloadDialog.getFocusStops());
|
||||||
@@ -494,10 +466,6 @@
|
|||||||
this._shownFileCount = e.detail.length;
|
this._shownFileCount = e.detail.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
_fileListActionsVisible(shownFileCount, maxFilesForBulkActions) {
|
|
||||||
return shownFileCount <= maxFilesForBulkActions;
|
|
||||||
},
|
|
||||||
|
|
||||||
_expandAllDiffs() {
|
_expandAllDiffs() {
|
||||||
this.$.fileList.expandAllDiffs();
|
this.$.fileList.expandAllDiffs();
|
||||||
},
|
},
|
||||||
@@ -666,39 +634,12 @@
|
|||||||
this._patchRange.patchNum ||
|
this._patchRange.patchNum ||
|
||||||
this.computeLatestPatchNum(this._allPatchSets));
|
this.computeLatestPatchNum(this._allPatchSets));
|
||||||
|
|
||||||
this._updateSelected();
|
this.$.fileListHeader.updateSelected();
|
||||||
|
|
||||||
const title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
|
const title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
|
||||||
this.fire('title-change', {title});
|
this.fire('title-change', {title});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Change active patch to the provided patch num.
|
|
||||||
* @param {number|string} basePatchNum the base patch to be viewed.
|
|
||||||
* @param {number|string} patchNum the patch number to be viewed.
|
|
||||||
* @param {boolean} opt_forceParams When set to true, the resulting URL will
|
|
||||||
* always include the patch range, even if the requested patchNum is
|
|
||||||
* known to be the latest.
|
|
||||||
*/
|
|
||||||
_changePatchNum(patchNum, basePatchNum, opt_forceParams) {
|
|
||||||
if (!opt_forceParams) {
|
|
||||||
let currentPatchNum;
|
|
||||||
if (this._change.current_revision) {
|
|
||||||
currentPatchNum =
|
|
||||||
this._change.revisions[this._change.current_revision]._number;
|
|
||||||
} else {
|
|
||||||
currentPatchNum = this.computeLatestPatchNum(this._allPatchSets);
|
|
||||||
}
|
|
||||||
if (this.patchNumEquals(patchNum, currentPatchNum) &&
|
|
||||||
basePatchNum === 'PARENT') {
|
|
||||||
Gerrit.Nav.navigateToChange(this._change);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Gerrit.Nav.navigateToChange(this._change, patchNum,
|
|
||||||
basePatchNum);
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeChangeUrl(change) {
|
_computeChangeUrl(change) {
|
||||||
return Gerrit.Nav.getUrlForChange(change);
|
return Gerrit.Nav.getUrlForChange(change);
|
||||||
},
|
},
|
||||||
@@ -753,37 +694,6 @@
|
|||||||
return CHANGE_ID_ERROR.MISSING;
|
return CHANGE_ID_ERROR.MISSING;
|
||||||
},
|
},
|
||||||
|
|
||||||
_computePatchInfoClass(patchNum, allPatchSets) {
|
|
||||||
if (this.patchNumEquals(patchNum, this.EDIT_NAME)) {
|
|
||||||
return 'patchInfoEdit';
|
|
||||||
}
|
|
||||||
|
|
||||||
const latestNum = this.computeLatestPatchNum(allPatchSets);
|
|
||||||
if (this.patchNumEquals(patchNum, latestNum)) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return 'patchInfoOldPatchSet';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a patch number should be disabled based on value of the
|
|
||||||
* basePatchNum from gr-file-list.
|
|
||||||
* @param {number} patchNum Patch number available in dropdown
|
|
||||||
* @param {number|string} basePatchNum Base patch number from file list
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
_computePatchSetDisabled(patchNum, basePatchNum) {
|
|
||||||
if (basePatchNum === 'PARENT') { return false; }
|
|
||||||
|
|
||||||
return this.findSortedIndex(patchNum, this._sortedRevisions) <=
|
|
||||||
this.findSortedIndex(basePatchNum, this._sortedRevisions);
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeBasePatchDisabled(patchNum, currentPatchNum) {
|
|
||||||
return this.findSortedIndex(patchNum, this._sortedRevisions) >=
|
|
||||||
this.findSortedIndex(currentPatchNum, this._sortedRevisions);
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeLabelNames(labels) {
|
_computeLabelNames(labels) {
|
||||||
return Object.keys(labels).sort();
|
return Object.keys(labels).sort();
|
||||||
},
|
},
|
||||||
@@ -1163,81 +1073,11 @@
|
|||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateSelected() {
|
|
||||||
this._selectedPatchSet = this._patchRange.patchNum;
|
|
||||||
this._diffAgainst = this._patchRange.basePatchNum;
|
|
||||||
},
|
|
||||||
|
|
||||||
_computePatchSetDescription(change, patchNum) {
|
|
||||||
const rev = this.getRevisionByPatchNum(change.revisions, patchNum);
|
|
||||||
return (rev && rev.description) ?
|
|
||||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
|
||||||
},
|
|
||||||
|
|
||||||
_computePatchSetCommentsString(allComments, patchNum) {
|
|
||||||
let numComments = 0;
|
|
||||||
let numUnresolved = 0;
|
|
||||||
for (const file in allComments) {
|
|
||||||
if (allComments.hasOwnProperty(file)) {
|
|
||||||
numComments += this.$.fileList.getCommentsForPath(
|
|
||||||
allComments, patchNum, file).length;
|
|
||||||
numUnresolved += this.$.fileList.computeUnresolvedNum(
|
|
||||||
allComments, {}, patchNum, file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let commentsStr = '';
|
|
||||||
if (numComments > 0) {
|
|
||||||
commentsStr = '(' + numComments + ' comments';
|
|
||||||
if (numUnresolved > 0) {
|
|
||||||
commentsStr += ', ' + numUnresolved + ' unresolved';
|
|
||||||
}
|
|
||||||
commentsStr += ')';
|
|
||||||
}
|
|
||||||
return commentsStr;
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeDescriptionPlaceholder(readOnly) {
|
|
||||||
return (readOnly ? 'No' : 'Add a') + ' patch set description';
|
|
||||||
},
|
|
||||||
|
|
||||||
_handleDescriptionChanged(e) {
|
|
||||||
const desc = e.detail.trim();
|
|
||||||
const rev = this.getRevisionByPatchNum(this._change.revisions,
|
|
||||||
this._selectedPatchSet);
|
|
||||||
const sha = this._getPatchsetHash(this._change.revisions, rev);
|
|
||||||
this.$.restAPI.setDescription(this._changeNum,
|
|
||||||
this._selectedPatchSet, desc)
|
|
||||||
.then(res => {
|
|
||||||
if (res.ok) {
|
|
||||||
this.set(['_change', 'revisions', sha, 'description'], desc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {!Object} revisions The revisions object keyed by revision hashes
|
|
||||||
* @param {?Object} patchSet A revision already fetched from {revisions}
|
|
||||||
* @return {string|undefined} the SHA hash corresponding to the revision.
|
|
||||||
*/
|
|
||||||
_getPatchsetHash(revisions, patchSet) {
|
|
||||||
for (const rev in revisions) {
|
|
||||||
if (revisions.hasOwnProperty(rev) &&
|
|
||||||
revisions[rev] === patchSet) {
|
|
||||||
return rev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeCanStartReview(loggedIn, change, account) {
|
_computeCanStartReview(loggedIn, change, account) {
|
||||||
return !!(loggedIn && change.work_in_progress &&
|
return !!(loggedIn && change.work_in_progress &&
|
||||||
change.owner._account_id === account._account_id);
|
change.owner._account_id === account._account_id);
|
||||||
},
|
},
|
||||||
|
|
||||||
_computeDescriptionReadOnly(loggedIn, change, account) {
|
|
||||||
return !(loggedIn && (account._account_id === change.owner._account_id));
|
|
||||||
},
|
|
||||||
|
|
||||||
_computeReplyDisabled() { return false; },
|
_computeReplyDisabled() { return false; },
|
||||||
|
|
||||||
_computeChangePermalinkAriaLabel(changeNum) {
|
_computeChangePermalinkAriaLabel(changeNum) {
|
||||||
@@ -1424,9 +1264,5 @@
|
|||||||
const patchRange = patchRangeRecord.base || {};
|
const patchRange = patchRangeRecord.base || {};
|
||||||
return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
|
return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
|
||||||
},
|
},
|
||||||
|
|
||||||
_computeEditLoadedClass(editLoaded) {
|
|
||||||
return editLoaded ? 'editLoaded' : '';
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@@ -171,6 +171,20 @@ limitations under the License.
|
|||||||
assert.isFalse(element.$.mainContent.classList.contains('overlayOpen'));
|
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', () => {
|
test('X should expand all messages', () => {
|
||||||
const handleExpand =
|
const handleExpand =
|
||||||
sandbox.stub(element.$.messageList, 'handleExpandCollapse');
|
sandbox.stub(element.$.messageList, 'handleExpandCollapse');
|
||||||
@@ -238,79 +252,13 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Diff preferences hidden when no prefs or logged out', () => {
|
test('diff preferences open when open-diff-prefs is fired', () => {
|
||||||
element._loggedIn = false;
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
||||||
|
|
||||||
element._loggedIn = true;
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
||||||
|
|
||||||
element._loggedIn = false;
|
|
||||||
element._diffPrefs = {font_size: '12'};
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
|
||||||
|
|
||||||
element._loggedIn = true;
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.isFalse(element.$.diffPrefsContainer.hidden);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('prefsButton opens gr-diff-preferences', () => {
|
|
||||||
const handlePrefsTapSpy = sandbox.spy(element, '_handlePrefsTap');
|
|
||||||
const overlayOpenStub = sandbox.stub(element.$.fileList,
|
const overlayOpenStub = sandbox.stub(element.$.fileList,
|
||||||
'openDiffPrefs');
|
'openDiffPrefs');
|
||||||
const prefsButton = Polymer.dom(element.root).querySelectorAll(
|
element.$.fileListHeader.fire('open-diff-prefs');
|
||||||
'.prefsButton')[0];
|
|
||||||
|
|
||||||
MockInteractions.tap(prefsButton);
|
|
||||||
|
|
||||||
assert.isTrue(handlePrefsTapSpy.called);
|
|
||||||
assert.isTrue(overlayOpenStub.called);
|
assert.isTrue(overlayOpenStub.called);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_computeDescriptionReadOnly', () => {
|
|
||||||
assert.equal(element._computeDescriptionReadOnly(false,
|
|
||||||
{owner: {_account_id: 1}}, {_account_id: 1}), true);
|
|
||||||
assert.equal(element._computeDescriptionReadOnly(true,
|
|
||||||
{owner: {_account_id: 0}}, {_account_id: 1}), true);
|
|
||||||
assert.equal(element._computeDescriptionReadOnly(true,
|
|
||||||
{owner: {_account_id: 1}}, {_account_id: 1}), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_computeDescriptionPlaceholder', () => {
|
|
||||||
assert.equal(element._computeDescriptionPlaceholder(true),
|
|
||||||
'No patch set description');
|
|
||||||
assert.equal(element._computeDescriptionPlaceholder(false),
|
|
||||||
'Add a patch set description');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_computePatchSetDisabled', () => {
|
|
||||||
element._sortedRevisions = [
|
|
||||||
{_number: 1},
|
|
||||||
{_number: 2},
|
|
||||||
{_number: element.EDIT_NAME, basePatchNum: 2},
|
|
||||||
{_number: 3},
|
|
||||||
];
|
|
||||||
let basePatchNum = 'PARENT';
|
|
||||||
let patchNum = 1;
|
|
||||||
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
|
||||||
false);
|
|
||||||
basePatchNum = 1;
|
|
||||||
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
|
||||||
true);
|
|
||||||
patchNum = 2;
|
|
||||||
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
|
||||||
false);
|
|
||||||
basePatchNum = element.EDIT_NAME;
|
|
||||||
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
|
||||||
true);
|
|
||||||
patchNum = '3';
|
|
||||||
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
|
||||||
false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_prepareCommitMsgForLinkify', () => {
|
test('_prepareCommitMsgForLinkify', () => {
|
||||||
let commitMessage = 'R=test@google.com';
|
let commitMessage = 'R=test@google.com';
|
||||||
let result = element._prepareCommitMsgForLinkify(commitMessage);
|
let result = element._prepareCommitMsgForLinkify(commitMessage);
|
||||||
@@ -325,80 +273,6 @@ limitations under the License.
|
|||||||
assert.equal(result, 'CC=\u200Btest@google.com');
|
assert.equal(result, 'CC=\u200Btest@google.com');
|
||||||
}),
|
}),
|
||||||
|
|
||||||
test('_computePatchSetCommentsString', () => {
|
|
||||||
// Test string with unresolved comments.
|
|
||||||
comments = {
|
|
||||||
foo: 'foo comments',
|
|
||||||
bar: 'bar comments',
|
|
||||||
xyz: 'xyz comments',
|
|
||||||
};
|
|
||||||
sandbox.stub(element.$.fileList, 'getCommentsForPath', (c, p, f) => {
|
|
||||||
if (f == 'foo') {
|
|
||||||
return ['comment1', 'comment2'];
|
|
||||||
} else if (f == 'bar') {
|
|
||||||
return ['comment1'];
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
sandbox.stub(element.$.fileList, 'computeUnresolvedNum', (c, d, p, f) => {
|
|
||||||
if (f == 'foo') {
|
|
||||||
return 0;
|
|
||||||
} else if (f == 'bar') {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
assert.equal(element._computePatchSetCommentsString(comments, 1),
|
|
||||||
'(3 comments, 1 unresolved)');
|
|
||||||
|
|
||||||
// Test string with no unresolved comments.
|
|
||||||
delete comments['bar'];
|
|
||||||
assert.equal(element._computePatchSetCommentsString(comments, 1),
|
|
||||||
'(2 comments)');
|
|
||||||
|
|
||||||
// Test string with no comments.
|
|
||||||
delete comments['foo'];
|
|
||||||
assert.equal(element._computePatchSetCommentsString(comments, 1), '');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_handleDescriptionChanged', () => {
|
|
||||||
const putDescStub = sandbox.stub(element.$.restAPI, 'setDescription')
|
|
||||||
.returns(Promise.resolve({ok: true}));
|
|
||||||
sandbox.stub(element, '_computeDescriptionReadOnly');
|
|
||||||
|
|
||||||
element._changeNum = '42';
|
|
||||||
element._patchRange = {
|
|
||||||
basePatchNum: 'PARENT',
|
|
||||||
patchNum: 1,
|
|
||||||
};
|
|
||||||
element._selectedPatchNum = '1';
|
|
||||||
element._change = {
|
|
||||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
|
||||||
revisions: {
|
|
||||||
rev1: {_number: 1, description: 'test', commit: {commit: 'rev1'}},
|
|
||||||
},
|
|
||||||
current_revision: 'rev1',
|
|
||||||
status: 'NEW',
|
|
||||||
labels: {},
|
|
||||||
actions: {},
|
|
||||||
owner: {_account_id: 1},
|
|
||||||
};
|
|
||||||
element._account = {_account_id: 1};
|
|
||||||
element._loggedIn = true;
|
|
||||||
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
const label = element.$.descriptionLabel;
|
|
||||||
assert.equal(label.value, 'test');
|
|
||||||
label.editing = true;
|
|
||||||
label._inputText = 'test2';
|
|
||||||
label._save();
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.isTrue(putDescStub.called);
|
|
||||||
assert.equal(putDescStub.args[0][2], 'test2');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_updateRebaseAction', () => {
|
test('_updateRebaseAction', () => {
|
||||||
const currentRevisionActions = {
|
const currentRevisionActions = {
|
||||||
cherrypick: {
|
cherrypick: {
|
||||||
@@ -572,106 +446,6 @@ limitations under the License.
|
|||||||
assert.equal(element._numFilesShown, 200);
|
assert.equal(element._numFilesShown, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('patch num change', done => {
|
|
||||||
element._changeNum = '42';
|
|
||||||
element._patchRange = {
|
|
||||||
basePatchNum: 'PARENT',
|
|
||||||
patchNum: 2,
|
|
||||||
};
|
|
||||||
element._change = {
|
|
||||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
|
||||||
revisions: {
|
|
||||||
rev2: {_number: 2},
|
|
||||||
rev1: {_number: 1},
|
|
||||||
rev13: {_number: 13},
|
|
||||||
rev3: {_number: 3},
|
|
||||||
},
|
|
||||||
current_revision: 'rev3',
|
|
||||||
status: 'NEW',
|
|
||||||
labels: {},
|
|
||||||
};
|
|
||||||
element.viewState.diffMode = 'UNIFIED';
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
|
|
||||||
const selectEl = element.$$('.patchInfo-header gr-select');
|
|
||||||
assert.ok(selectEl);
|
|
||||||
const optionEls = Polymer.dom(element.root).querySelectorAll(
|
|
||||||
'.patchInfo-header option');
|
|
||||||
assert.equal(optionEls.length, 4);
|
|
||||||
const select = element.$$('.patchInfo-header #patchSetSelect').bindValue;
|
|
||||||
assert.notEqual(select, 1);
|
|
||||||
assert.equal(select, 2);
|
|
||||||
assert.notEqual(select, 3);
|
|
||||||
assert.equal(optionEls[3].value, 13);
|
|
||||||
|
|
||||||
let numEvents = 0;
|
|
||||||
selectEl.addEventListener('change', e => {
|
|
||||||
assert.equal(element.viewState.diffMode, 'UNIFIED');
|
|
||||||
numEvents++;
|
|
||||||
if (numEvents == 1) {
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, '1', 'PARENT'));
|
|
||||||
selectEl.nativeSelect.value = '3';
|
|
||||||
element.fire('change', {}, {node: selectEl.nativeSelect});
|
|
||||||
} else if (numEvents == 2) {
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, '3', 'PARENT'));
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
selectEl.nativeSelect.value = '1';
|
|
||||||
element.fire('change', {}, {node: selectEl.nativeSelect});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('patch num change with missing current_revision', done => {
|
|
||||||
element._changeNum = '42';
|
|
||||||
element._patchRange = {
|
|
||||||
basePatchNum: 'PARENT',
|
|
||||||
patchNum: 2,
|
|
||||||
};
|
|
||||||
element._change = {
|
|
||||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
|
||||||
revisions: {
|
|
||||||
rev2: {_number: 2},
|
|
||||||
rev1: {_number: 1},
|
|
||||||
rev13: {_number: 13},
|
|
||||||
rev3: {_number: 3},
|
|
||||||
},
|
|
||||||
status: 'NEW',
|
|
||||||
labels: {},
|
|
||||||
};
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
const selectEl = element.$$('.patchInfo-header gr-select');
|
|
||||||
assert.ok(selectEl);
|
|
||||||
const optionEls = Polymer.dom(element.root).querySelectorAll(
|
|
||||||
'.patchInfo-header option');
|
|
||||||
assert.equal(optionEls.length, 4);
|
|
||||||
assert.notEqual(
|
|
||||||
element.$$('.patchInfo-header #patchSetSelect').bindValue, 1);
|
|
||||||
assert.equal(
|
|
||||||
element.$$('.patchInfo-header #patchSetSelect').bindValue, 2);
|
|
||||||
assert.notEqual(
|
|
||||||
element.$$('.patchInfo-header #patchSetSelect').bindValue, 3);
|
|
||||||
assert.equal(optionEls[3].value, 13);
|
|
||||||
|
|
||||||
let numEvents = 0;
|
|
||||||
selectEl.addEventListener('change', e => {
|
|
||||||
numEvents++;
|
|
||||||
if (numEvents == 1) {
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, '1', 'PARENT'));
|
|
||||||
selectEl.nativeSelect.value = '3';
|
|
||||||
element.fire('change', {}, {node: selectEl.nativeSelect});
|
|
||||||
} else if (numEvents == 2) {
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, '3', 'PARENT'));
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
selectEl.nativeSelect.value = '1';
|
|
||||||
element.fire('change', {}, {node: selectEl.nativeSelect});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('diffMode defaults to side by side without preferences', done => {
|
test('diffMode defaults to side by side without preferences', done => {
|
||||||
sandbox.stub(element.$.restAPI, 'getPreferences').returns(
|
sandbox.stub(element.$.restAPI, 'getPreferences').returns(
|
||||||
Promise.resolve({}));
|
Promise.resolve({}));
|
||||||
@@ -703,101 +477,6 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('diff against dropdown', done => {
|
|
||||||
element._changeNum = '42';
|
|
||||||
element._patchRange = {
|
|
||||||
basePatchNum: 'PARENT',
|
|
||||||
patchNum: '3',
|
|
||||||
};
|
|
||||||
element._change = {
|
|
||||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
|
||||||
revisions: {
|
|
||||||
rev1: {_number: 1},
|
|
||||||
rev2: {_number: 2},
|
|
||||||
rev3: {_number: 'edit', basePatchNum: 2},
|
|
||||||
rev4: {_number: 3},
|
|
||||||
},
|
|
||||||
status: 'NEW',
|
|
||||||
labels: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
flush(() => {
|
|
||||||
const selectEl = element.$.patchChange;
|
|
||||||
assert.equal(selectEl.nativeSelect.value, 'PARENT');
|
|
||||||
assert.isTrue(element.$$('#patchChange option[value="3"]')
|
|
||||||
.hasAttribute('disabled'));
|
|
||||||
selectEl.addEventListener('change', () => {
|
|
||||||
assert.equal(selectEl.nativeSelect.value, 'edit');
|
|
||||||
assert(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, '3', 'edit'),
|
|
||||||
'Should navigate to /c/42/edit..3');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
selectEl.nativeSelect.value = 'edit';
|
|
||||||
element.fire('change', {}, {node: selectEl.nativeSelect});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('expandAllDiffs called when expand button clicked', () => {
|
|
||||||
element._shownFileCount = 1;
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
sandbox.stub(element.$.fileList, 'expandAllDiffs');
|
|
||||||
MockInteractions.tap(Polymer.dom(element.root).querySelector(
|
|
||||||
'#expandBtn'));
|
|
||||||
assert.isTrue(element.$.fileList.expandAllDiffs.called);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('collapseAllDiffs called when expand button clicked', () => {
|
|
||||||
element._shownFileCount = 1;
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
sandbox.stub(element.$.fileList, 'collapseAllDiffs');
|
|
||||||
MockInteractions.tap(Polymer.dom(element.root).querySelector(
|
|
||||||
'#collapseBtn'));
|
|
||||||
assert.isTrue(element.$.fileList.collapseAllDiffs.called);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('show/hide diffs disabled for large amounts of files', done => {
|
|
||||||
const computeSpy = sandbox.spy(element, '_fileListActionsVisible');
|
|
||||||
element._files = [];
|
|
||||||
element.changeNum = '42';
|
|
||||||
element.patchRange = {
|
|
||||||
basePatchNum: 'PARENT',
|
|
||||||
patchNum: '2',
|
|
||||||
};
|
|
||||||
element._shownFileCount = 1;
|
|
||||||
flush(() => {
|
|
||||||
assert.isTrue(computeSpy.lastCall.returnValue);
|
|
||||||
_.times(element._maxFilesForBulkActions + 1, () => {
|
|
||||||
element._shownFileCount = element._shownFileCount + 1;
|
|
||||||
});
|
|
||||||
assert.isFalse(computeSpy.lastCall.returnValue);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('diff mode selector initializes from preferences', () => {
|
|
||||||
let resolvePrefs;
|
|
||||||
const prefsPromise = new Promise(resolve => {
|
|
||||||
resolvePrefs = resolve;
|
|
||||||
});
|
|
||||||
sandbox.stub(element.$.restAPI, 'getPreferences').returns(prefsPromise);
|
|
||||||
|
|
||||||
// Attach a new gr-change-view so we can intercept the preferences fetch.
|
|
||||||
const view = document.createElement('gr-change-view');
|
|
||||||
const select = view.$.modeSelect;
|
|
||||||
fixture('blank').appendChild(view);
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
|
|
||||||
// At this point the diff mode doesn't yet have the user's preference.
|
|
||||||
assert.equal(select.nativeSelect.value, 'SIDE_BY_SIDE');
|
|
||||||
|
|
||||||
// Receive the overriding preference.
|
|
||||||
resolvePrefs({default_diff_view: 'UNIFIED'});
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
assert.equal(select.nativeSelect.value, 'SIDE_BY_SIDE');
|
|
||||||
document.getElementById('blank').restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('don’t reload entire page when patchRange changes', () => {
|
test('don’t reload entire page when patchRange changes', () => {
|
||||||
const reloadStub = sandbox.stub(element, '_reload',
|
const reloadStub = sandbox.stub(element, '_reload',
|
||||||
() => { return Promise.resolve(); });
|
() => { return Promise.resolve(); });
|
||||||
@@ -841,35 +520,6 @@ limitations under the License.
|
|||||||
assert.isTrue(collapseStub.calledTwice);
|
assert.isTrue(collapseStub.calledTwice);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('include base patch when not parent', () => {
|
|
||||||
element._changeNum = '42';
|
|
||||||
element._patchRange = {
|
|
||||||
basePatchNum: '2',
|
|
||||||
patchNum: '3',
|
|
||||||
};
|
|
||||||
element._change = {
|
|
||||||
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
|
||||||
revisions: {
|
|
||||||
rev2: {_number: 2},
|
|
||||||
rev1: {_number: 1},
|
|
||||||
rev13: {_number: 13},
|
|
||||||
rev3: {_number: 3},
|
|
||||||
},
|
|
||||||
status: 'NEW',
|
|
||||||
labels: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
element._changePatchNum(13, 2);
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, 13, 2));
|
|
||||||
|
|
||||||
element._patchRange.basePatchNum = 'PARENT';
|
|
||||||
|
|
||||||
element._changePatchNum(3, 'PARENT');
|
|
||||||
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
|
||||||
element._change, 3, 'PARENT'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('related changes are updated and new patch selected after rebase',
|
test('related changes are updated and new patch selected after rebase',
|
||||||
done => {
|
done => {
|
||||||
element._changeNum = '42';
|
element._changeNum = '42';
|
||||||
@@ -888,7 +538,6 @@ limitations under the License.
|
|||||||
|
|
||||||
test('related changes are not updated after other action', done => {
|
test('related changes are not updated after other action', done => {
|
||||||
sandbox.stub(element, '_reload', () => { return Promise.resolve(); });
|
sandbox.stub(element, '_reload', () => { return Promise.resolve(); });
|
||||||
sandbox.stub(element, '_updateSelected');
|
|
||||||
sandbox.stub(element.$.relatedChanges, 'reload');
|
sandbox.stub(element.$.relatedChanges, 'reload');
|
||||||
const e = {detail: {action: 'abandon'}};
|
const e = {detail: {action: 'abandon'}};
|
||||||
element._handleReloadChange(e).then(() => {
|
element._handleReloadChange(e).then(() => {
|
||||||
@@ -1092,15 +741,6 @@ limitations under the License.
|
|||||||
'_openReplyDialog should have been passed CCS');
|
'_openReplyDialog should have been passed CCS');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('class is applied to file list on old patch set', () => {
|
|
||||||
const allPatchSets = [{num: 1}, {num: 2}, {num: 4}];
|
|
||||||
assert.equal(element._computePatchInfoClass('1', allPatchSets),
|
|
||||||
'patchInfoOldPatchSet');
|
|
||||||
assert.equal(element._computePatchInfoClass('2', allPatchSets),
|
|
||||||
'patchInfoOldPatchSet');
|
|
||||||
assert.equal(element._computePatchInfoClass('4', allPatchSets), '');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getUrlParameter functionality', () => {
|
test('getUrlParameter functionality', () => {
|
||||||
const locationStub = sandbox.stub(element, '_getLocationSearch');
|
const locationStub = sandbox.stub(element, '_getLocationSearch');
|
||||||
|
|
||||||
@@ -1510,30 +1150,14 @@ limitations under the License.
|
|||||||
assert.equal(element._patchRange.patchNum, 'baz');
|
assert.equal(element._patchRange.patchNum, 'baz');
|
||||||
});
|
});
|
||||||
|
|
||||||
suite('editLoaded behavior', () => {
|
test('_editLoaded set when patchNum is an edit', () => {
|
||||||
setup(() => {
|
sandbox.stub(element, 'computeLatestPatchNum').returns('2');
|
||||||
element._loggedIn = true;
|
element._patchRange = {patchNum: element.EDIT_NAME};
|
||||||
element._diffPrefs = {};
|
|
||||||
});
|
|
||||||
|
|
||||||
const isVisible = el => {
|
assert.isTrue(element._editLoaded);
|
||||||
assert.ok(el);
|
element.set('_patchRange.patchNum', 1);
|
||||||
return getComputedStyle(el).getPropertyValue('display') !== 'none';
|
|
||||||
};
|
|
||||||
|
|
||||||
test('patch specific elements', () => {
|
assert.isFalse(element._editLoaded);
|
||||||
sandbox.stub(element, 'computeLatestPatchNum').returns('2');
|
|
||||||
element._patchRange = {patchNum: element.EDIT_NAME};
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
|
|
||||||
assert.isFalse(isVisible(element.$.diffPrefsContainer));
|
|
||||||
assert.isFalse(isVisible(element.$$('.descriptionContainer')));
|
|
||||||
element.set('_patchRange.patchNum', 1);
|
|
||||||
flushAsynchronousOperations();
|
|
||||||
|
|
||||||
assert.isTrue(isVisible(element.$$('.descriptionContainer')));
|
|
||||||
assert.isTrue(isVisible(element.$.diffPrefsContainer));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -0,0 +1,226 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2017 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
|
||||||
|
<link rel="import" href="../../../styles/shared-styles.html">
|
||||||
|
<link rel="import" href="../../core/gr-navigation/gr-navigation.html">
|
||||||
|
<link rel="import" href="../../shared/gr-editable-label/gr-editable-label.html">
|
||||||
|
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||||
|
<link rel="import" href="../../shared/gr-select/gr-select.html">
|
||||||
|
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||||
|
|
||||||
|
|
||||||
|
<dom-module id="gr-file-list-header">
|
||||||
|
<template>
|
||||||
|
<style include="shared-styles">
|
||||||
|
.prefsButton {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.collapseToggleButton {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.patchInfoEdit.patchInfo-header {
|
||||||
|
background-color: #fcfad6;
|
||||||
|
}
|
||||||
|
.patchInfoOldPatchSet.patchInfo-header {
|
||||||
|
background-color: #fff9c4;
|
||||||
|
}
|
||||||
|
.patchInfoOldPatchSet .latestPatchContainer {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
.patchInfo-header {
|
||||||
|
padding: .5em calc(var(--default-horizontal-margin) / 2);
|
||||||
|
}
|
||||||
|
.patchInfo-header {
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
border-bottom: 1px solid #ebebeb;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.latestPatchContainer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.patchSetSelect {
|
||||||
|
max-width: 8em;
|
||||||
|
}
|
||||||
|
gr-editable-label.descriptionLabel {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#diffPrefsContainer,
|
||||||
|
.rightControls {
|
||||||
|
margin: auto 0 auto auto;
|
||||||
|
}
|
||||||
|
.patchInfo-header-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.showOnEdit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editLoaded .hideOnEdit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editLoaded .showOnEdit {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
.fileList-header {
|
||||||
|
display: flex;
|
||||||
|
font-weight: bold;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: .5em calc(var(--default-horizontal-margin) / 2);
|
||||||
|
}
|
||||||
|
.rightControls {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
font-weight: normal;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
.separator {
|
||||||
|
margin: 0 .25em;
|
||||||
|
}
|
||||||
|
.expandInline {
|
||||||
|
padding-right: .25em;
|
||||||
|
}
|
||||||
|
.patchSetSelect {
|
||||||
|
max-width: 8em;
|
||||||
|
}
|
||||||
|
.editLoaded .hideOnEdit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editLoaded .showOnEdit {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class$="patchInfo-header [[_computeEditLoadedClass(editLoaded)]] [[_computePatchInfoClass(patchRange.patchNum, allPatchSets)]]">
|
||||||
|
<div class="patchInfo-header-wrapper">
|
||||||
|
<label class="patchSelectLabel" for="patchSetSelect">
|
||||||
|
Patch set
|
||||||
|
</label>
|
||||||
|
<gr-select
|
||||||
|
id="patchSetSelect"
|
||||||
|
bind-value="{{_selectedPatchSet}}"
|
||||||
|
class="patchSetSelect"
|
||||||
|
on-change="_handlePatchChange">
|
||||||
|
<select>
|
||||||
|
<template is="dom-repeat" items="[[allPatchSets]]"
|
||||||
|
as="patchNum">
|
||||||
|
<option
|
||||||
|
value$="[[patchNum.num]]"
|
||||||
|
disabled$="[[_computePatchSetDisabled(patchNum.num, patchRange.basePatchNum, revisions)]]">
|
||||||
|
[[patchNum.num]]
|
||||||
|
/
|
||||||
|
[[computeLatestPatchNum(allPatchSets)]]
|
||||||
|
[[_computePatchSetCommentsString(comments, patchNum.num)]]
|
||||||
|
[[_computePatchSetDescription(change, patchNum.num)]]
|
||||||
|
</option>
|
||||||
|
</template>
|
||||||
|
</select>
|
||||||
|
</gr-select>
|
||||||
|
/
|
||||||
|
<gr-commit-info
|
||||||
|
change="[[change]]"
|
||||||
|
server-config="[[serverConfig]]"
|
||||||
|
commit-info="[[commitInfo]]"></gr-commit-info>
|
||||||
|
<span class="latestPatchContainer">
|
||||||
|
/
|
||||||
|
<a href$="[[changeUrl]]">Go to latest patch set</a>
|
||||||
|
</span>
|
||||||
|
<span class="downloadContainer desktop">
|
||||||
|
/
|
||||||
|
<gr-button link
|
||||||
|
class="download"
|
||||||
|
on-tap="_handleDownloadTap">Download</gr-button>
|
||||||
|
</span>
|
||||||
|
<span class="descriptionContainer hideOnEdit">
|
||||||
|
/
|
||||||
|
<gr-editable-label
|
||||||
|
id="descriptionLabel"
|
||||||
|
class="descriptionLabel"
|
||||||
|
value="[[_computePatchSetDescription(change, _selectedPatchSet)]]"
|
||||||
|
placeholder="[[_computeDescriptionPlaceholder(_descriptionReadOnly)]]"
|
||||||
|
read-only="[[_descriptionReadOnly]]"
|
||||||
|
on-changed="_handleDescriptionChanged"></gr-editable-label>
|
||||||
|
</span>
|
||||||
|
<span id="diffPrefsContainer"
|
||||||
|
class="hideOnEdit"
|
||||||
|
hidden$="[[_computePrefsButtonHidden(diffPrefs, loggedIn)]]"
|
||||||
|
hidden>
|
||||||
|
<gr-button link
|
||||||
|
class="prefsButton desktop"
|
||||||
|
on-tap="_handlePrefsTap">Diff Preferences</gr-button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="fileList-header">
|
||||||
|
<div>Files</div>
|
||||||
|
<div class="rightControls">
|
||||||
|
<template is="dom-if"
|
||||||
|
if="[[_fileListActionsVisible(shownFileCount, _maxFilesForBulkActions)]]">
|
||||||
|
<gr-button
|
||||||
|
id="expandBtn"
|
||||||
|
link
|
||||||
|
on-tap="_expandAllDiffs">Show diffs</gr-button>
|
||||||
|
<span class="separator">/</span>
|
||||||
|
<gr-button
|
||||||
|
id="collapseBtn"
|
||||||
|
link
|
||||||
|
on-tap="_collapseAllDiffs">Hide diffs</gr-button>
|
||||||
|
</template>
|
||||||
|
<template is="dom-if"
|
||||||
|
if="[[!_fileListActionsVisible(shownFileCount, _maxFilesForBulkActions)]]">
|
||||||
|
<div class="warning">
|
||||||
|
Bulk actions disabled because there are too many files.
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="separator">/</span>
|
||||||
|
<gr-select
|
||||||
|
id="modeSelect"
|
||||||
|
bind-value="{{diffViewMode}}">
|
||||||
|
<select>
|
||||||
|
<option value="SIDE_BY_SIDE">Side By Side</option>
|
||||||
|
<option value="UNIFIED_DIFF">Unified</option>
|
||||||
|
</select>
|
||||||
|
</gr-select>
|
||||||
|
<span class="separator">/</span>
|
||||||
|
<label>
|
||||||
|
Diff against
|
||||||
|
<gr-select id="patchChange" bind-value="{{_diffAgainst}}"
|
||||||
|
class="patchSetSelect" on-change="_handleBasePatchChange">
|
||||||
|
<select>
|
||||||
|
<option value="PARENT">Base</option>
|
||||||
|
<template
|
||||||
|
is="dom-repeat"
|
||||||
|
items="[[allPatchSets]]"
|
||||||
|
as="patchNum">
|
||||||
|
<option
|
||||||
|
disabled$="[[_computeBasePatchDisabled(patchNum.num, patchRange.patchNum, revisions)]]"
|
||||||
|
value$="[[patchNum.num]]">
|
||||||
|
[[patchNum.num]]
|
||||||
|
[[patchNum.desc]]
|
||||||
|
</option>
|
||||||
|
</template>
|
||||||
|
</select>
|
||||||
|
</gr-select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||||
|
</template>
|
||||||
|
<script src="gr-file-list-header.js"></script>
|
||||||
|
</dom-module>
|
@@ -0,0 +1,264 @@
|
|||||||
|
// Copyright (C) 2017 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.
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Maximum length for patch set descriptions.
|
||||||
|
const PATCH_DESC_MAX_LENGTH = 500;
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'gr-file-list-header',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
account: Object,
|
||||||
|
allPatchSets: Array,
|
||||||
|
change: Object,
|
||||||
|
changeNum: String,
|
||||||
|
changeUrl: String,
|
||||||
|
comments: Object,
|
||||||
|
commitInfo: Object,
|
||||||
|
editLoaded: Boolean,
|
||||||
|
loggedIn: Boolean,
|
||||||
|
serverConfig: Object,
|
||||||
|
shownFileCount: Number,
|
||||||
|
diffPrefs: Object,
|
||||||
|
diffViewMode: String,
|
||||||
|
/** @type {?} */
|
||||||
|
patchRange: {
|
||||||
|
type: Object,
|
||||||
|
observer: 'updateSelected',
|
||||||
|
},
|
||||||
|
revisions: Array,
|
||||||
|
// Caps the number of files that can be shown and have the 'show diffs' /
|
||||||
|
// 'hide diffs' buttons still be functional.
|
||||||
|
_maxFilesForBulkActions: {
|
||||||
|
type: Number,
|
||||||
|
readOnly: true,
|
||||||
|
value: 225,
|
||||||
|
},
|
||||||
|
_descriptionReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
computed: '_computeDescriptionReadOnly(loggedIn, change, account)',
|
||||||
|
},
|
||||||
|
_selectedPatchSet: String,
|
||||||
|
_diffAgainst: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
behaviors: [
|
||||||
|
Gerrit.PatchSetBehavior,
|
||||||
|
],
|
||||||
|
|
||||||
|
_expandAllDiffs() {
|
||||||
|
this.fire('expand-diffs');
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapseAllDiffs() {
|
||||||
|
this.fire('collapse-diffs');
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSelected() {
|
||||||
|
this._selectedPatchSet = this.patchRange.patchNum;
|
||||||
|
this._diffAgainst = this.patchRange.basePatchNum;
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeDescriptionPlaceholder(readOnly) {
|
||||||
|
return (readOnly ? 'No' : 'Add a') + ' patch set description';
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeDescriptionReadOnly(loggedIn, change, account) {
|
||||||
|
return !(loggedIn && (account._account_id === change.owner._account_id));
|
||||||
|
},
|
||||||
|
|
||||||
|
_computePatchSetDescription(change, patchNum) {
|
||||||
|
const rev = this.getRevisionByPatchNum(change.revisions, patchNum);
|
||||||
|
return (rev && rev.description) ?
|
||||||
|
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} revisions The revisions object keyed by revision hashes
|
||||||
|
* @param {?Object} patchSet A revision already fetched from {revisions}
|
||||||
|
* @return {string|undefined} the SHA hash corresponding to the revision.
|
||||||
|
*/
|
||||||
|
_getPatchsetHash(revisions, patchSet) {
|
||||||
|
for (const rev in revisions) {
|
||||||
|
if (revisions.hasOwnProperty(rev) &&
|
||||||
|
revisions[rev] === patchSet) {
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleDescriptionChanged(e) {
|
||||||
|
const desc = e.detail.trim();
|
||||||
|
const rev = this.getRevisionByPatchNum(this.change.revisions,
|
||||||
|
this._selectedPatchSet);
|
||||||
|
const sha = this._getPatchsetHash(this.change.revisions, rev);
|
||||||
|
this.$.restAPI.setDescription(this.changeNum,
|
||||||
|
this._selectedPatchSet, desc)
|
||||||
|
.then(res => {
|
||||||
|
if (res.ok) {
|
||||||
|
this.set(['_change', 'revisions', sha, 'description'], desc);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeBasePatchDisabled(patchNum, currentPatchNum) {
|
||||||
|
return this.findSortedIndex(patchNum, this.revisions) >=
|
||||||
|
this.findSortedIndex(currentPatchNum, this.revisions);
|
||||||
|
},
|
||||||
|
|
||||||
|
_computePrefsButtonHidden(prefs, loggedIn) {
|
||||||
|
return !loggedIn || !prefs;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Copied from gr-file-list
|
||||||
|
_getCommentsForPath(comments, patchNum, path) {
|
||||||
|
return (comments[path] || []).filter(c => {
|
||||||
|
return this.patchNumEquals(c.patch_set, patchNum);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Copied from gr-file-list
|
||||||
|
_computeUnresolvedNum(comments, drafts, patchNum, path) {
|
||||||
|
comments = this._getCommentsForPath(comments, patchNum, path);
|
||||||
|
drafts = this._getCommentsForPath(drafts, patchNum, path);
|
||||||
|
comments = comments.concat(drafts);
|
||||||
|
|
||||||
|
// Create an object where every comment ID is the key of an unresolved
|
||||||
|
// comment.
|
||||||
|
|
||||||
|
const idMap = comments.reduce((acc, comment) => {
|
||||||
|
if (comment.unresolved) {
|
||||||
|
acc[comment.id] = true;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Set false for the comments that are marked as parents.
|
||||||
|
for (const comment of comments) {
|
||||||
|
idMap[comment.in_reply_to] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The unresolved comments are the comments that still have true.
|
||||||
|
const unresolvedLeaves = Object.keys(idMap).filter(key => {
|
||||||
|
return idMap[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return unresolvedLeaves.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
_computePatchSetCommentsString(allComments, patchNum) {
|
||||||
|
let numComments = 0;
|
||||||
|
let numUnresolved = 0;
|
||||||
|
for (const file in allComments) {
|
||||||
|
if (allComments.hasOwnProperty(file)) {
|
||||||
|
numComments += this._getCommentsForPath(
|
||||||
|
allComments, patchNum, file).length;
|
||||||
|
numUnresolved += this._computeUnresolvedNum(
|
||||||
|
allComments, {}, patchNum, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let commentsStr = '';
|
||||||
|
if (numComments > 0) {
|
||||||
|
commentsStr = '(' + numComments + ' comments';
|
||||||
|
if (numUnresolved > 0) {
|
||||||
|
commentsStr += ', ' + numUnresolved + ' unresolved';
|
||||||
|
}
|
||||||
|
commentsStr += ')';
|
||||||
|
}
|
||||||
|
return commentsStr;
|
||||||
|
},
|
||||||
|
|
||||||
|
_fileListActionsVisible(shownFileCount, maxFilesForBulkActions) {
|
||||||
|
return shownFileCount <= maxFilesForBulkActions;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a patch number should be disabled based on value of the
|
||||||
|
* basePatchNum from gr-file-list.
|
||||||
|
* @param {number} patchNum Patch number available in dropdown
|
||||||
|
* @param {number|string} basePatchNum Base patch number from file list
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
_computePatchSetDisabled(patchNum, basePatchNum) {
|
||||||
|
if (basePatchNum === 'PARENT') { return false; }
|
||||||
|
|
||||||
|
return this.findSortedIndex(patchNum, this.revisions) <=
|
||||||
|
this.findSortedIndex(basePatchNum, this.revisions);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change active patch to the provided patch num.
|
||||||
|
* @param {number|string} basePatchNum the base patch to be viewed.
|
||||||
|
* @param {number|string} patchNum the patch number to be viewed.
|
||||||
|
* @param {boolean} opt_forceParams When set to true, the resulting URL will
|
||||||
|
* always include the patch range, even if the requested patchNum is
|
||||||
|
* known to be the latest.
|
||||||
|
*/
|
||||||
|
_changePatchNum(patchNum, basePatchNum, opt_forceParams) {
|
||||||
|
if (!opt_forceParams) {
|
||||||
|
let currentPatchNum;
|
||||||
|
if (this.change.current_revision) {
|
||||||
|
currentPatchNum =
|
||||||
|
this.change.revisions[this.change.current_revision]._number;
|
||||||
|
} else {
|
||||||
|
currentPatchNum = this.computeLatestPatchNum(this.allPatchSets);
|
||||||
|
}
|
||||||
|
if (this.patchNumEquals(patchNum, currentPatchNum) &&
|
||||||
|
basePatchNum === 'PARENT') {
|
||||||
|
Gerrit.Nav.navigateToChange(this.change);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Gerrit.Nav.navigateToChange(this.change, patchNum,
|
||||||
|
basePatchNum);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleBasePatchChange(e) {
|
||||||
|
this._changePatchNum(this._selectedPatchSet, e.target.value, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handlePatchChange(e) {
|
||||||
|
this._changePatchNum(e.target.value, this._diffAgainst, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handlePrefsTap(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.fire('open-diff-prefs');
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleDownloadTap(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.fire('open-download-dialog');
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeEditLoadedClass(editLoaded) {
|
||||||
|
return editLoaded ? 'editLoaded' : '';
|
||||||
|
},
|
||||||
|
|
||||||
|
_computePatchInfoClass(patchNum, allPatchSets) {
|
||||||
|
if (this.patchNumEquals(patchNum, this.EDIT_NAME)) {
|
||||||
|
return 'patchInfoEdit';
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestNum = this.computeLatestPatchNum(allPatchSets);
|
||||||
|
if (this.patchNumEquals(patchNum, latestNum)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return 'patchInfoOldPatchSet';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
@@ -0,0 +1,435 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2017 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-file-list-header</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||||
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
|
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||||
|
<script src="../../../bower_components/page/page.js"></script>
|
||||||
|
|
||||||
|
<link rel="import" href="gr-file-list-header.html">
|
||||||
|
|
||||||
|
<script>void(0);</script>
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<gr-file-list-header></gr-file-list-header>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<test-fixture id="blank">
|
||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
suite('gr-file-list-header tests', () => {
|
||||||
|
let element;
|
||||||
|
let sandbox;
|
||||||
|
let navigateToChangeStub;
|
||||||
|
|
||||||
|
setup(() => {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
navigateToChangeStub = sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
||||||
|
stub('gr-rest-api-interface', {
|
||||||
|
getConfig() { return Promise.resolve({test: 'config'}); },
|
||||||
|
getAccount() { return Promise.resolve(null); },
|
||||||
|
_fetchSharedCacheURL() { return Promise.resolve({}); },
|
||||||
|
});
|
||||||
|
element = fixture('basic');
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown(done => {
|
||||||
|
flush(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Diff preferences hidden when no prefs or logged out', () => {
|
||||||
|
element.loggedIn = false;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
||||||
|
|
||||||
|
element.loggedIn = true;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
||||||
|
|
||||||
|
element.loggedIn = false;
|
||||||
|
element.diffPrefs = {font_size: '12'};
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isTrue(element.$.diffPrefsContainer.hidden);
|
||||||
|
|
||||||
|
element.loggedIn = true;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isFalse(element.$.diffPrefsContainer.hidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computeDescriptionReadOnly', () => {
|
||||||
|
assert.equal(element._computeDescriptionReadOnly(false,
|
||||||
|
{owner: {_account_id: 1}}, {_account_id: 1}), true);
|
||||||
|
assert.equal(element._computeDescriptionReadOnly(true,
|
||||||
|
{owner: {_account_id: 0}}, {_account_id: 1}), true);
|
||||||
|
assert.equal(element._computeDescriptionReadOnly(true,
|
||||||
|
{owner: {_account_id: 1}}, {_account_id: 1}), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computeDescriptionPlaceholder', () => {
|
||||||
|
assert.equal(element._computeDescriptionPlaceholder(true),
|
||||||
|
'No patch set description');
|
||||||
|
assert.equal(element._computeDescriptionPlaceholder(false),
|
||||||
|
'Add a patch set description');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computePatchSetDisabled', () => {
|
||||||
|
element.revisions = [
|
||||||
|
{_number: 1},
|
||||||
|
{_number: 2},
|
||||||
|
{_number: element.EDIT_NAME, basePatchNum: 2},
|
||||||
|
{_number: 3},
|
||||||
|
];
|
||||||
|
let basePatchNum = 'PARENT';
|
||||||
|
let patchNum = 1;
|
||||||
|
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
||||||
|
false);
|
||||||
|
basePatchNum = 1;
|
||||||
|
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
||||||
|
true);
|
||||||
|
patchNum = 2;
|
||||||
|
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
||||||
|
false);
|
||||||
|
basePatchNum = element.EDIT_NAME;
|
||||||
|
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
||||||
|
true);
|
||||||
|
patchNum = '3';
|
||||||
|
assert.equal(element._computePatchSetDisabled(patchNum, basePatchNum),
|
||||||
|
false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_computePatchSetCommentsString', () => {
|
||||||
|
// Test string with unresolved comments.
|
||||||
|
|
||||||
|
comments = {
|
||||||
|
foo: [{
|
||||||
|
id: '27dcee4d_f7b77cfa',
|
||||||
|
message: 'test',
|
||||||
|
patch_set: 1,
|
||||||
|
unresolved: true,
|
||||||
|
}],
|
||||||
|
bar: [{
|
||||||
|
id: '27dcee4d_f7b77cfa',
|
||||||
|
message: 'test',
|
||||||
|
patch_set: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '27dcee4d_f7b77cfa',
|
||||||
|
message: 'test',
|
||||||
|
patch_set: 1,
|
||||||
|
}],
|
||||||
|
abc: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.equal(element._computePatchSetCommentsString(comments, 1),
|
||||||
|
'(3 comments, 1 unresolved)');
|
||||||
|
|
||||||
|
// Test string with no unresolved comments.
|
||||||
|
delete comments['foo'];
|
||||||
|
assert.equal(element._computePatchSetCommentsString(comments, 1),
|
||||||
|
'(2 comments)');
|
||||||
|
|
||||||
|
// Test string with no comments.
|
||||||
|
delete comments['bar'];
|
||||||
|
assert.equal(element._computePatchSetCommentsString(comments, 1), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('_handleDescriptionChanged', () => {
|
||||||
|
const putDescStub = sandbox.stub(element.$.restAPI, 'setDescription')
|
||||||
|
.returns(Promise.resolve({ok: true}));
|
||||||
|
sandbox.stub(element, '_computeDescriptionReadOnly');
|
||||||
|
|
||||||
|
element.changeNum = '42';
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: 1,
|
||||||
|
};
|
||||||
|
element._selectedPatchNum = '1';
|
||||||
|
element.change = {
|
||||||
|
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||||
|
revisions: {
|
||||||
|
rev1: {_number: 1, description: 'test', commit: {commit: 'rev1'}},
|
||||||
|
},
|
||||||
|
current_revision: 'rev1',
|
||||||
|
status: 'NEW',
|
||||||
|
labels: {},
|
||||||
|
actions: {},
|
||||||
|
owner: {_account_id: 1},
|
||||||
|
};
|
||||||
|
element.account = {_account_id: 1};
|
||||||
|
element.loggedIn = true;
|
||||||
|
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
const label = element.$.descriptionLabel;
|
||||||
|
assert.equal(label.value, 'test');
|
||||||
|
label.editing = true;
|
||||||
|
label._inputText = 'test2';
|
||||||
|
label._save();
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isTrue(putDescStub.called);
|
||||||
|
assert.equal(putDescStub.args[0][2], 'test2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('patch num change', done => {
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
element.allPatchSets = [
|
||||||
|
{num: 1},
|
||||||
|
{num: 2},
|
||||||
|
{num: 3},
|
||||||
|
{num: 13},
|
||||||
|
];
|
||||||
|
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
|
||||||
|
const selectEl = element.$$('.patchInfo-header gr-select');
|
||||||
|
assert.ok(selectEl);
|
||||||
|
const optionEls = Polymer.dom(element.root).querySelectorAll(
|
||||||
|
'.patchInfo-header option');
|
||||||
|
assert.equal(optionEls.length, 4);
|
||||||
|
const select = element.$$('.patchInfo-header #patchSetSelect').bindValue;
|
||||||
|
assert.notEqual(select, 1);
|
||||||
|
assert.equal(select, 2);
|
||||||
|
assert.notEqual(select, 3);
|
||||||
|
assert.equal(optionEls[3].value, 13);
|
||||||
|
|
||||||
|
let numEvents = 0;
|
||||||
|
selectEl.addEventListener('change', e => {
|
||||||
|
assert.equal(element.diffViewMode, 'SIDE_BY_SIDE');
|
||||||
|
numEvents++;
|
||||||
|
if (numEvents == 1) {
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, '1', 'PARENT'));
|
||||||
|
selectEl.nativeSelect.value = '3';
|
||||||
|
element.fire('change', {}, {node: selectEl.nativeSelect});
|
||||||
|
} else if (numEvents == 2) {
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, '3', 'PARENT'));
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selectEl.nativeSelect.value = '1';
|
||||||
|
element.fire('change', {}, {node: selectEl.nativeSelect});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('patch num change with missing current_revision', done => {
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
element.allPatchSets = [
|
||||||
|
{num: 1},
|
||||||
|
{num: 2},
|
||||||
|
{num: 3},
|
||||||
|
{num: 13},
|
||||||
|
];
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
const selectEl = element.$$('.patchInfo-header gr-select');
|
||||||
|
assert.ok(selectEl);
|
||||||
|
const optionEls = Polymer.dom(element.root).querySelectorAll(
|
||||||
|
'.patchInfo-header option');
|
||||||
|
assert.equal(optionEls.length, 4);
|
||||||
|
assert.notEqual(
|
||||||
|
element.$$('.patchInfo-header #patchSetSelect').bindValue, 1);
|
||||||
|
assert.equal(
|
||||||
|
element.$$('.patchInfo-header #patchSetSelect').bindValue, 2);
|
||||||
|
assert.notEqual(
|
||||||
|
element.$$('.patchInfo-header #patchSetSelect').bindValue, 3);
|
||||||
|
assert.equal(optionEls[3].value, 13);
|
||||||
|
|
||||||
|
let numEvents = 0;
|
||||||
|
selectEl.addEventListener('change', e => {
|
||||||
|
numEvents++;
|
||||||
|
if (numEvents == 1) {
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, '1', 'PARENT'));
|
||||||
|
selectEl.nativeSelect.value = '3';
|
||||||
|
element.fire('change', {}, {node: selectEl.nativeSelect});
|
||||||
|
} else if (numEvents == 2) {
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, '3', 'PARENT'));
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selectEl.nativeSelect.value = '1';
|
||||||
|
element.fire('change', {}, {node: selectEl.nativeSelect});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('diff against dropdown', done => {
|
||||||
|
element.revisions = [
|
||||||
|
{commit: {}},
|
||||||
|
{commit: {}},
|
||||||
|
{commit: {}},
|
||||||
|
{commit: {}},
|
||||||
|
];
|
||||||
|
element.allPatchSets = [
|
||||||
|
{num: 1},
|
||||||
|
{num: 2},
|
||||||
|
{num: 3},
|
||||||
|
{num: 'edit'},
|
||||||
|
];
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: '3',
|
||||||
|
};
|
||||||
|
|
||||||
|
flush(() => {
|
||||||
|
const selectEl = element.$.patchChange;
|
||||||
|
assert.equal(selectEl.nativeSelect.value, 'PARENT');
|
||||||
|
assert.isTrue(element.$$('#patchChange option[value="3"]')
|
||||||
|
.hasAttribute('disabled'));
|
||||||
|
selectEl.addEventListener('change', () => {
|
||||||
|
assert.equal(selectEl.nativeSelect.value, 'edit');
|
||||||
|
assert(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, '3', 'edit'),
|
||||||
|
'Should navigate to /c/42/edit..3');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
selectEl.nativeSelect.value = 'edit';
|
||||||
|
element.fire('change', {}, {node: selectEl.nativeSelect});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('expandAllDiffs called when expand button clicked', () => {
|
||||||
|
element.shownFileCount = 1;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
sandbox.stub(element, '_expandAllDiffs');
|
||||||
|
MockInteractions.tap(Polymer.dom(element.root).querySelector(
|
||||||
|
'#expandBtn'));
|
||||||
|
assert.isTrue(element._expandAllDiffs.called);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('collapseAllDiffs called when expand button clicked', () => {
|
||||||
|
element.shownFileCount = 1;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
sandbox.stub(element, '_collapseAllDiffs');
|
||||||
|
MockInteractions.tap(Polymer.dom(element.root).querySelector(
|
||||||
|
'#collapseBtn'));
|
||||||
|
assert.isTrue(element._collapseAllDiffs.called);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('show/hide diffs disabled for large amounts of files', done => {
|
||||||
|
const computeSpy = sandbox.spy(element, '_fileListActionsVisible');
|
||||||
|
element._files = [];
|
||||||
|
element.changeNum = '42';
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: '2',
|
||||||
|
};
|
||||||
|
element.shownFileCount = 1;
|
||||||
|
flush(() => {
|
||||||
|
assert.isTrue(computeSpy.lastCall.returnValue);
|
||||||
|
_.times(element._maxFilesForBulkActions + 1, () => {
|
||||||
|
element.shownFileCount = element.shownFileCount + 1;
|
||||||
|
});
|
||||||
|
assert.isFalse(computeSpy.lastCall.returnValue);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('diff mode selector is set correctly', () => {
|
||||||
|
const select = element.$.modeSelect;
|
||||||
|
element.diffViewMode = 'SIDE_BY_SIDE';
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.equal(select.nativeSelect.value, 'SIDE_BY_SIDE');
|
||||||
|
|
||||||
|
element.diffViewMode = 'UNIFIED_DIFF';
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.equal(select.nativeSelect.value, 'UNIFIED_DIFF');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('include base patch when not parent', () => {
|
||||||
|
element.changeNum = '42';
|
||||||
|
element.patchRange = {
|
||||||
|
basePatchNum: '2',
|
||||||
|
patchNum: '3',
|
||||||
|
};
|
||||||
|
element.change = {
|
||||||
|
change_id: 'Iad9dc96274af6946f3632be53b106ef80f7ba6ca',
|
||||||
|
revisions: {
|
||||||
|
rev2: {_number: 2},
|
||||||
|
rev1: {_number: 1},
|
||||||
|
rev13: {_number: 13},
|
||||||
|
rev3: {_number: 3},
|
||||||
|
},
|
||||||
|
status: 'NEW',
|
||||||
|
labels: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
element._changePatchNum(13, 2);
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, 13, 2));
|
||||||
|
|
||||||
|
element.patchRange.basePatchNum = 'PARENT';
|
||||||
|
|
||||||
|
element._changePatchNum(3, 'PARENT');
|
||||||
|
assert.isTrue(navigateToChangeStub.lastCall.calledWithExactly(
|
||||||
|
element.change, 3, 'PARENT'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('class is applied to file list on old patch set', () => {
|
||||||
|
const allPatchSets = [{num: 1}, {num: 2}, {num: 4}];
|
||||||
|
assert.equal(element._computePatchInfoClass('1', allPatchSets),
|
||||||
|
'patchInfoOldPatchSet');
|
||||||
|
assert.equal(element._computePatchInfoClass('2', allPatchSets),
|
||||||
|
'patchInfoOldPatchSet');
|
||||||
|
assert.equal(element._computePatchInfoClass('4', allPatchSets), '');
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('editLoaded behavior', () => {
|
||||||
|
setup(() => {
|
||||||
|
element.loggedIn = true;
|
||||||
|
element.diffPrefs = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
const isVisible = el => {
|
||||||
|
assert.ok(el);
|
||||||
|
return getComputedStyle(el).getPropertyValue('display') !== 'none';
|
||||||
|
};
|
||||||
|
|
||||||
|
test('patch specific elements', () => {
|
||||||
|
element.editLoaded = true;
|
||||||
|
sandbox.stub(element, 'computeLatestPatchNum').returns('2');
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
|
||||||
|
assert.isFalse(isVisible(element.$.diffPrefsContainer));
|
||||||
|
assert.isFalse(isVisible(element.$$('.descriptionContainer')));
|
||||||
|
|
||||||
|
element.editLoaded = false;
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
|
||||||
|
assert.isTrue(isVisible(element.$$('.descriptionContainer')));
|
||||||
|
assert.isTrue(isVisible(element.$.diffPrefsContainer));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@@ -68,6 +68,7 @@ limitations under the License.
|
|||||||
'change/gr-label-scores/gr-label-scores_test.html',
|
'change/gr-label-scores/gr-label-scores_test.html',
|
||||||
'change/gr-label-score-row/gr-label-score-row_test.html',
|
'change/gr-label-score-row/gr-label-score-row_test.html',
|
||||||
'change/gr-file-list/gr-file-list_test.html',
|
'change/gr-file-list/gr-file-list_test.html',
|
||||||
|
'change/gr-file-list-header/gr-file-list-header_test.html',
|
||||||
'change/gr-message/gr-message_test.html',
|
'change/gr-message/gr-message_test.html',
|
||||||
'change/gr-messages-list/gr-messages-list_test.html',
|
'change/gr-messages-list/gr-messages-list_test.html',
|
||||||
'change/gr-related-changes-list/gr-related-changes-list_test.html',
|
'change/gr-related-changes-list/gr-related-changes-list_test.html',
|
||||||
|
Reference in New Issue
Block a user