Migrate gr-hovercard-account to LitElement
Google-Bug-Id: b/202457138
Change-Id: Iac3756d0df781b53014d7442f03e6dccb6765099
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
index 9897a9f..dabf761 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
@@ -199,9 +199,9 @@
${!this.hideHovercard
? html`<gr-hovercard-account
for="hovercardTarget"
- .account="${account}"
- .change="${change}"
- ?highlight-attention=${highlightAttention}
+ .account=${account}
+ .change=${change}
+ .highlightAttention=${highlightAttention}
.voteableText=${this.voteableText}
></gr-hovercard-account>`
: ''}
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
index 3988095..6a34fbb 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.ts
@@ -16,17 +16,11 @@
*/
import '@polymer/iron-icon/iron-icon';
-import '../../../styles/gr-font-styles';
-import '../../../styles/shared-styles';
-import '../../../styles/gr-hovercard-styles';
import '../gr-avatar/gr-avatar';
import '../gr-button/gr-button';
-import {HovercardBehaviorMixin} from '../gr-hovercard/gr-hovercard-behavior';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-hovercard-account_html';
import {appContext} from '../../../services/app-context';
import {accountKey, isSelf} from '../../../utils/account-util';
-import {customElement, property} from '@polymer/decorators';
+import {customElement, property} from 'lit/decorators';
import {
AccountInfo,
ChangeInfo,
@@ -46,16 +40,15 @@
import {CURRENT} from '../../../utils/patch-set-util';
import {isInvolved, isRemovableReviewer} from '../../../utils/change-util';
import {assertIsDefined} from '../../../utils/common-util';
+import {fontStyles} from '../../../styles/gr-font-styles';
+import {css, html, LitElement} from 'lit';
+import {HovercardMixin} from '../../../mixins/hovercard-mixin/hovercard-mixin';
// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = HovercardBehaviorMixin(PolymerElement);
+const base = HovercardMixin(LitElement);
@customElement('gr-hovercard-account')
export class GrHovercardAccount extends base {
- static get template() {
- return htmlTemplate;
- }
-
@property({type: Object})
account!: AccountInfo;
@@ -107,9 +100,214 @@
});
}
- _computeText(account?: AccountInfo, selfAccount?: AccountInfo) {
- if (!account || !selfAccount) return '';
- return isSelf(account, selfAccount) ? 'Your' : 'Their';
+ static override get styles() {
+ return [
+ fontStyles,
+ base.styles || [],
+ css`
+ .top,
+ .attention,
+ .status,
+ .voteable {
+ padding: var(--spacing-s) var(--spacing-l);
+ }
+ .top {
+ display: flex;
+ padding-top: var(--spacing-xl);
+ min-width: 300px;
+ }
+ gr-avatar {
+ height: 48px;
+ width: 48px;
+ margin-right: var(--spacing-l);
+ }
+ .title,
+ .email {
+ color: var(--deemphasized-text-color);
+ }
+ .action {
+ border-top: 1px solid var(--border-color);
+ padding: var(--spacing-s) var(--spacing-l);
+ --gr-button-padding: var(--spacing-s) var(--spacing-m);
+ }
+ .attention {
+ background-color: var(--emphasis-color);
+ }
+ .attention a {
+ text-decoration: none;
+ }
+ iron-icon {
+ vertical-align: top;
+ }
+ .status iron-icon {
+ width: 14px;
+ height: 14px;
+ position: relative;
+ top: 2px;
+ }
+ iron-icon.attentionIcon {
+ width: 14px;
+ height: 14px;
+ position: relative;
+ top: 3px;
+ }
+ .reason {
+ padding-top: var(--spacing-s);
+ }
+ `,
+ ];
+ }
+
+ override render() {
+ return html`
+ <div id="container" role="tooltip" tabindex="-1">
+ ${this.renderContent()}
+ </div>
+ `;
+ }
+
+ private renderContent() {
+ if (!this._isShowing) return;
+ return html`
+ <div class="top">
+ <div class="avatar">
+ <gr-avautar .account=${this.account} imageSize="56"></gr-avatar>
+ </div>
+ <div class="account">
+ <h3 class="name heading-3">${this.account.name}</h3>
+ <div class="email">${this.account.email}</div>
+ </div>
+ </div>
+ ${this.renderAccountStatus()}
+ ${
+ this.voteableText
+ ? html`
+ <div class="voteable">
+ <span class="title">Voteable:</span>
+ <span class="value">${this.voteableText}</span>
+ </div>
+ `
+ : ''
+ }
+ ${this.renderNeedsAttention()} ${this.renderAddToAttention()}
+ ${this.renderRemoveFromAttention()} ${this.renderReviewerOrCcActions()}
+ `;
+ }
+
+ private renderReviewerOrCcActions() {
+ if (!this._selfAccount || !isRemovableReviewer(this.change, this.account))
+ return;
+ return html`
+ <div class="action">
+ <gr-button
+ class="removeReviewerOrCC"
+ link=""
+ no-uppercase
+ @click="${this.handleRemoveReviewerOrCC}"
+ >
+ Remove ${this.computeReviewerOrCCText()}
+ </gr-button>
+ </div>
+ <div class="action">
+ <gr-button
+ class="changeReviewerOrCC"
+ link=""
+ no-uppercase
+ @click="${this.handleChangeReviewerOrCCStatus}"
+ >
+ ${this.computeChangeReviewerOrCCText()}
+ </gr-button>
+ </div>
+ `;
+ }
+
+ private renderAccountStatus() {
+ if (!this.account.status) return;
+ return html`
+ <div class="status">
+ <span class="title">
+ <iron-icon icon="gr-icons:calendar"></iron-icon>
+ Status:
+ </span>
+ <span class="value">${this.account.status}</span>
+ </div>
+ `;
+ }
+
+ private renderNeedsAttention() {
+ if (!(this.isAttentionEnabled && this.hasUserAttention)) return;
+ const lastUpdate = getLastUpdate(this.account, this.change);
+ return html`
+ <div class="attention">
+ <div>
+ <iron-icon
+ class="attentionIcon"
+ icon="gr-icons:attention"
+ ></iron-icon>
+ <span> ${this.computePronoun()} turn to take this action. </span>
+ <a
+ href="https://gerrit-review.googlesource.com/Documentation/user-attention-set.html"
+ target="_blank"
+ >
+ <iron-icon
+ icon="gr-icons:help-outline"
+ title="read documentation"
+ ></iron-icon>
+ </a>
+ </div>
+ <div class="reason">
+ <span class="title">Reason:</span>
+ <span class="value">
+ ${getReason(this._config, this.account, this.change)}
+ </span>
+ ${lastUpdate
+ ? html` (<gr-date-formatter
+ withTooltip
+ .dateStr="${lastUpdate}"
+ ></gr-date-formatter
+ >)`
+ : ''}
+ </div>
+ </div>
+ `;
+ }
+
+ private renderAddToAttention() {
+ if (!this.computeShowActionAddToAttentionSet()) return;
+ return html`
+ <div class="action">
+ <gr-button
+ class="addToAttentionSet"
+ link=""
+ no-uppercase
+ @click="${this.handleClickAddToAttentionSet}"
+ >
+ Add to attention set
+ </gr-button>
+ </div>
+ `;
+ }
+
+ private renderRemoveFromAttention() {
+ if (!this.computeShowActionRemoveFromAttentionSet()) return;
+ return html`
+ <div class="action">
+ <gr-button
+ class="removeFromAttentionSet"
+ link=""
+ no-uppercase
+ @click="${this.handleClickRemoveFromAttentionSet}"
+ >
+ Remove from attention set
+ </gr-button>
+ </div>
+ `;
+ }
+
+ // private but used by tests
+ computePronoun() {
+ if (!this.account || !this._selfAccount) return '';
+ return isSelf(this.account, this._selfAccount) ? 'Your' : 'Their';
}
get isAttentionEnabled() {
@@ -124,27 +322,11 @@
return hasAttention(this.account, this.change);
}
- _computeReason(change?: ChangeInfo) {
- return getReason(this._config, this.account, change);
- }
-
- _computeLastUpdate(change?: ChangeInfo) {
- return getLastUpdate(this.account, change);
- }
-
- /** 3rd parameter is just for *triggering* re-computation. */
- _showReviewerOrCCActions(
- account?: AccountInfo,
- change?: ChangeInfo,
- _?: unknown
- ) {
- return !!this._selfAccount && isRemovableReviewer(change, account);
- }
-
- _getReviewerState(account: AccountInfo, change: ChangeInfo) {
+ private getReviewerState() {
if (
- change.reviewers[ReviewerState.REVIEWER]?.some(
- (reviewer: AccountInfo) => reviewer._account_id === account._account_id
+ this.change!.reviewers[ReviewerState.REVIEWER]?.some(
+ (reviewer: AccountInfo) =>
+ reviewer._account_id === this.account._account_id
)
) {
return ReviewerState.REVIEWER;
@@ -152,21 +334,21 @@
return ReviewerState.CC;
}
- _computeReviewerOrCCText(account?: AccountInfo, change?: ChangeInfo) {
- if (!change || !account) return '';
- return this._getReviewerState(account, change) === ReviewerState.REVIEWER
+ private computeReviewerOrCCText() {
+ if (!this.change || !this.account) return '';
+ return this.getReviewerState() === ReviewerState.REVIEWER
? 'Reviewer'
: 'CC';
}
- _computeChangeReviewerOrCCText(account?: AccountInfo, change?: ChangeInfo) {
- if (!change || !account) return '';
- return this._getReviewerState(account, change) === ReviewerState.REVIEWER
+ private computeChangeReviewerOrCCText() {
+ if (!this.change || !this.account) return '';
+ return this.getReviewerState() === ReviewerState.REVIEWER
? 'Move Reviewer to CC'
: 'Move CC to Reviewer';
}
- _handleChangeReviewerOrCCStatus() {
+ private handleChangeReviewerOrCCStatus() {
assertIsDefined(this.change, 'change');
// accountKey() throws an error if _account_id & email is not found, which
// we want to check before showing reloading toast
@@ -179,7 +361,7 @@
{
reviewer: _accountKey,
state:
- this._getReviewerState(this.account, this.change) === ReviewerState.CC
+ this.getReviewerState() === ReviewerState.CC
? ReviewerState.REVIEWER
: ReviewerState.CC,
},
@@ -190,15 +372,14 @@
.then(response => {
if (!response || !response.ok) {
throw new Error(
- 'something went wrong when toggling' +
- this._getReviewerState(this.account, this.change!)
+ 'something went wrong when toggling' + this.getReviewerState()
);
}
this.dispatchEventThroughTarget('reload', {clearPatchset: true});
});
}
- _handleRemoveReviewerOrCC() {
+ private handleRemoveReviewerOrCC() {
if (!this.change || !(this.account?._account_id || this.account?.email))
throw new Error('Missing change or account.');
this.dispatchEventThroughTarget('show-alert', {
@@ -218,45 +399,21 @@
});
}
- /** Parameters are just for *triggering* re-computation. */
- _computeShowLabelNeedsAttention(
- _1: unknown,
- _2: unknown,
- _3: unknown,
- _4: unknown
- ) {
- return this.isAttentionEnabled && this.hasUserAttention;
- }
-
- /** Parameters are just for *triggering* re-computation. */
- _computeShowActionAddToAttentionSet(
- _1: unknown,
- _2: unknown,
- _3: unknown,
- _4: unknown,
- _5: unknown
- ) {
+ private computeShowActionAddToAttentionSet() {
const involvedOrSelf =
isInvolved(this.change, this._selfAccount) ||
isSelf(this.account, this._selfAccount);
return involvedOrSelf && this.isAttentionEnabled && !this.hasUserAttention;
}
- /** Parameters are just for *triggering* re-computation. */
- _computeShowActionRemoveFromAttentionSet(
- _1: unknown,
- _2: unknown,
- _3: unknown,
- _4: unknown,
- _5: unknown
- ) {
+ private computeShowActionRemoveFromAttentionSet() {
const involvedOrSelf =
isInvolved(this.change, this._selfAccount) ||
isSelf(this.account, this._selfAccount);
return involvedOrSelf && this.isAttentionEnabled && this.hasUserAttention;
}
- _handleClickAddToAttentionSet() {
+ private handleClickAddToAttentionSet(e: MouseEvent) {
if (!this.change || !this.account._account_id) return;
this.dispatchEventThroughTarget('show-alert', {
message: 'Saving attention set update ...',
@@ -277,17 +434,17 @@
this.reporting.reportInteraction(
'attention-hovercard-add',
- this._reportingDetails()
+ this.reportingDetails()
);
this.restApiService
.addToAttentionSet(this.change._number, this.account._account_id, reason)
.then(() => {
this.dispatchEventThroughTarget('hide-alert');
});
- this.hide();
+ this.hide(e);
}
- _handleClickRemoveFromAttentionSet() {
+ private handleClickRemoveFromAttentionSet(e: MouseEvent) {
if (!this.change || !this.account._account_id) return;
this.dispatchEventThroughTarget('show-alert', {
message: 'Saving attention set update ...',
@@ -304,7 +461,7 @@
this.reporting.reportInteraction(
'attention-hovercard-remove',
- this._reportingDetails()
+ this.reportingDetails()
);
this.restApiService
.removeFromAttentionSet(
@@ -315,10 +472,10 @@
.then(() => {
this.dispatchEventThroughTarget('hide-alert');
});
- this.hide();
+ this.hide(e);
}
- _reportingDetails() {
+ private reportingDetails() {
const targetId = this.account._account_id;
const ownerId =
(this.change && this.change.owner && this.change.owner._account_id) || -1;
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts
deleted file mode 100644
index cba7293..0000000
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.ts
+++ /dev/null
@@ -1,197 +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 '../../../styles/gr-hovercard-styles';
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="gr-font-styles">
- /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
- </style>
- <style include="shared-styles">
- /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
- </style>
- <style include="gr-hovercard-styles">
- .top,
- .attention,
- .status,
- .voteable {
- padding: var(--spacing-s) var(--spacing-l);
- }
- .top {
- display: flex;
- padding-top: var(--spacing-xl);
- min-width: 300px;
- }
- gr-avatar {
- height: 48px;
- width: 48px;
- margin-right: var(--spacing-l);
- }
- .title,
- .email {
- color: var(--deemphasized-text-color);
- }
- .action {
- border-top: 1px solid var(--border-color);
- padding: var(--spacing-s) var(--spacing-l);
- --gr-button-padding: var(--spacing-s) var(--spacing-m);
- }
- .attention {
- background-color: var(--emphasis-color);
- }
- .attention a {
- text-decoration: none;
- }
- iron-icon {
- vertical-align: top;
- }
- .status iron-icon {
- width: 14px;
- height: 14px;
- position: relative;
- top: 2px;
- }
- iron-icon.attentionIcon {
- width: 14px;
- height: 14px;
- position: relative;
- top: 3px;
- }
- .reason {
- padding-top: var(--spacing-s);
- }
- </style>
- <div id="container" role="tooltip" tabindex="-1">
- <template is="dom-if" if="[[_isShowing]]">
- <div class="top">
- <div class="avatar">
- <gr-avatar account="[[account]]" imageSize="56"></gr-avatar>
- </div>
- <div class="account">
- <h3 class="name heading-3">[[account.name]]</h3>
- <div class="email">[[account.email]]</div>
- </div>
- </div>
- <template is="dom-if" if="[[account.status]]">
- <div class="status">
- <span class="title">
- <iron-icon icon="gr-icons:calendar"></iron-icon>
- Status:
- </span>
- <span class="value">[[account.status]]</span>
- </div>
- </template>
- <template is="dom-if" if="[[voteableText]]">
- <div class="voteable">
- <span class="title">Voteable:</span>
- <span class="value">[[voteableText]]</span>
- </div>
- </template>
- <template
- is="dom-if"
- if="[[_computeShowLabelNeedsAttention(_config, highlightAttention, account, change)]]"
- >
- <div class="attention">
- <div>
- <iron-icon
- class="attentionIcon"
- icon="gr-icons:attention"
- ></iron-icon>
- <span>
- [[_computeText(account, _selfAccount)]] turn to take action.
- </span>
- <a
- href="https://gerrit-review.googlesource.com/Documentation/user-attention-set.html"
- target="_blank"
- >
- <iron-icon
- icon="gr-icons:help-outline"
- title="read documentation"
- ></iron-icon>
- </a>
- </div>
- <div class="reason">
- <span class="title">Reason:</span>
- <span class="value">[[_computeReason(change)]]</span>
- <template is="dom-if" if="[[_computeLastUpdate(change)]]">
- (<gr-date-formatter
- withTooltip
- date-str="[[_computeLastUpdate(change)]]"
- ></gr-date-formatter
- >)
- </template>
- </div>
- </div>
- </template>
- <template
- is="dom-if"
- if="[[_computeShowActionAddToAttentionSet(_config, highlightAttention, account, change, _selfAccount)]]"
- >
- <div class="action">
- <gr-button
- class="addToAttentionSet"
- link=""
- no-uppercase=""
- on-click="_handleClickAddToAttentionSet"
- >
- Add to attention set
- </gr-button>
- </div>
- </template>
- <template
- is="dom-if"
- if="[[_computeShowActionRemoveFromAttentionSet(_config, highlightAttention, account, change, _selfAccount)]]"
- >
- <div class="action">
- <gr-button
- class="removeFromAttentionSet"
- link=""
- no-uppercase=""
- on-click="_handleClickRemoveFromAttentionSet"
- >
- Remove from attention set
- </gr-button>
- </div>
- </template>
- <template
- is="dom-if"
- if="[[_showReviewerOrCCActions(account, change, _selfAccount)]]"
- >
- <div class="action">
- <gr-button
- class="removeReviewerOrCC"
- link=""
- no-uppercase=""
- on-click="_handleRemoveReviewerOrCC"
- >
- Remove [[_computeReviewerOrCCText(account, change)]]
- </gr-button>
- </div>
- <div class="action">
- <gr-button
- class="changeReviewerOrCC"
- link=""
- no-uppercase=""
- on-click="_handleChangeReviewerOrCCStatus"
- >
- [[_computeChangeReviewerOrCCText(account, change)]]
- </gr-button>
- </div>
- </template>
- </template>
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
index 82f64d0..5530d7c 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.js
@@ -19,7 +19,7 @@
import './gr-hovercard-account.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
import {ReviewerState} from '../../../constants/constants.js';
-import {stubRestApi} from '../../../test/test-utils.js';
+import {mockPromise, stubRestApi} from '../../../test/test-utils.js';
const basicFixture = fixtureFromTemplate(html`
<gr-hovercard-account class="hovered"></gr-hovercard-account>
@@ -57,33 +57,21 @@
'Kermit The Frog');
});
- test('_computeLastUpdate', () => {
- const last_update = '2019-07-17 19:39:02.000000000';
- const change = {
- attention_set: {
- 31415926535: {
- last_update,
- },
- },
- };
- assert.equal(element._computeLastUpdate(change), last_update);
- });
-
- test('_computeText', () => {
- let account = {_account_id: '1'};
- const selfAccount = {_account_id: '1'};
- assert.equal(element._computeText(account, selfAccount), 'Your');
- account = {_account_id: '2'};
- assert.equal(element._computeText(account, selfAccount), 'Their');
+ test('computePronoun', () => {
+ element.account = {_account_id: '1'};
+ element._selfAccount = {_account_id: '1'};
+ assert.equal(element.computePronoun(), 'Your');
+ element.account = {_account_id: '2'};
+ assert.equal(element.computePronoun(), 'Their');
});
test('account status is not shown if the property is not set', () => {
assert.isNull(element.shadowRoot.querySelector('.status'));
});
- test('account status is displayed', () => {
+ test('account status is displayed', async () => {
element.account = {status: 'OOO', ...ACCOUNT};
- flush();
+ await element.updateComplete;
assert.equal(element.shadowRoot.querySelector('.status .value').innerText,
'OOO');
});
@@ -92,9 +80,9 @@
assert.isNull(element.shadowRoot.querySelector('.voteable'));
});
- test('voteable div is displayed', () => {
+ test('voteable div is displayed', async () => {
element.voteableText = 'CodeReview: +2';
- flush();
+ await element.updateComplete;
assert.equal(element.shadowRoot.querySelector('.voteable .value').innerText,
element.voteableText);
});
@@ -106,15 +94,15 @@
[ReviewerState.REVIEWER]: [ACCOUNT],
},
};
+ await element.updateComplete;
stubRestApi('removeChangeReviewer').returns(Promise.resolve({ok: true}));
const reloadListener = sinon.spy();
element._target.addEventListener('reload', reloadListener);
- await flush();
const button = element.shadowRoot.querySelector('.removeReviewerOrCC');
assert.isOk(button);
assert.equal(button.innerText, 'Remove Reviewer');
MockInteractions.tap(button);
- await flush();
+ await element.updateComplete;
assert.isTrue(reloadListener.called);
});
@@ -125,6 +113,7 @@
[ReviewerState.REVIEWER]: [ACCOUNT],
},
};
+ await element.updateComplete;
const saveReviewStub = stubRestApi(
'saveChangeReview').returns(
Promise.resolve({ok: true}));
@@ -132,14 +121,12 @@
const reloadListener = sinon.spy();
element._target.addEventListener('reload', reloadListener);
- await flush();
const button = element.shadowRoot.querySelector('.changeReviewerOrCC');
assert.isOk(button);
assert.equal(button.innerText, 'Move Reviewer to CC');
MockInteractions.tap(button);
- await flush();
-
+ await element.updateComplete;
assert.isTrue(saveReviewStub.called);
assert.isTrue(reloadListener.called);
});
@@ -151,20 +138,19 @@
[ReviewerState.REVIEWER]: [],
},
};
+ await element.updateComplete;
const saveReviewStub = stubRestApi(
'saveChangeReview').returns(Promise.resolve({ok: true}));
stubRestApi('removeChangeReviewer').returns(Promise.resolve({ok: true}));
const reloadListener = sinon.spy();
element._target.addEventListener('reload', reloadListener);
- await flush();
const button = element.shadowRoot.querySelector('.changeReviewerOrCC');
assert.isOk(button);
assert.equal(button.innerText, 'Move CC to Reviewer');
MockInteractions.tap(button);
- await flush();
-
+ await element.updateComplete;
assert.isTrue(saveReviewStub.called);
assert.isTrue(reloadListener.called);
});
@@ -176,31 +162,26 @@
[ReviewerState.REVIEWER]: [],
},
};
+ await element.updateComplete;
stubRestApi('removeChangeReviewer').returns(Promise.resolve({ok: true}));
const reloadListener = sinon.spy();
element._target.addEventListener('reload', reloadListener);
- await flush();
const button = element.shadowRoot.querySelector('.removeReviewerOrCC');
assert.equal(button.innerText, 'Remove CC');
assert.isOk(button);
MockInteractions.tap(button);
-
- await flush();
-
+ await element.updateComplete;
assert.isTrue(reloadListener.called);
});
test('add to attention set', async () => {
- let apiResolve;
- const apiPromise = new Promise(r => {
- apiResolve = r;
- });
+ const apiPromise = mockPromise();
const apiSpy = stubRestApi('addToAttentionSet').returns(apiPromise);
element.highlightAttention = true;
element._target = document.createElement('div');
- flush();
+ await element.updateComplete;
const showAlertListener = sinon.spy();
const hideAlertListener = sinon.spy();
const updatedListener = sinon.spy();
@@ -224,8 +205,8 @@
assert.isTrue(updatedListener.called, 'updatedListener was called');
assert.isFalse(element._isShowing, 'hovercard is hidden');
- apiResolve({});
- await flush();
+ apiPromise.resolve({});
+ await element.updateComplete;
assert.isTrue(apiSpy.calledOnce);
assert.equal(apiSpy.lastCall.args[2],
`Added by <GERRIT_ACCOUNT_${ACCOUNT._account_id}>`
@@ -234,10 +215,7 @@
});
test('remove from attention set', async () => {
- let apiResolve;
- const apiPromise = new Promise(r => {
- apiResolve = r;
- });
+ const apiPromise = mockPromise();
const apiSpy = stubRestApi('removeFromAttentionSet').returns(apiPromise);
element.highlightAttention = true;
element.change = {
@@ -246,7 +224,7 @@
owner: {...ACCOUNT},
};
element._target = document.createElement('div');
- flush();
+ await element.updateComplete;
const showAlertListener = sinon.spy();
const hideAlertListener = sinon.spy();
const updatedListener = sinon.spy();
@@ -264,8 +242,8 @@
assert.isTrue(updatedListener.called, 'updatedListener was called');
assert.isFalse(element._isShowing, 'hovercard is hidden');
- apiResolve({});
- await flush();
+ apiPromise.resolve({});
+ await element.updateComplete;
assert.isTrue(apiSpy.calledOnce);
assert.equal(apiSpy.lastCall.args[2],