Convert gr-repo-access_test.js to typescript Change-Id: I68af2ac63ad8368b8b4f4d0fcae49865122777e2
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 7e04281..cf5d952 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
@@ -115,7 +115,8 @@ @property({type: Boolean}) _loading = true; - private originalInheritsFrom?: ProjectInfo; + // private but used in the tests + originalInheritsFrom?: ProjectInfo; private readonly restApiService = getAppContext().restApiService; @@ -131,7 +132,7 @@ this._modified = true; } - _repoChanged(repo: RepoName) { + _repoChanged(repo?: RepoName) { this._loading = true; if (!repo) {
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.ts similarity index 65% rename from polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.js rename to polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.ts index 1ccfd5e..a5159ae 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.ts
@@ -15,23 +15,42 @@ * limitations under the License. */ -import '../../../test/common-test-setup-karma.js'; -import './gr-repo-access.js'; -import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js'; -import {GerritNav} from '../../core/gr-navigation/gr-navigation.js'; -import {toSortedPermissionsArray} from '../../../utils/access-util.js'; +import '../../../test/common-test-setup-karma'; +import './gr-repo-access'; +import {GrRepoAccess} from './gr-repo-access'; +import {GerritNav} from '../../core/gr-navigation/gr-navigation'; +import {toSortedPermissionsArray} from '../../../utils/access-util'; import { addListenerForTest, mockPromise, + queryAll, + queryAndAssert, stubRestApi, -} from '../../../test/test-utils.js'; +} from '../../../test/test-utils'; +import { + ChangeInfo, + GitRef, + RepoName, + UrlEncodedRepoName, +} from '../../../types/common'; +import {PermissionAction} from '../../../constants/constants'; +import {PageErrorEvent} from '../../../types/events'; +import {GrButton} from '../../shared/gr-button/gr-button'; +import { + AutocompleteCommitEvent, + GrAutocomplete, +} from '../../shared/gr-autocomplete/gr-autocomplete'; +import * as MockInteractions from '@polymer/iron-test-helpers/mock-interactions'; +import {GrAccessSection} from '../gr-access-section/gr-access-section'; +import {GrPermission} from '../gr-permission/gr-permission'; +import {createChange} from '../../../test/test-data-generators'; const basicFixture = fixtureFromElement('gr-repo-access'); suite('gr-repo-access tests', () => { - let element; + let element: GrRepoAccess; - let repoStub; + let repoStub: sinon.SinonStub; const accessRes = { local: { @@ -39,13 +58,13 @@ permissions: { owner: { rules: { - 234: {action: 'ALLOW'}, - 123: {action: 'DENY'}, + 234: {action: PermissionAction.ALLOW}, + 123: {action: PermissionAction.DENY}, }, }, read: { rules: { - 234: {action: 'ALLOW'}, + 234: {action: PermissionAction.ALLOW}, }, }, }, @@ -59,11 +78,13 @@ name: 'Maintainers', }, }, - config_web_links: [{ - name: 'gitiles', - target: '_blank', - url: 'https://my/site/+log/123/project.config', - }], + config_web_links: [ + { + name: 'gitiles', + target: '_blank', + url: 'https://my/site/+log/123/project.config', + }, + ], can_upload: true, }; const accessRes2 = { @@ -73,7 +94,7 @@ accessDatabase: { rules: { group1: { - action: 'ALLOW', + action: PermissionAction.ALLOW, }, }, }, @@ -82,15 +103,17 @@ }, }; const repoRes = { + id: '' as UrlEncodedRepoName, labels: { 'Code-Review': { values: { - ' 0': 'No score', + '0': 'No score', '-1': 'I would prefer this is not merged as is', '-2': 'This shall not be merged', '+1': 'Looks good to me, but someone else must approve', '+2': 'Looks good to me, approved', }, + default_value: 0, }, }, }; @@ -106,7 +129,7 @@ }; setup(async () => { element = basicFixture.instantiate(); - stubRestApi('getAccount').returns(Promise.resolve(null)); + stubRestApi('getAccount').returns(Promise.resolve(undefined)); repoStub = stubRestApi('getRepo').returns(Promise.resolve(repoRes)); element._loading = false; element._ownerOf = []; @@ -115,43 +138,51 @@ }); test('_repoChanged called when repo name changes', async () => { - sinon.stub(element, '_repoChanged'); - element.repo = 'New Repo'; + const repoChangedStub = sinon.stub(element, '_repoChanged'); + element.repo = 'New Repo' as RepoName; await flush(); - assert.isTrue(element._repoChanged.called); + assert.isTrue(repoChangedStub.called); }); test('_repoChanged', async () => { - const accessStub = stubRestApi( - 'getRepoAccessRights'); + const accessStub = stubRestApi('getRepoAccessRights'); - accessStub.withArgs('New Repo').returns( - Promise.resolve(JSON.parse(JSON.stringify(accessRes)))); - accessStub.withArgs('Another New Repo') - .returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2)))); - const capabilitiesStub = stubRestApi( - 'getCapabilities'); + accessStub + .withArgs('New Repo' as RepoName) + .returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes)))); + accessStub + .withArgs('Another New Repo' as RepoName) + .returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2)))); + const capabilitiesStub = stubRestApi('getCapabilities'); capabilitiesStub.returns(Promise.resolve(capabilitiesRes)); - await element._repoChanged('New Repo'); + await element._repoChanged('New Repo' as RepoName); 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._sections, + toSortedPermissionsArray(accessRes.local) + ); assert.deepEqual(element._labels, repoRes.labels); - assert.equal(getComputedStyle(element.shadowRoot - .querySelector('.weblinks')).display, - 'block'); + assert.equal( + getComputedStyle(queryAndAssert<HTMLDivElement>(element, '.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'); + await element._repoChanged('Another New Repo' as RepoName); + assert.deepEqual( + element._sections, + toSortedPermissionsArray(accessRes2.local) + ); + assert.equal( + getComputedStyle(queryAndAssert<HTMLDivElement>(element, '.weblinks')) + .display, + 'none' + ); }); test('_repoChanged when repo changes to undefined returns', async () => { @@ -161,10 +192,12 @@ name: 'Access Database', }, }; - const accessStub = stubRestApi('getRepoAccessRights') - .returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2)))); - const capabilitiesStub = stubRestApi( - 'getCapabilities').returns(Promise.resolve(capabilitiesRes)); + const accessStub = stubRestApi('getRepoAccessRights').returns( + Promise.resolve(JSON.parse(JSON.stringify(accessRes2))) + ); + const capabilitiesStub = stubRestApi('getCapabilities').returns( + Promise.resolve(capabilitiesRes) + ); await element._repoChanged(); assert.isFalse(accessStub.called); @@ -173,34 +206,39 @@ }); test('_computeParentHref', () => { - const repoName = 'test-repo'; - assert.equal(element._computeParentHref(repoName), - '/admin/repos/test-repo,access'); + assert.equal( + element._computeParentHref('test-repo' as RepoName), + '/admin/repos/test-repo,access' + ); }); test('_computeMainClass', () => { - let ownerOf = ['refs/*']; + let ownerOf = ['refs/*'] as GitRef[]; const editing = true; const canUpload = false; - assert.equal(element._computeMainClass(ownerOf, canUpload), 'admin'); - assert.equal(element._computeMainClass(ownerOf, canUpload, editing), - 'admin editing'); + assert.equal(element._computeMainClass(ownerOf, canUpload, false), 'admin'); + assert.equal( + element._computeMainClass(ownerOf, canUpload, editing), + 'admin editing' + ); ownerOf = []; - assert.equal(element._computeMainClass(ownerOf, canUpload), ''); - assert.equal(element._computeMainClass(ownerOf, canUpload, editing), - 'editing'); + assert.equal(element._computeMainClass(ownerOf, canUpload, false), ''); + assert.equal( + element._computeMainClass(ownerOf, canUpload, editing), + 'editing' + ); }); test('inherit section', async () => { element._local = {}; element._ownerOf = []; - sinon.stub(element, '_computeParentHref'); + const computeParentHrefStub = 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); + assert.isFalse(computeParentHrefStub.called); // When in edit mode, the autocomplete should appear. element._editing = true; // When editing, the autocomplete should still not be shown. @@ -208,33 +246,45 @@ element._editing = false; element._inheritsFrom = { - id: '1234', - name: 'another-repo', + id: '1234' as UrlEncodedRepoName, + name: 'another-repo' as RepoName, }; await flush(); // When there is a parent project, the link should be displayed. assert.notEqual(getComputedStyle(element.$.inheritsFrom).display, 'none'); - assert.notEqual(getComputedStyle(element.$.inheritFromName).display, - 'none'); - assert.equal(getComputedStyle(element.$.editInheritFromInput).display, - 'none'); - assert.isTrue(element._computeParentHref.called); + assert.notEqual( + getComputedStyle(element.$.inheritFromName).display, + 'none' + ); + assert.equal( + getComputedStyle( + queryAndAssert<GrAutocomplete>(element, '#editInheritFromInput') + ).display, + 'none' + ); + assert.isTrue(computeParentHrefStub.called); element._editing = true; // When editing, the autocomplete should be shown. assert.notEqual(getComputedStyle(element.$.inheritsFrom).display, 'none'); assert.equal(getComputedStyle(element.$.inheritFromName).display, 'none'); - assert.notEqual(getComputedStyle(element.$.editInheritFromInput).display, - 'none'); + assert.notEqual( + getComputedStyle( + queryAndAssert<GrAutocomplete>(element, '#editInheritFromInput') + ).display, + 'none' + ); }); test('_handleUpdateInheritFrom', async () => { - element._inheritFromFilter = 'foo bar baz'; - element._handleUpdateInheritFrom({detail: {value: 'abc+123'}}); + element._inheritFromFilter = 'foo bar baz' as RepoName; + element._handleUpdateInheritFrom({ + detail: {value: 'abc+123'}, + } as CustomEvent); await flush(); assert.isOk(element._inheritsFrom); - assert.equal(element._inheritsFrom.id, 'abc+123'); - assert.equal(element._inheritsFrom.name, 'foo bar baz'); + assert.equal(element._inheritsFrom!.id, 'abc+123'); + assert.equal(element._inheritsFrom!.name, 'foo bar baz' as RepoName); }); test('_computeLoadingClass', () => { @@ -243,84 +293,113 @@ }); test('fires page-error', async () => { - const response = {status: 404}; + const response = {status: 404} as Response; - stubRestApi('getRepoAccessRights').callsFake((repoName, errFn) => { - errFn(response); + stubRestApi('getRepoAccessRights').callsFake((_repoName, errFn) => { + if (errFn !== undefined) { + errFn(response); + } return Promise.resolve(undefined); }); const promise = mockPromise(); addListenerForTest(document, 'page-error', e => { - assert.deepEqual(e.detail.response, response); + assert.deepEqual((e as PageErrorEvent).detail.response, response); promise.resolve(); }); - element.repo = 'test'; + element.repo = 'test' as RepoName; await promise; }); suite('with defined sections', () => { const testEditSaveCancelBtns = async ( - shouldShowSave, - shouldShowSaveReview + shouldShowSave: boolean, + shouldShowSaveReview: boolean ) => { // 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' + getComputedStyle(queryAndAssert<GrButton>(element, '#saveReviewBtn')) + .display, + 'none' + ); + assert.equal( + getComputedStyle(queryAndAssert<GrButton>(element, '#saveBtn')).display, + 'none' + ); + assert.notEqual( + getComputedStyle(queryAndAssert<GrButton>(element, '#editBtn')).display, + 'none' + ); + assert.equal( + queryAndAssert<GrButton>(element, '#editBtn').innerText, + 'EDIT' + ); + assert.equal( + getComputedStyle( + queryAndAssert<GrAutocomplete>(element, '#editInheritFromInput') + ).display, + 'none' ); element._inheritsFrom = { - id: 'test-project', + id: 'test-project' as UrlEncodedRepoName, }; await flush(); assert.equal( - getComputedStyle( - element.shadowRoot.querySelector('#editInheritFromInput') - ).display, - 'none' + getComputedStyle( + queryAndAssert<GrAutocomplete>(element, '#editInheritFromInput') + ).display, + 'none' ); - MockInteractions.tap(element.$.editBtn); + MockInteractions.tap(queryAndAssert<GrButton>(element, '#editBtn')); await flush(); // Edit button changes to Cancel button, and Save button is visible but // disabled. - assert.equal(element.$.editBtn.innerText, 'CANCEL'); + assert.equal( + queryAndAssert<GrButton>(element, '#editBtn').innerText, + 'CANCEL' + ); if (shouldShowSaveReview) { assert.notEqual( - getComputedStyle(element.$.saveReviewBtn).display, - 'none' + getComputedStyle(queryAndAssert<GrButton>(element, '#saveReviewBtn')) + .display, + 'none' ); - assert.isTrue(element.$.saveReviewBtn.disabled); + assert.isTrue( + queryAndAssert<GrButton>(element, '#saveReviewBtn').disabled + ); } if (shouldShowSave) { - assert.notEqual(getComputedStyle(element.$.saveBtn).display, 'none'); - assert.isTrue(element.$.saveBtn.disabled); + assert.notEqual( + getComputedStyle(queryAndAssert<GrButton>(element, '#saveBtn')) + .display, + 'none' + ); + assert.isTrue(queryAndAssert<GrButton>(element, '#saveBtn').disabled); } assert.notEqual( - getComputedStyle( - element.shadowRoot.querySelector('#editInheritFromInput') - ).display, - 'none' + getComputedStyle( + queryAndAssert<GrAutocomplete>(element, '#editInheritFromInput') + ).display, + 'none' ); // Save button should be enabled after access is modified element.dispatchEvent( - new CustomEvent('access-modified', { - composed: true, - bubbles: true, - }) + new CustomEvent('access-modified', { + composed: true, + bubbles: true, + }) ); if (shouldShowSaveReview) { - assert.isFalse(element.$.saveReviewBtn.disabled); + assert.isFalse( + queryAndAssert<GrButton>(element, '#saveReviewBtn').disabled + ); } if (shouldShowSave) { - assert.isFalse(element.$.saveBtn.disabled); + assert.isFalse(queryAndAssert<GrButton>(element, '#saveBtn').disabled); } }; @@ -337,16 +416,20 @@ }); test('removing an added section', async () => { - element.editing = true; + 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, - })); + assert.equal(element._sections!.length, 1); + queryAndAssert<GrAccessSection>( + element, + 'gr-access-section' + ).dispatchEvent( + new CustomEvent('added-section-removed', { + composed: true, + bubbles: true, + }) + ); await flush(); - assert.equal(element._sections.length, 0); + assert.equal(element._sections!.length, 0); }); test('button visibility for non ref owner', () => { @@ -354,64 +437,77 @@ assert.equal(getComputedStyle(element.$.editBtn).display, 'none'); }); - test('button visibility for non ref owner with upload privilege', - async () => { - element._canUpload = true; - await flush(); - 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', async () => { - element._ownerOf = ['refs/for/*']; + element._ownerOf = ['refs/for/*'] as GitRef[]; await flush(); testEditSaveCancelBtns(true, false); }); test('button visibility for ref owner and upload', async () => { - element._ownerOf = ['refs/for/*']; + element._ownerOf = ['refs/for/*'] as GitRef[]; element._canUpload = true; await flush(); testEditSaveCancelBtns(true, false); }); test('_handleAccessModified called with event fired', async () => { - sinon.spy(element, '_handleAccessModified'); + const handleAccessModifiedSpy = sinon.spy( + element, + '_handleAccessModified' + ); element.dispatchEvent( - new CustomEvent('access-modified', { - composed: true, bubbles: true, - })); + new CustomEvent('access-modified', { + composed: true, + bubbles: true, + }) + ); await flush(); - assert.isTrue(element._handleAccessModified.called); + assert.isTrue(handleAccessModifiedSpy.called); }); test('_handleAccessModified called when parent changes', async () => { element._inheritsFrom = { - id: 'test-project', + id: 'test-project' as UrlEncodedRepoName, }; await flush(); - element.shadowRoot.querySelector('#editInheritFromInput').dispatchEvent( - new CustomEvent('commit', { - detail: {}, - composed: true, bubbles: true, - })); - sinon.spy(element, '_handleAccessModified'); + queryAndAssert<GrAutocomplete>( + element, + '#editInheritFromInput' + ).dispatchEvent( + new CustomEvent('commit', { + detail: {}, + composed: true, + bubbles: true, + }) + ); + const handleAccessModifiedSpy = sinon.spy( + element, + '_handleAccessModified' + ); element.dispatchEvent( - new CustomEvent('access-modified', { - detail: {}, - composed: true, bubbles: true, - })); + new CustomEvent('access-modified', { + detail: {}, + composed: true, + bubbles: true, + }) + ); await flush(); - assert.isTrue(element._handleAccessModified.called); + assert.isTrue(handleAccessModifiedSpy.called); }); test('_handleSaveForReview', async () => { - const saveStub = - stubRestApi('setRepoAccessRightsForReview'); + const saveStub = stubRestApi('setRepoAccessRightsForReview'); sinon.stub(element, '_computeAddAndRemove').returns({ add: {}, remove: {}, }); - element._handleSaveForReview(); + element._handleSaveForReview(new Event('test')); await flush(); assert.isFalse(saveStub.called); }); @@ -522,29 +618,35 @@ test('_handleSaveForReview parent change', async () => { element._inheritsFrom = { - id: 'test-project', + id: 'test-project' as UrlEncodedRepoName, }; - element._originalInheritsFrom = { - id: 'test-project-original', + element.originalInheritsFrom = { + id: 'test-project-original' as UrlEncodedRepoName, }; await flush(); assert.deepEqual(element._computeAddAndRemove(), { - parent: 'test-project', add: {}, remove: {}, + parent: 'test-project', + add: {}, + remove: {}, }); }); test('_handleSaveForReview new parent with spaces', async () => { - element._inheritsFrom = {id: 'spaces+in+project+name'}; - element._originalInheritsFrom = {id: 'old-project'}; + element._inheritsFrom = { + id: 'spaces+in+project+name' as UrlEncodedRepoName, + }; + element.originalInheritsFrom = {id: 'old-project' as UrlEncodedRepoName}; await flush(); assert.deepEqual(element._computeAddAndRemove(), { - parent: 'spaces in project name', add: {}, remove: {}, + parent: 'spaces in project name', + add: {}, + remove: {}, }); }); test('_handleSaveForReview rules', async () => { // Delete a rule. - element._local['refs/*'].permissions.owner.rules[123].deleted = true; + element._local!['refs/*'].permissions.owner.rules[123].deleted = true; await flush(); let expectedInput = { add: {}, @@ -563,10 +665,10 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Undo deleting a rule. - delete element._local['refs/*'].permissions.owner.rules[123].deleted; + delete element._local!['refs/*'].permissions.owner.rules[123].deleted; // Modify a rule. - element._local['refs/*'].permissions.owner.rules[123].modified = true; + element._local!['refs/*'].permissions.owner.rules[123].modified = true; await flush(); expectedInput = { add: { @@ -597,7 +699,9 @@ test('_computeAddAndRemove permissions', async () => { // Add a new rule to a permission. - let expectedInput = { + let expectedInput = {}; + + expectedInput = { add: { 'refs/*': { permissions: { @@ -614,22 +718,27 @@ }, remove: {}, }; - - element.shadowRoot - .querySelector('gr-access-section').shadowRoot - .querySelector('gr-permission') - ._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + const grAccessSection = queryAndAssert<GrAccessSection>( + element, + 'gr-access-section' + ); + queryAndAssert<GrPermission>( + grAccessSection, + 'gr-permission' + )._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Remove the added rule. - delete element._local['refs/*'].permissions.owner.rules.Maintainers; + delete element._local!['refs/*'].permissions.owner.rules.Maintainers; // Delete a permission. - element._local['refs/*'].permissions.owner.deleted = true; + element._local!['refs/*'].permissions.owner.deleted = true; await flush(); + expectedInput = { add: {}, remove: { @@ -643,10 +752,10 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Undo delete permission. - delete element._local['refs/*'].permissions.owner.deleted; + delete element._local!['refs/*'].permissions.owner.deleted; // Modify a permission. - element._local['refs/*'].permissions.owner.modified = true; + element._local!['refs/*'].permissions.owner.modified = true; await flush(); expectedInput = { add: { @@ -675,7 +784,9 @@ test('_computeAddAndRemove sections', async () => { // Add a new permission to a section - let expectedInput = { + let expectedInput = {}; + + expectedInput = { add: { 'refs/*': { permissions: { @@ -689,8 +800,10 @@ }, remove: {}, }; - element.shadowRoot - .querySelector('gr-access-section')._handleAddPermission(); + queryAndAssert<GrAccessSection>( + element, + 'gr-access-section' + )._handleAddPermission(); await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); @@ -716,18 +829,23 @@ }, remove: {}, }; - const newPermission = - dom(element.shadowRoot - .querySelector('gr-access-section').root).querySelectorAll( - 'gr-permission')[2]; - newPermission._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + const grAccessSection = queryAndAssert<GrAccessSection>( + element, + 'gr-access-section' + ); + const newPermission = queryAll<GrPermission>( + grAccessSection, + 'gr-permission' + )[2]; + newPermission._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Modify a section reference. - element._local['refs/*'].updatedId = 'refs/for/bar'; - element._local['refs/*'].modified = true; + element._local!['refs/*'].updatedId = 'refs/for/bar'; + element._local!['refs/*'].modified = true; await flush(); expectedInput = { add: { @@ -735,13 +853,13 @@ modified: true, updatedId: 'refs/for/bar', permissions: { - 'owner': { + owner: { rules: { 234: {action: 'ALLOW'}, 123: {action: 'DENY'}, }, }, - 'read': { + read: { rules: { 234: {action: 'ALLOW'}, }, @@ -771,7 +889,7 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Delete a section. - element._local['refs/*'].deleted = true; + element._local!['refs/*'].deleted = true; await flush(); expectedInput = { add: {}, @@ -786,7 +904,9 @@ test('_computeAddAndRemove new section', async () => { // Add a new permission to a section - let expectedInput = { + let expectedInput = {}; + + expectedInput = { add: { 'refs/for/*': { added: true, @@ -814,8 +934,10 @@ }, remove: {}, }; - const newSection = dom(element.root) - .querySelectorAll('gr-access-section')[1]; + const newSection = queryAll<GrAccessSection>( + element, + 'gr-access-section' + )[1]; newSection._handleAddPermission(); await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); @@ -844,14 +966,17 @@ remove: {}, }; - newSection.shadowRoot - .querySelector('gr-permission')._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + queryAndAssert<GrPermission>( + newSection, + 'gr-permission' + )._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Modify a the reference from the default value. - element._local['refs/for/*'].updatedId = 'refs/for/new'; + element._local!['refs/for/*'].updatedId = 'refs/for/new'; await flush(); expectedInput = { add: { @@ -881,10 +1006,12 @@ 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; + element._local!['refs/*'].permissions.owner.rules[123].modified = true; + element._local!['refs/*'].permissions.owner.deleted = true; await flush(); - let expectedInput = { + let expectedInput = {}; + + expectedInput = { add: {}, remove: { 'refs/*': { @@ -896,13 +1023,13 @@ }; assert.deepEqual(element._computeAddAndRemove(), expectedInput); // 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; + 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; + element._local!['refs/*'].permissions.read.modified = true; await flush(); expectedInput = { add: { @@ -929,10 +1056,10 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Modify both permissions with an exclusive bit. Owner is still // deleted. - element._local['refs/*'].permissions.owner.exclusive = true; - element._local['refs/*'].permissions.owner.modified = true; - element._local['refs/*'].permissions.read.exclusive = true; - element._local['refs/*'].permissions.read.modified = true; + element._local!['refs/*'].permissions.owner.exclusive = true; + 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: { @@ -960,12 +1087,17 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Add a rule to the existing permission; - const readPermission = - dom(element.shadowRoot - .querySelector('gr-access-section').root).querySelectorAll( - 'gr-permission')[1]; - readPermission._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + const grAccessSection = queryAndAssert<GrAccessSection>( + element, + 'gr-access-section' + ); + const readPermission = queryAll<GrPermission>( + grAccessSection, + 'gr-permission' + )[1]; + readPermission._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); await flush(); expectedInput = { @@ -995,8 +1127,8 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Change one of the refs - element._local['refs/*'].updatedId = 'refs/for/bar'; - element._local['refs/*'].modified = true; + element._local!['refs/*'].updatedId = 'refs/for/bar'; + element._local!['refs/*'].modified = true; await flush(); expectedInput = { @@ -1032,21 +1164,26 @@ }, }, }; - element._local['refs/*'].deleted = true; + element._local!['refs/*'].deleted = true; await flush(); assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Add a new section. MockInteractions.tap(element.$.addReferenceBtn); - let newSection = dom(element.root) - .querySelectorAll('gr-access-section')[1]; + let newSection = queryAll<GrAccessSection>( + element, + 'gr-access-section' + )[1]; newSection._handleAddPermission(); await flush(); - newSection.shadowRoot - .querySelector('gr-permission')._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + queryAndAssert<GrPermission>( + newSection, + 'gr-permission' + )._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); // Modify a the reference from the default value. - element._local['refs/for/*'].updatedId = 'refs/for/new'; + element._local!['refs/for/*'].updatedId = 'refs/for/new'; await flush(); expectedInput = { @@ -1079,8 +1216,9 @@ assert.deepEqual(element._computeAddAndRemove(), expectedInput); // Modify newly added rule inside new ref. - element._local['refs/for/*'].permissions['label-Code-Review']. - rules['Maintainers'].modified = true; + element._local!['refs/for/*'].permissions['label-Code-Review'].rules[ + 'Maintainers' + ].modified = true; await flush(); expectedInput = { add: { @@ -1115,15 +1253,17 @@ // Add a second new section. MockInteractions.tap(element.$.addReferenceBtn); await flush(); - newSection = dom(element.root) - .querySelectorAll('gr-access-section')[2]; + newSection = queryAll<GrAccessSection>(element, 'gr-access-section')[2]; newSection._handleAddPermission(); await flush(); - newSection.shadowRoot - .querySelector('gr-permission')._handleAddRuleItem( - {detail: {value: 'Maintainers'}}); + queryAndAssert<GrPermission>( + newSection, + 'gr-permission' + )._handleAddRuleItem({ + detail: {value: 'Maintainers'}, + } as AutocompleteCommitEvent); // Modify a the reference from the default value. - element._local['refs/for/**'].updatedId = 'refs/for/new2'; + element._local!['refs/for/**'].updatedId = 'refs/for/new2'; await flush(); expectedInput = { add: { @@ -1178,16 +1318,16 @@ // 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); + 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); + 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); + assert.equal(element._sections!.length, 1); + assert.equal(Object.keys(element._local!).length, 1); }); test('_handleSave', async () => { @@ -1216,24 +1356,25 @@ }, }; stubRestApi('getRepoAccessRights').returns( - Promise.resolve(JSON.parse(JSON.stringify(accessRes)))); - sinon.stub(GerritNav, 'navigateToChange'); - let resolver; - const saveStub = stubRestApi( - 'setRepoAccessRights') - .returns(new Promise(r => resolver = r)); + Promise.resolve(JSON.parse(JSON.stringify(accessRes))) + ); + const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange'); + let resolver: (value: Response | PromiseLike<Response>) => void; + const saveStub = stubRestApi('setRepoAccessRights').returns( + new Promise(r => (resolver = r)) + ); - element.repo = 'test-repo'; + element.repo = 'test-repo' as RepoName; sinon.stub(element, '_computeAddAndRemove').returns(repoAccessInput); element._modified = true; MockInteractions.tap(element.$.saveBtn); await flush(); assert.equal(element.$.saveBtn.hasAttribute('loading'), true); - resolver({_number: 1}); + resolver!({status: 200} as Response); await flush(); assert.isTrue(saveStub.called); - assert.isTrue(GerritNav.navigateToChange.notCalled); + assert.isTrue(navigateToChangeStub.notCalled); }); test('_handleSaveForReview', async () => { @@ -1262,26 +1403,27 @@ }, }; stubRestApi('getRepoAccessRights').returns( - Promise.resolve(JSON.parse(JSON.stringify(accessRes)))); - sinon.stub(GerritNav, 'navigateToChange'); - let resolver; + Promise.resolve(JSON.parse(JSON.stringify(accessRes))) + ); + const navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange'); + let resolver: (value: ChangeInfo | PromiseLike<ChangeInfo>) => void; const saveForReviewStub = stubRestApi( - 'setRepoAccessRightsForReview') - .returns(new Promise(r => resolver = r)); + 'setRepoAccessRightsForReview' + ).returns(new Promise(r => (resolver = r))); - element.repo = 'test-repo'; + element.repo = 'test-repo' as RepoName; sinon.stub(element, '_computeAddAndRemove').returns(repoAccessInput); element._modified = true; MockInteractions.tap(element.$.saveReviewBtn); await flush(); assert.equal(element.$.saveReviewBtn.hasAttribute('loading'), true); - resolver({_number: 1}); + resolver!(createChange()); await flush(); assert.isTrue(saveForReviewStub.called); - assert.isTrue(GerritNav.navigateToChange - .lastCall.calledWithExactly({_number: 1})); + assert.isTrue( + navigateToChangeStub.lastCall.calledWithExactly(createChange()) + ); }); }); }); -