commit 30f2b9cdf343535b230f9c046e2dfaac20fe262d Author: Dmitrii Filippov Date: Fri Oct 16 12:56:35 2020 +0200 Allow to remove reviewers that don't have _account_id The issue was introduced by the following change: https://gerrit-review.googlesource.com/c/gerrit/+/281146 Change-Id: Ib5a25c75630888c64c290356690d11d5202a30d3 diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts index d7a1f17..5ca7d88 100644 --- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts +++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.ts @@ -35,12 +35,14 @@ import { Reviewers, AccountId, DetailedLabelInfo, + EmailAddress, } from '../../../types/common'; import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces'; import {GrAccountChip} from '../../shared/gr-account-chip/gr-account-chip'; import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api'; import {hasOwnProperty} from '../../../utils/common-util'; import {isRemovableReviewer} from '../../../utils/change-util'; +import {ReviewerState} from '../../../constants/constants'; export interface GrReviewerList { $: { @@ -262,7 +264,7 @@ export class GrReviewerList extends GestureEventListeners( if (!target.account || !this.change) { return; } - const accountID = target.account._account_id; + const accountID = target.account._account_id || target.account.email; this.disabled = true; if (!accountID) return; this._xhrPromise = this._removeReviewer(accountID) @@ -272,12 +274,15 @@ export class GrReviewerList extends GestureEventListeners( return response; } if (!this.change || !this.change.reviewers) return; - const reviewers: {[type: string]: AccountInfo[] | undefined} = this - .change!.reviewers; - for (const type of ['REVIEWER', 'CC']) { - reviewers[type] = reviewers[type] || []; - for (let i = 0; i < reviewers[type]!.length; i++) { - if (reviewers[type]![i]._account_id === accountID) { + const reviewers = this.change.reviewers; + for (const type of [ReviewerState.REVIEWER, ReviewerState.CC]) { + const reviewerStateByType = reviewers[type] || []; + reviewers[type] = reviewerStateByType; + for (let i = 0; i < reviewerStateByType.length; i++) { + if ( + reviewerStateByType[i]._account_id === accountID || + reviewerStateByType[i].email === accountID + ) { this.splice('change.reviewers.' + type, i, 1); break; } @@ -316,7 +321,7 @@ export class GrReviewerList extends GestureEventListeners( this._displayedReviewers = this._reviewers; } - _removeReviewer(id: AccountId): Promise { + _removeReviewer(id: AccountId | EmailAddress): Promise { if (!this.change) return Promise.resolve(undefined); return this.$.restAPI.removeChangeReviewer(this.change._number, id); } diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js index ad9af30..d29abfc 100644 --- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js +++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.js @@ -116,6 +116,101 @@ suite('gr-reviewer-list tests', () => { } }); + suite('_handleRemove', () => { + let removeReviewerStub; + let reviewersChangedSpy; + + const reviewerWithId = { + _account_id: 2, + name: 'Some name', + }; + + const reviewerWithIdAndEmail = { + _account_id: 4, + name: 'Some other name', + email: 'example@', + }; + + const reviewerWithEmailOnly = { + email: 'example2@example', + }; + + let chips; + + setup(() => { + removeReviewerStub = sinon + .stub(element, '_removeReviewer') + .returns(Promise.resolve(new Response({status: 200}))); + element.mutable = true; + + const allReviewers = [ + reviewerWithId, + reviewerWithIdAndEmail, + reviewerWithEmailOnly, + ]; + + element.change = { + owner: { + _account_id: 1, + }, + reviewers: { + REVIEWER: allReviewers, + }, + removable_reviewers: allReviewers, + }; + flush(); + chips = Array.from(element.root.querySelectorAll('gr-account-chip')); + assert.equal(chips.length, allReviewers.length); + reviewersChangedSpy = sinon.spy(element, '_reviewersChanged'); + }); + + test('_handleRemove for account with accountId only', async () => { + const accountChip = chips.find(chip => + chip.account._account_id === reviewerWithId._account_id + ); + accountChip._handleRemoveTap(new MouseEvent('click')); + await flush(); + assert.isTrue(removeReviewerStub.calledOnce); + assert.isTrue(removeReviewerStub.calledWith(reviewerWithId._account_id)); + assert.isTrue(reviewersChangedSpy.called); + expect(element.change.reviewers.REVIEWER).to.have.deep.members([ + reviewerWithIdAndEmail, + reviewerWithEmailOnly, + ]); + }); + + test('_handleRemove for account with accountId and email', async () => { + const accountChip = chips.find(chip => + chip.account._account_id === reviewerWithIdAndEmail._account_id + ); + accountChip._handleRemoveTap(new MouseEvent('click')); + await flush(); + assert.isTrue(removeReviewerStub.calledOnce); + assert.isTrue( + removeReviewerStub.calledWith(reviewerWithIdAndEmail._account_id)); + assert.isTrue(reviewersChangedSpy.called); + expect(element.change.reviewers.REVIEWER).to.have.deep.members([ + reviewerWithId, + reviewerWithEmailOnly, + ]); + }); + + test('_handleRemove for account with email only', async () => { + const accountChip = chips.find( + chip => chip.account.email === reviewerWithEmailOnly.email + ); + accountChip._handleRemoveTap(new MouseEvent('click')); + await flush(); + assert.isTrue(removeReviewerStub.calledOnce); + assert.isTrue(removeReviewerStub.calledWith(reviewerWithEmailOnly.email)); + assert.isTrue(reviewersChangedSpy.called); + expect(element.change.reviewers.REVIEWER).to.have.deep.members([ + reviewerWithId, + reviewerWithIdAndEmail, + ]); + }); + }); + test('tracking reviewers and ccs', () => { let counter = 0; function makeAccount() {