Fix flakiness for gr-repo-access_test
Change-Id: Ia52c1e01b6249a854f4884ac681e09faa07b058b
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
index 80c58ca..411bb27 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.ts
@@ -91,7 +91,7 @@
_groups?: ProjectAccessGroups;
@property({type: Object})
- _inheritsFrom?: ProjectInfo | null | {};
+ _inheritsFrom?: ProjectInfo;
@property({type: Object})
_labels?: LabelNameToLabelTypeInfoMap;
@@ -114,7 +114,7 @@
@property({type: Boolean})
_loading = true;
- private originalInheritsFrom?: ProjectInfo | null;
+ private originalInheritsFrom?: ProjectInfo;
private readonly restApiService = appContext.restApiService;
@@ -159,16 +159,13 @@
// Keep a copy of the original inherit from values separate from
// the ones data bound to gr-autocomplete, so the original value
// can be restored if the user cancels.
- this._inheritsFrom = res.inherits_from
- ? {
- ...res.inherits_from,
- }
- : null;
- this.originalInheritsFrom = res.inherits_from
- ? {
- ...res.inherits_from,
- }
- : null;
+ if (res.inherits_from) {
+ this._inheritsFrom = {...res.inherits_from};
+ this.originalInheritsFrom = {...res.inherits_from};
+ } else {
+ this._inheritsFrom = undefined;
+ this.originalInheritsFrom = undefined;
+ }
// Initialize the filter value so when the user clicks edit, the
// current value appears. If there is no parent repo, it is
// initialized as an empty string.
@@ -218,19 +215,11 @@
}
_handleUpdateInheritFrom(e: CustomEvent<{value: string}>) {
- const parentProject: ProjectInfo = {
+ this._inheritsFrom = {
+ ...(this._inheritsFrom ?? {}),
id: e.detail.value as UrlEncodedRepoName,
name: this._inheritFromFilter,
};
- if (!this._inheritsFrom) {
- this._inheritsFrom = parentProject;
- } else {
- // TODO(TS): replace with
- // this._inheritsFrom = {...this._inheritsFrom, ...parentProject};
- const projectInfo = this._inheritsFrom as ProjectInfo;
- projectInfo.id = parentProject.id;
- projectInfo.name = parentProject.name;
- }
this._handleAccessModified();
}
@@ -268,8 +257,8 @@
return weblinks && weblinks.length ? 'show' : '';
}
- _computeShowInherit(inheritsFrom?: RepoName) {
- return inheritsFrom ? 'show' : '';
+ _computeShowInherit(inheritsFrom?: ProjectInfo) {
+ return inheritsFrom?.id?.length ? 'show' : '';
}
// TODO(TS): Unclear what is model here, provide a better explanation
@@ -297,18 +286,10 @@
}
// Restore inheritFrom.
if (this._inheritsFrom) {
- // Can't assign this._inheritsFrom = {...this.originalInheritsFrom}
- // directly, because this._inheritsFrom is declared as
- // '...|null|undefined` and typescript reports error when trying
- // to access .name property (because 'name' in null and 'name' in undefined
- // lead to runtime error)
- // After migrating to Typescript v4.2 the code below can be rewritten as
- // const copy = {...this.originalInheritsFrom};
- const copy: ProjectInfo | {} = this.originalInheritsFrom
+ this._inheritsFrom = this.originalInheritsFrom
? {...this.originalInheritsFrom}
- : {};
- this._inheritsFrom = copy;
- this._inheritFromFilter = 'name' in copy ? copy.name : undefined;
+ : undefined;
+ this._inheritFromFilter = this.originalInheritsFrom?.name;
}
if (!this._local) {
return;
@@ -448,12 +429,10 @@
const originalInheritsFromId = this.originalInheritsFrom
? singleDecodeURL(this.originalInheritsFrom.id)
- : null;
- // TODO(TS): this._inheritsFrom as ProjectInfo might be a mistake.
- // _inheritsFrom can be {}
+ : undefined;
const inheritsFromId = this._inheritsFrom
- ? singleDecodeURL((this._inheritsFrom as ProjectInfo).id)
- : null;
+ ? singleDecodeURL(this._inheritsFrom.id)
+ : undefined;
const inheritFromChanged =
// Inherit from changed
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
index a4e019e..2b7fdf5 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js
@@ -100,22 +100,24 @@
name: 'Create Account',
},
};
- setup(() => {
+ setup(async () => {
element = basicFixture.instantiate();
stubRestApi('getAccount').returns(Promise.resolve(null));
repoStub = stubRestApi('getRepo').returns(Promise.resolve(repoRes));
element._loading = false;
element._ownerOf = [];
element._canUpload = false;
+ await flush();
});
- test('_repoChanged called when repo name changes', () => {
+ test('_repoChanged called when repo name changes', async () => {
sinon.stub(element, '_repoChanged');
element.repo = 'New Repo';
+ await flush();
assert.isTrue(element._repoChanged.called);
});
- test('_repoChanged', done => {
+ test('_repoChanged', async () => {
const accessStub = stubRestApi(
'getRepoAccessRights');
@@ -127,31 +129,28 @@
'getCapabilities');
capabilitiesStub.returns(Promise.resolve(capabilitiesRes));
- element._repoChanged('New Repo').then(() => {
- assert.isTrue(accessStub.called);
- assert.isTrue(capabilitiesStub.called);
- assert.isTrue(repoStub.called);
- assert.isNotOk(element._inheritsFrom);
- assert.deepEqual(element._local, accessRes.local);
- assert.deepEqual(element._sections,
- toSortedPermissionsArray(accessRes.local));
- assert.deepEqual(element._labels, repoRes.labels);
- assert.equal(getComputedStyle(element.shadowRoot
- .querySelector('.weblinks')).display,
- 'block');
- return element._repoChanged('Another New Repo');
- })
- .then(() => {
- assert.deepEqual(element._sections,
- toSortedPermissionsArray(accessRes2.local));
- assert.equal(getComputedStyle(element.shadowRoot
- .querySelector('.weblinks')).display,
- 'none');
- done();
- });
+ await element._repoChanged('New Repo');
+ assert.isTrue(accessStub.called);
+ assert.isTrue(capabilitiesStub.called);
+ assert.isTrue(repoStub.called);
+ assert.isNotOk(element._inheritsFrom);
+ assert.deepEqual(element._local, accessRes.local);
+ assert.deepEqual(element._sections,
+ toSortedPermissionsArray(accessRes.local));
+ assert.deepEqual(element._labels, repoRes.labels);
+ assert.equal(getComputedStyle(element.shadowRoot
+ .querySelector('.weblinks')).display,
+ 'block');
+
+ await element._repoChanged('Another New Repo');
+ assert.deepEqual(element._sections,
+ toSortedPermissionsArray(accessRes2.local));
+ assert.equal(getComputedStyle(element.shadowRoot
+ .querySelector('.weblinks')).display,
+ 'none');
});
- test('_repoChanged when repo changes to undefined returns', done => {
+ test('_repoChanged when repo changes to undefined returns', async () => {
const capabilitiesRes = {
accessDatabase: {
id: 'accessDatabase',
@@ -163,12 +162,10 @@
const capabilitiesStub = stubRestApi(
'getCapabilities').returns(Promise.resolve(capabilitiesRes));
- element._repoChanged().then(() => {
- assert.isFalse(accessStub.called);
- assert.isFalse(capabilitiesStub.called);
- assert.isFalse(repoStub.called);
- done();
- });
+ await element._repoChanged();
+ assert.isFalse(accessStub.called);
+ assert.isFalse(capabilitiesStub.called);
+ assert.isFalse(repoStub.called);
});
test('_computeParentHref', () => {
@@ -190,24 +187,29 @@
'editing');
});
- test('inherit section', () => {
+ test('inherit section', async () => {
element._local = {};
element._ownerOf = [];
sinon.stub(element, '_computeParentHref');
+ await flush();
+
// Nothing should appear when no inherit from and not in edit mode.
assert.equal(getComputedStyle(element.$.inheritsFrom).display, 'none');
// The autocomplete should be hidden, and the link should be displayed.
assert.isFalse(element._computeParentHref.called);
- // When it edit mode, the autocomplete should appear.
+ // When in edit mode, the autocomplete should appear.
element._editing = true;
// When editing, the autocomplete should still not be shown.
assert.equal(getComputedStyle(element.$.inheritsFrom).display, 'none');
+
element._editing = false;
element._inheritsFrom = {
+ id: '1234',
name: 'another-repo',
};
+ await flush();
+
// When there is a parent project, the link should be displayed.
- flush();
assert.notEqual(getComputedStyle(element.$.inheritsFrom).display, 'none');
assert.notEqual(getComputedStyle(element.$.inheritFromName).display,
'none');
@@ -222,9 +224,10 @@
'none');
});
- test('_handleUpdateInheritFrom', () => {
+ test('_handleUpdateInheritFrom', async () => {
element._inheritFromFilter = 'foo bar baz';
element._handleUpdateInheritFrom({detail: {value: 'abc+123'}});
+ await flush();
assert.isOk(element._inheritsFrom);
assert.equal(element._inheritsFrom.id, 'abc+123');
assert.equal(element._inheritsFrom.name, 'foo bar baz');
@@ -251,46 +254,61 @@
});
suite('with defined sections', () => {
- const testEditSaveCancelBtns = (shouldShowSave, shouldShowSaveReview) => {
+ const testEditSaveCancelBtns = async (
+ shouldShowSave,
+ shouldShowSaveReview
+ ) => {
// Edit button is visible and Save button is hidden.
assert.equal(getComputedStyle(element.$.saveReviewBtn).display, 'none');
assert.equal(getComputedStyle(element.$.saveBtn).display, 'none');
assert.notEqual(getComputedStyle(element.$.editBtn).display, 'none');
assert.equal(element.$.editBtn.innerText, 'EDIT');
- assert.equal(getComputedStyle(element.$.editInheritFromInput).display,
- 'none');
+ assert.equal(
+ getComputedStyle(element.$.editInheritFromInput).display,
+ 'none'
+ );
element._inheritsFrom = {
id: 'test-project',
};
- flush();
- assert.equal(getComputedStyle(element.shadowRoot
- .querySelector('#editInheritFromInput'))
- .display, 'none');
+ await flush();
+ assert.equal(
+ getComputedStyle(
+ element.shadowRoot.querySelector('#editInheritFromInput')
+ ).display,
+ 'none'
+ );
MockInteractions.tap(element.$.editBtn);
- flush();
+ await flush();
// Edit button changes to Cancel button, and Save button is visible but
// disabled.
assert.equal(element.$.editBtn.innerText, 'CANCEL');
if (shouldShowSaveReview) {
- assert.notEqual(getComputedStyle(element.$.saveReviewBtn).display,
- 'none');
+ assert.notEqual(
+ getComputedStyle(element.$.saveReviewBtn).display,
+ 'none'
+ );
assert.isTrue(element.$.saveReviewBtn.disabled);
}
if (shouldShowSave) {
assert.notEqual(getComputedStyle(element.$.saveBtn).display, 'none');
assert.isTrue(element.$.saveBtn.disabled);
}
- assert.notEqual(getComputedStyle(element.shadowRoot
- .querySelector('#editInheritFromInput'))
- .display, 'none');
+ assert.notEqual(
+ getComputedStyle(
+ element.shadowRoot.querySelector('#editInheritFromInput')
+ ).display,
+ 'none'
+ );
// Save button should be enabled after access is modified
element.dispatchEvent(
new CustomEvent('access-modified', {
- composed: true, bubbles: true,
- }));
+ composed: true,
+ bubbles: true,
+ })
+ );
if (shouldShowSaveReview) {
assert.isFalse(element.$.saveReviewBtn.disabled);
}
@@ -299,7 +317,7 @@
}
};
- setup(() => {
+ setup(async () => {
// Create deep copies of these objects so the originals are not modified
// by any tests.
element._local = JSON.parse(JSON.stringify(accessRes.local));
@@ -308,18 +326,19 @@
element._groups = JSON.parse(JSON.stringify(accessRes.groups));
element._capabilities = JSON.parse(JSON.stringify(capabilitiesRes));
element._labels = JSON.parse(JSON.stringify(repoRes.labels));
- flush();
+ await flush();
});
- test('removing an added section', () => {
+ test('removing an added section', async () => {
element.editing = true;
+ await flush();
assert.equal(element._sections.length, 1);
element.shadowRoot
.querySelector('gr-access-section').dispatchEvent(
new CustomEvent('added-section-removed', {
composed: true, bubbles: true,
}));
- flush();
+ await flush();
assert.equal(element._sections.length, 0);
});
@@ -328,36 +347,41 @@
assert.equal(getComputedStyle(element.$.editBtn).display, 'none');
});
- test('button visibility for non ref owner with upload privilege', () => {
- element._canUpload = true;
- testEditSaveCancelBtns(false, true);
- });
+ test('button visibility for non ref owner with upload privilege',
+ async () => {
+ element._canUpload = true;
+ await flush();
+ testEditSaveCancelBtns(false, true);
+ });
- test('button visibility for ref owner', () => {
+ test('button visibility for ref owner', async () => {
element._ownerOf = ['refs/for/*'];
+ await flush();
testEditSaveCancelBtns(true, false);
});
- test('button visibility for ref owner and upload', () => {
+ test('button visibility for ref owner and upload', async () => {
element._ownerOf = ['refs/for/*'];
element._canUpload = true;
+ await flush();
testEditSaveCancelBtns(true, false);
});
- test('_handleAccessModified called with event fired', () => {
+ test('_handleAccessModified called with event fired', async () => {
sinon.spy(element, '_handleAccessModified');
element.dispatchEvent(
new CustomEvent('access-modified', {
composed: true, bubbles: true,
}));
+ await flush();
assert.isTrue(element._handleAccessModified.called);
});
- test('_handleAccessModified called when parent changes', () => {
+ test('_handleAccessModified called when parent changes', async () => {
element._inheritsFrom = {
id: 'test-project',
};
- flush();
+ await flush();
element.shadowRoot.querySelector('#editInheritFromInput').dispatchEvent(
new CustomEvent('commit', {
detail: {},
@@ -369,10 +393,11 @@
detail: {},
composed: true, bubbles: true,
}));
+ await flush();
assert.isTrue(element._handleAccessModified.called);
});
- test('_handleSaveForReview', () => {
+ test('_handleSaveForReview', async () => {
const saveStub =
stubRestApi('setRepoAccessRightsForReview');
sinon.stub(element, '_computeAddAndRemove').returns({
@@ -380,6 +405,7 @@
remove: {},
});
element._handleSaveForReview();
+ await flush();
assert.isFalse(saveStub.called);
});
@@ -487,29 +513,32 @@
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
});
- test('_handleSaveForReview parent change', () => {
+ test('_handleSaveForReview parent change', async () => {
element._inheritsFrom = {
id: 'test-project',
};
element._originalInheritsFrom = {
id: 'test-project-original',
};
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), {
parent: 'test-project', add: {}, remove: {},
});
});
- test('_handleSaveForReview new parent with spaces', () => {
+ test('_handleSaveForReview new parent with spaces', async () => {
element._inheritsFrom = {id: 'spaces+in+project+name'};
element._originalInheritsFrom = {id: 'old-project'};
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), {
parent: 'spaces in project name', add: {}, remove: {},
});
});
- test('_handleSaveForReview rules', () => {
+ test('_handleSaveForReview rules', async () => {
// Delete a rule.
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
+ await flush();
let expectedInput = {
add: {},
remove: {
@@ -531,6 +560,7 @@
// Modify a rule.
element._local['refs/*'].permissions.owner.rules[123].modified = true;
+ await flush();
expectedInput = {
add: {
'refs/*': {
@@ -558,7 +588,7 @@
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
});
- test('_computeAddAndRemove permissions', () => {
+ test('_computeAddAndRemove permissions', async () => {
// Add a new rule to a permission.
let expectedInput = {
add: {
@@ -584,7 +614,7 @@
._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
- flush();
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Remove the added rule.
@@ -592,6 +622,7 @@
// Delete a permission.
element._local['refs/*'].permissions.owner.deleted = true;
+ await flush();
expectedInput = {
add: {},
remove: {
@@ -609,6 +640,7 @@
// Modify a permission.
element._local['refs/*'].permissions.owner.modified = true;
+ await flush();
expectedInput = {
add: {
'refs/*': {
@@ -634,7 +666,7 @@
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
});
- test('_computeAddAndRemove sections', () => {
+ test('_computeAddAndRemove sections', async () => {
// Add a new permission to a section
let expectedInput = {
add: {
@@ -652,7 +684,7 @@
};
element.shadowRoot
.querySelector('gr-access-section')._handleAddPermission();
- flush();
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Add a new rule to the new permission.
@@ -683,11 +715,13 @@
'gr-permission')[2];
newPermission._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Modify a section reference.
element._local['refs/*'].updatedId = 'refs/for/bar';
element._local['refs/*'].modified = true;
+ await flush();
expectedInput = {
add: {
'refs/for/bar': {
@@ -726,10 +760,12 @@
},
},
};
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Delete a section.
element._local['refs/*'].deleted = true;
+ await flush();
expectedInput = {
add: {},
remove: {
@@ -741,7 +777,7 @@
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
});
- test('_computeAddAndRemove new section', () => {
+ test('_computeAddAndRemove new section', async () => {
// Add a new permission to a section
let expectedInput = {
add: {
@@ -753,6 +789,7 @@
remove: {},
};
MockInteractions.tap(element.$.addReferenceBtn);
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
expectedInput = {
@@ -773,7 +810,7 @@
const newSection = dom(element.root)
.querySelectorAll('gr-access-section')[1];
newSection._handleAddPermission();
- flush();
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Add rule to the new permission.
@@ -803,12 +840,12 @@
newSection.shadowRoot
.querySelector('gr-permission')._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
-
- flush();
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Modify a the reference from the default value.
element._local['refs/for/*'].updatedId = 'refs/for/new';
+ await flush();
expectedInput = {
add: {
'refs/for/new': {
@@ -835,10 +872,11 @@
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
});
- test('_computeAddAndRemove combinations', () => {
+ test('_computeAddAndRemove combinations', async () => {
// Modify rule and delete permission that it is inside of.
element._local['refs/*'].permissions.owner.rules[123].modified = true;
element._local['refs/*'].permissions.owner.deleted = true;
+ await flush();
let expectedInput = {
add: {},
remove: {
@@ -853,10 +891,12 @@
// Delete rule and delete permission that it is inside of.
element._local['refs/*'].permissions.owner.rules[123].modified = false;
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Also modify a different rule inside of another permission.
element._local['refs/*'].permissions.read.modified = true;
+ await flush();
expectedInput = {
add: {
'refs/*': {
@@ -886,6 +926,7 @@
element._local['refs/*'].permissions.owner.modified = true;
element._local['refs/*'].permissions.read.exclusive = true;
element._local['refs/*'].permissions.read.modified = true;
+ await flush();
expectedInput = {
add: {
'refs/*': {
@@ -918,6 +959,7 @@
'gr-permission')[1];
readPermission._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
+ await flush();
expectedInput = {
add: {
@@ -948,6 +990,7 @@
// Change one of the refs
element._local['refs/*'].updatedId = 'refs/for/bar';
element._local['refs/*'].modified = true;
+ await flush();
expectedInput = {
add: {
@@ -983,6 +1026,7 @@
},
};
element._local['refs/*'].deleted = true;
+ await flush();
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
// Add a new section.
@@ -990,12 +1034,13 @@
let newSection = dom(element.root)
.querySelectorAll('gr-access-section')[1];
newSection._handleAddPermission();
- flush();
+ await flush();
newSection.shadowRoot
.querySelector('gr-permission')._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
// Modify a the reference from the default value.
element._local['refs/for/*'].updatedId = 'refs/for/new';
+ await flush();
expectedInput = {
add: {
@@ -1029,6 +1074,7 @@
// Modify newly added rule inside new ref.
element._local['refs/for/*'].permissions['label-Code-Review'].
rules['Maintainers'].modified = true;
+ await flush();
expectedInput = {
add: {
'refs/for/new': {
@@ -1061,15 +1107,17 @@
// Add a second new section.
MockInteractions.tap(element.$.addReferenceBtn);
+ await flush();
newSection = dom(element.root)
.querySelectorAll('gr-access-section')[2];
newSection._handleAddPermission();
- flush();
+ await flush();
newSection.shadowRoot
.querySelector('gr-permission')._handleAddRuleItem(
{detail: {value: 'Maintainers'}});
// Modify a the reference from the default value.
element._local['refs/for/**'].updatedId = 'refs/for/new2';
+ await flush();
expectedInput = {
add: {
'refs/for/new': {
@@ -1119,20 +1167,23 @@
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
});
- test('Unsaved added refs are discarded when edit cancelled', () => {
+ test('Unsaved added refs are discarded when edit cancelled', async () => {
// Unsaved changes are discarded when editing is cancelled.
MockInteractions.tap(element.$.editBtn);
+ await flush();
assert.equal(element._sections.length, 1);
assert.equal(Object.keys(element._local).length, 1);
MockInteractions.tap(element.$.addReferenceBtn);
+ await flush();
assert.equal(element._sections.length, 2);
assert.equal(Object.keys(element._local).length, 2);
MockInteractions.tap(element.$.editBtn);
+ await flush();
assert.equal(element._sections.length, 1);
assert.equal(Object.keys(element._local).length, 1);
});
- test('_handleSave', done => {
+ test('_handleSave', async () => {
const repoAccessInput = {
add: {
'refs/*': {
@@ -1170,16 +1221,15 @@
element._modified = true;
MockInteractions.tap(element.$.saveBtn);
+ await flush();
assert.equal(element.$.saveBtn.hasAttribute('loading'), true);
resolver({_number: 1});
- flush(() => {
- assert.isTrue(saveStub.called);
- assert.isTrue(GerritNav.navigateToChange.notCalled);
- done();
- });
+ await flush();
+ assert.isTrue(saveStub.called);
+ assert.isTrue(GerritNav.navigateToChange.notCalled);
});
- test('_handleSaveForReview', done => {
+ test('_handleSaveForReview', async () => {
const repoAccessInput = {
add: {
'refs/*': {
@@ -1217,14 +1267,13 @@
element._modified = true;
MockInteractions.tap(element.$.saveReviewBtn);
+ await flush();
assert.equal(element.$.saveReviewBtn.hasAttribute('loading'), true);
resolver({_number: 1});
- flush(() => {
- assert.isTrue(saveForReviewStub.called);
- assert.isTrue(GerritNav.navigateToChange
- .lastCall.calledWithExactly({_number: 1}));
- done();
- });
+ await flush();
+ assert.isTrue(saveForReviewStub.called);
+ assert.isTrue(GerritNav.navigateToChange
+ .lastCall.calledWithExactly({_number: 1}));
});
});
});