summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Borden <frankborden@google.com>2022-04-08 17:38:08 +0200
committerPaladox none <thomasmulhall410@yahoo.com>2022-04-12 15:07:27 +0000
commite92610e588ae722b15a2a7c6e1dfe3f2524eb91b (patch)
tree83b5c5e57e864d7dfef44567870fc95d469aa538
parenta6847da2207e7e7c6ee47d9db728094195e0d629 (diff)
Convert gr-confirm-cherrypick-dialog to lit
Release-Notes: skip Change-Id: Ic5bd9ec99f50de2454083bf7607467716e59423c (cherry picked from commit 4f88a0fc8153c2cea1d21ab98115b3434cbd6062)
-rw-r--r--polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts8
-rw-r--r--polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts416
-rw-r--r--polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts223
-rw-r--r--polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts79
4 files changed, 373 insertions, 353 deletions
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
index 3ca7b0c2e3..50ab91c264 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
@@ -845,7 +845,7 @@ suite('gr-change-actions tests', () => {
sinon.stub(window, 'alert');
});
- test('works', () => {
+ test('works', async () => {
element._handleCherrypickTap();
const action = {
__key: 'cherrypick',
@@ -868,8 +868,10 @@ suite('gr-change-actions tests', () => {
element.$.confirmCherrypick.commitMessage = 'foo message';
element.$.confirmCherrypick.changeStatus = ChangeStatus.NEW;
element.$.confirmCherrypick.commitNum = '123' as CommitId;
+ await element.updateComplete;
element._handleCherrypickConfirm();
+ await element.updateComplete;
const autogrowEl = queryAndAssert<IronAutogrowTextareaElement>(
element.$.confirmCherrypick,
@@ -890,7 +892,7 @@ suite('gr-change-actions tests', () => {
]);
});
- test('cherry pick even with conflicts', () => {
+ test('cherry pick even with conflicts', async () => {
element._handleCherrypickTap();
const action = {
__key: 'cherrypick',
@@ -908,8 +910,10 @@ suite('gr-change-actions tests', () => {
element.$.confirmCherrypick.commitMessage = 'foo message';
element.$.confirmCherrypick.changeStatus = ChangeStatus.NEW;
element.$.confirmCherrypick.commitNum = '123' as CommitId;
+ await element.updateComplete;
element._handleCherrypickConflictConfirm();
+ await element.updateComplete;
assert.deepEqual(fireActionStub.lastCall.args, [
'/cherrypick',
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index c3ae19f981..828996ed44 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -19,8 +19,6 @@ import '@polymer/iron-input/iron-input';
import '../../../styles/shared-styles';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-dialog/gr-dialog';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-confirm-cherrypick-dialog_html';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getAppContext} from '../../../services/app-context';
import {
@@ -30,8 +28,13 @@ import {
CommitId,
ChangeInfoId,
} from '../../../types/common';
-import {customElement, property, observe} from '@polymer/decorators';
-import {GrTypedAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
+import {customElement, property, query, state} from 'lit/decorators';
+import {
+ AutocompleteCommitEvent,
+ AutocompleteQuery,
+ AutocompleteSuggestion,
+ GrTypedAutocomplete,
+} from '../../shared/gr-autocomplete/gr-autocomplete';
import {
HttpMethod,
ChangeStatus,
@@ -39,6 +42,11 @@ import {
} from '../../../constants/constants';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
import {fireEvent} from '../../../utils/event-util';
+import {css, html, LitElement, PropertyValues} from 'lit';
+import {sharedStyles} from '../../../styles/shared-styles';
+import {choose} from 'lit/directives/choose';
+import {when} from 'lit/directives/when';
+import {BindValueChangeEvent} from '../../../types/events';
const SUGGESTIONS_LIMIT = 15;
const CHANGE_SUBJECT_LIMIT = 50;
@@ -60,18 +68,8 @@ declare global {
}
}
-export interface GrConfirmCherrypickDialog {
- $: {
- branchInput: GrTypedAutocomplete<BranchName>;
- };
-}
-
@customElement('gr-confirm-cherrypick-dialog')
-export class GrConfirmCherrypickDialog extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
+export class GrConfirmCherrypickDialog extends LitElement {
/**
* Fired when the confirm button is pressed.
*
@@ -108,27 +106,30 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
@property({type: Array})
changes: ChangeInfo[] = [];
- @property({type: Object})
- _query?: (input: string) => Promise<{name: BranchName}[]>;
+ @state()
+ private query: AutocompleteQuery;
- @property({type: Boolean})
- _showCherryPickTopic = false;
+ @state()
+ private showCherryPickTopic = false;
- @property({type: Number})
- _changesCount?: number;
+ @state()
+ private changesCount?: number;
- @property({type: Number})
- _cherryPickType = CherryPickType.SINGLE_CHANGE;
+ @state()
+ cherryPickType = CherryPickType.SINGLE_CHANGE;
- @property({type: Boolean})
- _duplicateProjectChanges = false;
+ @state()
+ private duplicateProjectChanges = false;
- @property({type: Object})
+ @state()
// Status of each change that is being cherry picked together
- _statuses: Statuses;
+ private statuses: Statuses;
+
+ @state()
+ private invalidBranch = false;
- @property({type: Boolean})
- _invalidBranch = false;
+ @query('#branchInput')
+ branchInput!: GrTypedAutocomplete<BranchName>;
private selectedChangeIds = new Set<ChangeInfoId>();
@@ -138,8 +139,254 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
constructor() {
super();
- this._statuses = {};
- this._query = (text: string) => this._getProjectBranchesSuggestions(text);
+ this.statuses = {};
+ this.query = (text: string) => this.getProjectBranchesSuggestions(text);
+ }
+
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('branch')) {
+ this.updateBranch();
+ }
+ if (
+ changedProperties.has('changeStatus') ||
+ changedProperties.has('commitNum') ||
+ changedProperties.has('commitMessage')
+ ) {
+ this.computeMessage();
+ }
+ }
+
+ static override styles = [
+ sharedStyles,
+ css`
+ :host {
+ display: block;
+ }
+ :host([disabled]) {
+ opacity: 0.5;
+ pointer-events: none;
+ }
+ label {
+ cursor: pointer;
+ }
+ .main {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ }
+ .main label,
+ .main input[type='text'] {
+ display: block;
+ width: 100%;
+ }
+ iron-autogrow-textarea {
+ font-family: var(--monospace-font-family);
+ font-size: var(--font-size-mono);
+ line-height: var(--line-height-mono);
+ width: 73ch; /* Add a char to account for the border. */
+ }
+ .cherryPickTopicLayout {
+ display: flex;
+ align-items: center;
+ margin-bottom: var(--spacing-m);
+ }
+ .cherryPickSingleChange,
+ .cherryPickTopic {
+ margin-left: var(--spacing-m);
+ }
+ .cherry-pick-topic-message {
+ margin-bottom: var(--spacing-m);
+ }
+ label[for='messageInput'],
+ label[for='baseInput'] {
+ margin-top: var(--spacing-m);
+ }
+ .title {
+ font-weight: var(--font-weight-bold);
+ }
+ tr > td {
+ padding: var(--spacing-m);
+ }
+ th {
+ color: var(--deemphasized-text-color);
+ }
+ table {
+ border-collapse: collapse;
+ }
+ tr {
+ border-bottom: 1px solid var(--border-color);
+ }
+ .error {
+ color: var(--error-text-color);
+ }
+ .error-message {
+ color: var(--error-text-color);
+ margin: var(--spacing-m) 0 var(--spacing-m) 0;
+ }
+ `,
+ ];
+
+ override render() {
+ return html`
+ <gr-dialog
+ confirm-label="Cherry Pick"
+ .cancelLabel=${this.computeCancelLabel()}
+ ?disabled=${this.computeDisableCherryPick(
+ this.cherryPickType,
+ this.duplicateProjectChanges,
+ this.statuses,
+ this.branch
+ )}
+ @confirm=${this.handleConfirmTap}
+ @cancel=${this.handleCancelTap}
+ >
+ <div class="header title" slot="header">
+ Cherry Pick Change to Another Branch
+ </div>
+ <div class="main" slot="main">
+ ${when(this.showCherryPickTopic, () =>
+ this.renderCherrypickTopicLayout()
+ )}
+ <label for="branchInput"> Cherry Pick to branch </label>
+ <gr-autocomplete
+ id="branchInput"
+ .text=${this.branch}
+ .query=${this.query}
+ placeholder="Destination branch"
+ @commit=${(e: AutocompleteCommitEvent) =>
+ (this.branch = e.detail.value as BranchName)}
+ >
+ </gr-autocomplete>
+ ${when(
+ this.invalidBranch,
+ () => html`
+ <span class="error"
+ >Branch name cannot contain space or commas.</span
+ >
+ `
+ )}
+ ${choose(this.cherryPickType, [
+ [
+ CherryPickType.SINGLE_CHANGE,
+ () => this.renderCherrypickSingleChangeInputs(),
+ ],
+ [CherryPickType.TOPIC, () => this.renderCherrypickTopicTable()],
+ ])}
+ </div>
+ </gr-dialog>
+ `;
+ }
+
+ private renderCherrypickTopicLayout() {
+ return html`
+ <div class="cherryPickTopicLayout">
+ <input
+ name="cherryPickOptions"
+ type="radio"
+ id="cherryPickSingleChange"
+ @change=${this.handlecherryPickSingleChangeClicked}
+ checked
+ />
+ <label for="cherryPickSingleChange" class="cherryPickSingleChange">
+ Cherry Pick single change
+ </label>
+ </div>
+ <div class="cherryPickTopicLayout">
+ <input
+ name="cherryPickOptions"
+ type="radio"
+ id="cherryPickTopic"
+ @change=${this.handlecherryPickTopicClicked}
+ />
+ <label for="cherryPickTopic" class="cherryPickTopic">
+ Cherry Pick entire topic (${this.changesCount} Changes)
+ </label>
+ </div>
+ `;
+ }
+
+ private renderCherrypickSingleChangeInputs() {
+ return html`
+ <label for="baseInput"> Provide base commit sha1 for cherry-pick </label>
+ <iron-input
+ .bindValue=${this.baseCommit}
+ @bind-value-changed=${(e: BindValueChangeEvent) =>
+ (this.baseCommit = e.detail.value)}
+ >
+ <input
+ is="iron-input"
+ id="baseCommitInput"
+ maxlength="40"
+ placeholder="(optional)"
+ />
+ </iron-input>
+ <label for="messageInput"> Cherry Pick Commit Message </label>
+ <iron-autogrow-textarea
+ id="messageInput"
+ class="message"
+ autocomplete="on"
+ rows="4"
+ .maxRows=${15}
+ .bindValue=${this.message}
+ @bind-value-changed=${(e: BindValueChangeEvent) =>
+ (this.message = e.detail.value)}
+ ></iron-autogrow-textarea>
+ `;
+ }
+
+ private renderCherrypickTopicTable() {
+ return html`
+ <span class="error-message">${this.computeTopicErrorMessage()}</span>
+ <span class="cherry-pick-topic-message">
+ Commit Message will be auto generated
+ </span>
+ <table>
+ <thead>
+ <tr>
+ <th></th>
+ <th>Change</th>
+ <th>Status</th>
+ <th>Subject</th>
+ <th>Project</th>
+ <th>Progress</th>
+ <!-- Error Message -->
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ ${this.changes.map(
+ item => html`
+ <tr>
+ <td>
+ <input
+ type="checkbox"
+ data-item=${item.id as string}
+ @change=${this.toggleChangeSelected}
+ ?checked=${this.isChangeSelected(item.id)}
+ />
+ </td>
+ <td><span> ${this.getChangeId(item)} </span></td>
+ <td><span> ${item.status} </span></td>
+ <td>
+ <span> ${this.getTrimmedChangeSubject(item.subject)} </span>
+ </td>
+ <td><span> ${item.project} </span></td>
+ <td>
+ <span class=${this.computeStatusClass(item, this.statuses)}>
+ ${this.computeStatus(item, this.statuses)}
+ </span>
+ </td>
+ <td>
+ <span class="error">
+ ${this.computeError(item, this.statuses)}
+ </span>
+ </td>
+ </tr>
+ `
+ )}
+ </tbody>
+ </table>
+ `;
}
containsDuplicateProject(changes: ChangeInfo[]) {
@@ -156,28 +403,27 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
updateChanges(changes: ChangeInfo[]) {
this.changes = changes;
- this._statuses = {};
+ this.statuses = {};
changes.forEach(change => {
this.selectedChangeIds.add(change.id);
});
- this._duplicateProjectChanges = this.containsDuplicateProject(changes);
- this._changesCount = changes.length;
- this._showCherryPickTopic = changes.length > 1;
+ this.duplicateProjectChanges = this.containsDuplicateProject(changes);
+ this.changesCount = changes.length;
+ this.showCherryPickTopic = changes.length > 1;
}
- @observe('branch')
- _updateBranch(branch: string) {
+ private updateBranch() {
const invalidChars = [',', ' '];
- this._invalidBranch = !!(
- branch && invalidChars.some(c => branch.includes(c))
+ this.invalidBranch = !!(
+ this.branch && invalidChars.some(c => this.branch.includes(c))
);
}
- _isChangeSelected(changeId: ChangeInfoId) {
+ private isChangeSelected(changeId: ChangeInfoId) {
return this.selectedChangeIds.has(changeId);
}
- _toggleChangeSelected(e: Event) {
+ private toggleChangeSelected(e: Event) {
const changeId = ((dom(e) as EventApi).localTarget as HTMLElement).dataset[
'item'
]! as ChangeInfoId;
@@ -187,32 +433,32 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
const changes = this.changes.filter(change =>
this.selectedChangeIds.has(change.id)
);
- this._duplicateProjectChanges = this.containsDuplicateProject(changes);
+ this.duplicateProjectChanges = this.containsDuplicateProject(changes);
}
- _computeTopicErrorMessage(duplicateProjectChanges: boolean) {
- if (duplicateProjectChanges) {
+ private computeTopicErrorMessage() {
+ if (this.duplicateProjectChanges) {
return 'Two changes cannot be of the same project';
}
return '';
}
updateStatus(change: ChangeInfo, status: Status) {
- this._statuses = {...this._statuses, [change.id]: status};
+ this.statuses = {...this.statuses, [change.id]: status};
}
- _computeStatus(change: ChangeInfo, statuses: Statuses) {
+ private computeStatus(change: ChangeInfo, statuses: Statuses) {
if (!change || !statuses || !statuses[change.id])
return ProgressStatus.NOT_STARTED;
return statuses[change.id].status;
}
- _computeStatusClass(change: ChangeInfo, statuses: Statuses) {
+ computeStatusClass(change: ChangeInfo, statuses: Statuses) {
if (!change || !statuses || !statuses[change.id]) return '';
return statuses[change.id].status === ProgressStatus.FAILED ? 'error' : '';
}
- _computeError(change: ChangeInfo, statuses: Statuses) {
+ private computeError(change: ChangeInfo, statuses: Statuses) {
if (!change || !statuses || !statuses[change.id]) return '';
if (statuses[change.id].status === ProgressStatus.FAILED) {
return statuses[change.id].msg;
@@ -220,24 +466,24 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
return '';
}
- _getChangeId(change: ChangeInfo) {
+ private getChangeId(change: ChangeInfo) {
return change.change_id.substring(0, 10);
}
- _getTrimmedChangeSubject(subject: string) {
+ private getTrimmedChangeSubject(subject: string) {
if (!subject) return '';
if (subject.length < CHANGE_SUBJECT_LIMIT) return subject;
return subject.substring(0, CHANGE_SUBJECT_LIMIT) + '...';
}
- _computeCancelLabel(statuses: Statuses) {
- const isRunningChange = Object.values(statuses).some(
+ private computeCancelLabel() {
+ const isRunningChange = Object.values(this.statuses).some(
v => v.status === ProgressStatus.RUNNING
);
return isRunningChange ? 'Close' : 'Cancel';
}
- _computeDisableCherryPick(
+ private computeDisableCherryPick(
cherryPickType: CherryPickType,
duplicateProjectChanges: boolean,
statuses: Statuses,
@@ -254,64 +500,54 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
return isRunningChange;
}
- _computeIfSinglecherryPick(cherryPickType: CherryPickType) {
- return cherryPickType === CherryPickType.SINGLE_CHANGE;
- }
-
- _computeIfCherryPickTopic(cherryPickType: CherryPickType) {
- return cherryPickType === CherryPickType.TOPIC;
- }
-
- _handlecherryPickSingleChangeClicked() {
- this._cherryPickType = CherryPickType.SINGLE_CHANGE;
+ private handlecherryPickSingleChangeClicked() {
+ this.cherryPickType = CherryPickType.SINGLE_CHANGE;
fireEvent(this, 'iron-resize');
}
- _handlecherryPickTopicClicked() {
- this._cherryPickType = CherryPickType.TOPIC;
+ private handlecherryPickTopicClicked() {
+ this.cherryPickType = CherryPickType.TOPIC;
fireEvent(this, 'iron-resize');
}
- @observe('changeStatus', 'commitNum', 'commitMessage')
- _computeMessage(
- changeStatus?: string,
- commitNum?: number,
- commitMessage?: string
- ) {
+ private computeMessage() {
// Polymer 2: check for undefined
if (
- changeStatus === undefined ||
- commitNum === undefined ||
- commitMessage === undefined
+ this.changeStatus === undefined ||
+ this.commitNum === undefined ||
+ this.commitMessage === undefined
) {
return;
}
- let newMessage = commitMessage;
+ let newMessage = this.commitMessage;
- if (changeStatus === 'MERGED') {
+ if (this.changeStatus === 'MERGED') {
if (!newMessage.endsWith('\n')) {
newMessage += '\n';
}
- newMessage += '(cherry picked from commit ' + commitNum.toString() + ')';
+ newMessage += '(cherry picked from commit ' + this.commitNum + ')';
}
this.message = newMessage;
}
- _generateRandomCherryPickTopic(change: ChangeInfo) {
+ private generateRandomCherryPickTopic(change: ChangeInfo) {
const randomString = Math.random().toString(36).substr(2, 10);
const message = `cherrypick-${change.topic}-${randomString}`;
return message;
}
- _handleCherryPickFailed(change: ChangeInfo, response?: Response | null) {
+ private handleCherryPickFailed(
+ change: ChangeInfo,
+ response?: Response | null
+ ) {
if (!response) return;
response.text().then((errText: string) => {
this.updateStatus(change, {status: ProgressStatus.FAILED, msg: errText});
});
}
- _handleCherryPickTopic() {
+ private handleCherryPickTopic() {
const changes = this.changes.filter(change =>
this.selectedChangeIds.has(change.id)
);
@@ -320,7 +556,7 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
errorSpan!.innerHTML = 'No change selected';
return;
}
- const topic = this._generateRandomCherryPickTopic(changes[0]);
+ const topic = this.generateRandomCherryPickTopic(changes[0]);
changes.forEach(change => {
this.updateStatus(change, {status: ProgressStatus.RUNNING});
const payload = {
@@ -331,7 +567,7 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
allow_empty: true,
};
const handleError = (response?: Response | null) => {
- this._handleCherryPickFailed(change, response);
+ this.handleCherryPickFailed(change, response);
};
// revisions and current_revision must exist hence casting
const patchNum = change.revisions![change.current_revision!]._number;
@@ -346,7 +582,7 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
)
.then(() => {
this.updateStatus(change, {status: ProgressStatus.SUCCESSFUL});
- const failedOrPending = Object.values(this._statuses).find(
+ const failedOrPending = Object.values(this.statuses).find(
v => v.status !== ProgressStatus.SUCCESSFUL
);
if (!failedOrPending) {
@@ -358,12 +594,12 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
});
}
- _handleConfirmTap(e: Event) {
+ private handleConfirmTap(e: Event) {
e.preventDefault();
e.stopPropagation();
- if (this._cherryPickType === CherryPickType.TOPIC) {
+ if (this.cherryPickType === CherryPickType.TOPIC) {
this.reporting.reportInteraction('cherry-pick-topic-clicked', {});
- this._handleCherryPickTopic();
+ this.handleCherryPickTopic();
return;
}
// Cherry pick single change
@@ -375,7 +611,7 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
);
}
- _handleCancelTap(e: Event) {
+ private handleCancelTap(e: Event) {
e.preventDefault();
e.stopPropagation();
this.dispatchEvent(
@@ -387,10 +623,12 @@ export class GrConfirmCherrypickDialog extends PolymerElement {
}
resetFocus() {
- this.$.branchInput.focus();
+ this.branchInput.focus();
}
- _getProjectBranchesSuggestions(input: string) {
+ async getProjectBranchesSuggestions(
+ input: string
+ ): Promise<AutocompleteSuggestion[]> {
if (!this.project) return Promise.reject(new Error('Missing project'));
if (input.startsWith('refs/heads/')) {
input = input.substring('refs/heads/'.length);
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts
deleted file mode 100644
index d42f7e51f4..0000000000
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="shared-styles">
- :host {
- display: block;
- }
- :host([disabled]) {
- opacity: 0.5;
- pointer-events: none;
- }
- label {
- cursor: pointer;
- }
- .main {
- display: flex;
- flex-direction: column;
- width: 100%;
- }
- .main label,
- .main input[type='text'] {
- display: block;
- width: 100%;
- }
- iron-autogrow-textarea {
- font-family: var(--monospace-font-family);
- font-size: var(--font-size-mono);
- line-height: var(--line-height-mono);
- width: 73ch; /* Add a char to account for the border. */
- }
- .cherryPickTopicLayout {
- display: flex;
- align-items: center;
- margin-bottom: var(--spacing-m);
- }
- .cherryPickSingleChange,
- .cherryPickTopic {
- margin-left: var(--spacing-m);
- }
- .cherry-pick-topic-message {
- margin-bottom: var(--spacing-m);
- }
- label[for='messageInput'],
- label[for='baseInput'] {
- margin-top: var(--spacing-m);
- }
- .title {
- font-weight: var(--font-weight-bold);
- }
- tr > td {
- padding: var(--spacing-m);
- }
- th {
- color: var(--deemphasized-text-color);
- }
- table {
- border-collapse: collapse;
- }
- tr {
- border-bottom: 1px solid var(--border-color);
- }
- .error {
- color: var(--error-text-color);
- }
- .error-message {
- color: var(--error-text-color);
- margin: var(--spacing-m) 0 var(--spacing-m) 0;
- }
- </style>
- <gr-dialog
- confirm-label="Cherry Pick"
- cancel-label="[[_computeCancelLabel(_statuses)]]"
- disabled$="[[_computeDisableCherryPick(_cherryPickType, _duplicateProjectChanges, _statuses, branch)]]"
- on-confirm="_handleConfirmTap"
- on-cancel="_handleCancelTap"
- >
- <div class="header title" slot="header">
- Cherry Pick Change to Another Branch
- </div>
- <div class="main" slot="main">
- <template is="dom-if" if="[[_showCherryPickTopic]]">
- <div class="cherryPickTopicLayout">
- <input
- name="cherryPickOptions"
- type="radio"
- id="cherryPickSingleChange"
- on-change="_handlecherryPickSingleChangeClicked"
- checked=""
- />
- <label for="cherryPickSingleChange" class="cherryPickSingleChange">
- Cherry Pick single change
- </label>
- </div>
- <div class="cherryPickTopicLayout">
- <input
- name="cherryPickOptions"
- type="radio"
- id="cherryPickTopic"
- on-change="_handlecherryPickTopicClicked"
- />
- <label for="cherryPickTopic" class="cherryPickTopic">
- Cherry Pick entire topic ([[_changesCount]] Changes)
- </label>
- </div></template
- >
-
- <label for="branchInput"> Cherry Pick to branch </label>
- <gr-autocomplete
- id="branchInput"
- text="{{branch}}"
- query="[[_query]]"
- placeholder="Destination branch"
- >
- </gr-autocomplete>
- <template is="dom-if" if="[[_invalidBranch]]">
- <span class="error"> Branch name cannot contain space or commas. </span>
- </template>
- <template
- is="dom-if"
- if="[[_computeIfSinglecherryPick(_cherryPickType)]]"
- >
- <label for="baseInput">
- Provide base commit sha1 for cherry-pick
- </label>
- <iron-input
- maxlength="40"
- placeholder="(optional)"
- bind-value="{{baseCommit}}"
- >
- <input
- is="iron-input"
- id="baseCommitInput"
- maxlength="40"
- placeholder="(optional)"
- bind-value="{{baseCommit}}"
- />
- </iron-input>
- <label for="messageInput"> Cherry Pick Commit Message </label>
- </template>
- <template
- is="dom-if"
- if="[[_computeIfSinglecherryPick(_cherryPickType)]]"
- >
- <iron-autogrow-textarea
- id="messageInput"
- class="message"
- autocomplete="on"
- rows="4"
- max-rows="15"
- bind-value="{{message}}"
- ></iron-autogrow-textarea>
- </template>
- <template is="dom-if" if="[[_computeIfCherryPickTopic(_cherryPickType)]]">
- <span class="error-message"
- >[[_computeTopicErrorMessage(_duplicateProjectChanges)]]</span
- >
- <span class="cherry-pick-topic-message">
- Commit Message will be auto generated
- </span>
- <table>
- <thead>
- <tr>
- <th></th>
- <th>Change</th>
- <th>Status</th>
- <th>Subject</th>
- <th>Project</th>
- <th>Progress</th>
- <!-- Error Message -->
- <th></th>
- </tr>
- </thead>
- <tbody>
- <template is="dom-repeat" items="[[changes]]">
- <tr>
- <td>
- <input
- type="checkbox"
- data-item$="[[item.id]]"
- on-change="_toggleChangeSelected"
- checked="[[_isChangeSelected(item.id)]]"
- />
- </td>
- <td><span> [[_getChangeId(item)]] </span></td>
- <td><span> [[item.status]] </span></td>
- <td>
- <span> [[_getTrimmedChangeSubject(item.subject)]] </span>
- </td>
- <td><span> [[item.project]] </span></td>
- <td>
- <span class$="[[_computeStatusClass(item, _statuses)]]">
- [[_computeStatus(item, _statuses)]]
- </span>
- </td>
- <td>
- <span class="error">
- [[_computeError(item, _statuses)]]
- </span>
- </td>
- </tr>
- </template>
- </tbody>
- </table>
- </template>
- </div>
- </gr-dialog>
-`;
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
index 18a4feab3c..45e13b2628 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
@@ -36,8 +36,7 @@ import {createChange, createRevision} from '../../../test/test-data-generators';
import {GrDialog} from '../../shared/gr-dialog/gr-dialog.js';
import * as MockInteractions from '@polymer/iron-test-helpers/mock-interactions';
import {ProgressStatus} from '../../../constants/constants';
-
-const basicFixture = fixtureFromElement('gr-confirm-cherrypick-dialog');
+import {fixture, html} from '@open-wc/testing-helpers';
const CHERRY_PICK_TYPES = {
SINGLE_CHANGE: 1,
@@ -46,7 +45,7 @@ const CHERRY_PICK_TYPES = {
suite('gr-confirm-cherrypick-dialog tests', () => {
let element: GrConfirmCherrypickDialog;
- setup(() => {
+ setup(async () => {
stubRestApi('getRepoBranches').callsFake(input => {
if (input.startsWith('test')) {
return Promise.resolve([
@@ -60,53 +59,59 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
return Promise.resolve([]);
}
});
- element = basicFixture.instantiate();
+ element = await fixture(
+ html`<gr-confirm-cherrypick-dialog></gr-confirm-cherrypick-dialog>`
+ );
element.project = 'test-project' as RepoName;
});
- test('with message missing newline', () => {
+ test('with message missing newline', async () => {
element.changeStatus = ChangeStatus.MERGED;
element.commitMessage = 'message';
element.commitNum = '123' as CommitId;
element.branch = 'master' as BranchName;
- flush();
+ await element.updateComplete;
const expectedMessage = 'message\n(cherry picked from commit 123)';
assert.equal(element.message, expectedMessage);
});
- test('with merged change', () => {
+ test('with merged change', async () => {
element.changeStatus = ChangeStatus.MERGED;
element.commitMessage = 'message\n';
element.commitNum = '123' as CommitId;
element.branch = 'master' as BranchName;
- flush();
+ await element.updateComplete;
const expectedMessage = 'message\n(cherry picked from commit 123)';
assert.equal(element.message, expectedMessage);
});
- test('with unmerged change', () => {
+ test('with unmerged change', async () => {
element.changeStatus = ChangeStatus.NEW;
element.commitMessage = 'message\n';
element.commitNum = '123' as CommitId;
element.branch = 'master' as BranchName;
- flush();
+ await element.updateComplete;
+
const expectedMessage = 'message\n';
assert.equal(element.message, expectedMessage);
});
- test('with updated commit message', () => {
+ test('with updated commit message', async () => {
element.changeStatus = ChangeStatus.NEW;
element.commitMessage = 'message\n';
element.commitNum = '123' as CommitId;
element.branch = 'master' as BranchName;
+ await element.updateComplete;
+
const myNewMessage = 'updated commit message';
element.message = myNewMessage;
- flush();
+ await element.updateComplete;
+
assert.equal(element.message, myNewMessage);
});
- test('_getProjectBranchesSuggestions empty', async () => {
- const branches = await element._getProjectBranchesSuggestions('asdf');
+ test('getProjectBranchesSuggestions empty', async () => {
+ const branches = await element.getProjectBranchesSuggestions('asdf');
assert.isEmpty(branches);
});
@@ -141,20 +146,18 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
];
setup(async () => {
element.updateChanges(changes);
- element._cherryPickType = CHERRY_PICK_TYPES.TOPIC;
- await flush();
+ element.cherryPickType = CHERRY_PICK_TYPES.TOPIC;
+ await element.updateComplete;
});
test('cherry pick topic submit', async () => {
element.branch = 'master' as BranchName;
- await flush();
+ await element.updateComplete;
const executeChangeActionStub = stubRestApi(
'executeChangeAction'
).returns(Promise.resolve(new Response()));
- MockInteractions.tap(
- queryAndAssert<GrDialog>(element, 'gr-dialog').confirmButton!
- );
- await flush();
+ queryAndAssert<GrDialog>(element, 'gr-dialog').confirmButton!.click();
+ await element.updateComplete;
const args = executeChangeActionStub.args[0];
assert.equal(args[0], 1);
assert.equal(args[1], 'POST' as HttpMethod);
@@ -170,7 +173,7 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
'containsDuplicateProject'
);
element.branch = 'master' as BranchName;
- await flush();
+ await element.updateComplete;
const executeChangeActionStub = stubRestApi(
'executeChangeAction'
).returns(Promise.resolve(new Response()));
@@ -181,17 +184,15 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
assert.equal(checkboxes.length, 2);
assert.isTrue(checkboxes[0].checked);
MockInteractions.tap(checkboxes[0]);
- MockInteractions.tap(
- queryAndAssert<GrDialog>(element, 'gr-dialog').confirmButton!
- );
- await flush();
+ queryAndAssert<GrDialog>(element, 'gr-dialog').confirmButton!.click();
+ await element.updateComplete;
assert.equal(executeChangeActionStub.callCount, 1);
assert.isTrue(duplicateChangesStub.called);
});
test('deselecting all change shows error message', async () => {
element.branch = 'master' as BranchName;
- await flush();
+ await element.updateComplete;
const executeChangeActionStub = stubRestApi(
'executeChangeAction'
).returns(Promise.resolve(new Response()));
@@ -205,7 +206,7 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
MockInteractions.tap(
queryAndAssert<GrDialog>(element, 'gr-dialog').confirmButton!
);
- await flush();
+ await element.updateComplete;
assert.equal(executeChangeActionStub.callCount, 0);
assert.equal(
queryAndAssert<HTMLElement>(element, '.error-message').innerText,
@@ -213,16 +214,16 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
);
});
- test('_computeStatusClass', () => {
+ test('computeStatusClass', async () => {
assert.equal(
- element._computeStatusClass(
+ element.computeStatusClass(
{...createChange(), id: '1' as ChangeInfoId},
{1: {status: ProgressStatus.RUNNING}}
),
''
);
assert.equal(
- element._computeStatusClass(
+ element.computeStatusClass(
{...createChange(), id: '1' as ChangeInfoId},
{1: {status: ProgressStatus.FAILED}}
),
@@ -237,24 +238,24 @@ suite('gr-confirm-cherrypick-dialog tests', () => {
).confirmButton;
assert.isTrue(confirmButton!.hasAttribute('disabled'));
element.branch = 'b' as BranchName;
- await flush();
+ await element.updateComplete;
assert.isFalse(confirmButton!.hasAttribute('disabled'));
element.updateStatus(changes[0], {status: ProgressStatus.RUNNING});
- await flush();
+ await element.updateComplete;
assert.isTrue(confirmButton!.hasAttribute('disabled'));
});
});
- test('resetFocus', () => {
- const focusStub = sinon.stub(element.$.branchInput, 'focus');
+ test('resetFocus', async () => {
+ const focusStub = sinon.stub(element.branchInput, 'focus');
element.resetFocus();
+ await element.updateComplete;
+
assert.isTrue(focusStub.called);
});
- test('_getProjectBranchesSuggestions non-empty', async () => {
- const branches = await element._getProjectBranchesSuggestions(
- 'test-branch'
- );
+ test('getProjectBranchesSuggestions non-empty', async () => {
+ const branches = await element.getProjectBranchesSuggestions('test-branch');
assert.equal(branches.length, 1);
assert.equal(branches[0].name, 'test-branch');
});