| /** |
| * @license |
| * Copyright (C) 2017 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 '../../../test/common-test-setup-karma.js'; |
| import './gr-admin-view.js'; |
| import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js'; |
| import {GerritNav} from '../../core/gr-navigation/gr-navigation.js'; |
| import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js'; |
| import {mockPromise, stubBaseUrl, stubRestApi} from '../../../test/test-utils.js'; |
| import {GerritView} from '../../../services/router/router-model.js'; |
| |
| const basicFixture = fixtureFromElement('gr-admin-view'); |
| |
| function createAdminCapabilities() { |
| return { |
| createGroup: true, |
| createProject: true, |
| viewPlugins: true, |
| }; |
| } |
| |
| suite('gr-admin-view tests', () => { |
| let element; |
| |
| setup(async () => { |
| element = basicFixture.instantiate(); |
| stubRestApi('getProjectConfig').returns(Promise.resolve({})); |
| const pluginsLoaded = Promise.resolve(); |
| sinon.stub(getPluginLoader(), 'awaitPluginsLoaded').returns(pluginsLoaded); |
| await pluginsLoaded; |
| await flush(); |
| }); |
| |
| test('_computeURLHelper', () => { |
| const path = '/test'; |
| const host = 'http://www.testsite.com'; |
| const computedPath = element._computeURLHelper(host, path); |
| assert.equal(computedPath, '//http://www.testsite.com/test'); |
| }); |
| |
| test('link URLs', () => { |
| assert.equal( |
| element._computeLinkURL({url: '/test', noBaseUrl: true}), |
| '//' + window.location.host + '/test'); |
| |
| stubBaseUrl('/foo'); |
| assert.equal( |
| element._computeLinkURL({url: '/test', noBaseUrl: true}), |
| '//' + window.location.host + '/foo/test'); |
| assert.equal(element._computeLinkURL({url: '/test'}), '/test'); |
| assert.equal( |
| element._computeLinkURL({url: '/test', target: '_blank'}), |
| '/test'); |
| }); |
| |
| test('current page gets selected and is displayed', () => { |
| element._filteredLinks = [{ |
| name: 'Repositories', |
| url: '/admin/repos', |
| view: 'gr-repo-list', |
| }]; |
| |
| element.params = { |
| view: 'admin', |
| adminView: 'gr-repo-list', |
| }; |
| |
| flush(); |
| assert.equal(element.root.querySelectorAll( |
| '.selected').length, 1); |
| assert.ok(element.shadowRoot |
| .querySelector('gr-repo-list')); |
| assert.isNotOk(element.shadowRoot |
| .querySelector('gr-admin-create-repo')); |
| }); |
| |
| test('_filteredLinks admin', async () => { |
| stubRestApi('getAccount').returns(Promise.resolve({ |
| name: 'test-user', |
| })); |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| await element.reload(); |
| assert.equal(element._filteredLinks.length, 3); |
| |
| // Repos |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| |
| // Groups |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| |
| // Plugins |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| }); |
| |
| test('_filteredLinks non admin authenticated', async () => { |
| await element.reload(); |
| assert.equal(element._filteredLinks.length, 2); |
| // Repos |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| // Groups |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| }); |
| |
| test('_filteredLinks non admin unathenticated', async () => { |
| stubRestApi('getAccount').returns(Promise.resolve(undefined)); |
| await element.reload(); |
| assert.equal(element._filteredLinks.length, 1); |
| // Repos |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| }); |
| |
| test('_filteredLinks from plugin', () => { |
| stubRestApi('getAccount').returns(Promise.resolve(undefined)); |
| sinon.stub(element.jsAPI, 'getAdminMenuLinks').returns([ |
| {text: 'internal link text', url: '/internal/link/url'}, |
| {text: 'external link text', url: 'http://external/link/url'}, |
| ]); |
| return element.reload().then(() => { |
| assert.equal(element._filteredLinks.length, 3); |
| assert.deepEqual(element._filteredLinks[1], { |
| capability: undefined, |
| url: '/internal/link/url', |
| name: 'internal link text', |
| noBaseUrl: true, |
| view: null, |
| viewableToAll: true, |
| target: null, |
| }); |
| assert.deepEqual(element._filteredLinks[2], { |
| capability: undefined, |
| url: 'http://external/link/url', |
| name: 'external link text', |
| noBaseUrl: false, |
| view: null, |
| viewableToAll: true, |
| target: '_blank', |
| }); |
| }); |
| }); |
| |
| test('Repo shows up in nav', async () => { |
| element._repoName = 'Test Repo'; |
| stubRestApi('getAccount').returns(Promise.resolve({ |
| name: 'test-user', |
| })); |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| await element.reload(); |
| await flush(); |
| assert.equal(dom(element.root) |
| .querySelectorAll('.sectionTitle').length, 3); |
| assert.equal(element.shadowRoot |
| .querySelector('.breadcrumbText').innerText, 'Test Repo'); |
| assert.equal( |
| element.shadowRoot.querySelector('#pageSelect').items.length, |
| 7 |
| ); |
| }); |
| |
| test('Group shows up in nav', async () => { |
| element._groupId = 'a15262'; |
| element._groupName = 'my-group'; |
| element._groupIsInternal = true; |
| element._isAdmin = true; |
| element._groupOwner = false; |
| stubRestApi('getAccount').returns(Promise.resolve({name: 'test-user'})); |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| await element.reload(); |
| await flush(); |
| assert.equal(element._filteredLinks.length, 3); |
| // Repos |
| assert.isNotOk(element._filteredLinks[0].subsection); |
| // Groups |
| assert.equal(element._filteredLinks[1].subsection.children.length, 2); |
| assert.equal(element._filteredLinks[1].subsection.name, 'my-group'); |
| // Plugins |
| assert.isNotOk(element._filteredLinks[2].subsection); |
| }); |
| |
| test('Nav is reloaded when repo changes', () => { |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| stubRestApi('getAccount').returns(Promise.resolve({_id: 1})); |
| sinon.stub(element, 'reload'); |
| element.params = {repo: 'Test Repo', view: GerritView.REPO}; |
| assert.equal(element.reload.callCount, 1); |
| element.params = {repo: 'Test Repo 2', |
| view: GerritView.REPO}; |
| assert.equal(element.reload.callCount, 2); |
| }); |
| |
| test('Nav is reloaded when group changes', () => { |
| sinon.stub(element, '_computeGroupName'); |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| stubRestApi('getAccount').returns(Promise.resolve({_id: 1})); |
| sinon.stub(element, 'reload'); |
| element.params = {groupId: '1', view: GerritView.GROUP}; |
| assert.equal(element.reload.callCount, 1); |
| }); |
| |
| test('Nav is reloaded when group name changes', async () => { |
| const newName = 'newName'; |
| const reloadCalled = mockPromise(); |
| sinon.stub(element, '_computeGroupName'); |
| sinon.stub(element, 'reload').callsFake(() => { |
| assert.equal(element._groupName, newName); |
| reloadCalled.resolve(); |
| }); |
| element.params = {group: 1, view: GerritNav.View.GROUP}; |
| element._groupName = 'oldName'; |
| await flush(); |
| element.shadowRoot |
| .querySelector('gr-group').dispatchEvent( |
| new CustomEvent('name-changed', { |
| detail: {name: newName}, |
| composed: true, bubbles: true, |
| })); |
| await reloadCalled; |
| }); |
| |
| test('dropdown displays if there is a subsection', () => { |
| assert.isNotOk(element.shadowRoot |
| .querySelector('.mainHeader')); |
| element._subsectionLinks = [ |
| { |
| text: 'Home', |
| value: 'repo', |
| view: 'repo', |
| parent: 'my-repo', |
| detailType: undefined, |
| }, |
| ]; |
| flush(); |
| assert.isOk(element.shadowRoot |
| .querySelector('.mainHeader')); |
| element._subsectionLinks = undefined; |
| flush(); |
| assert.equal( |
| getComputedStyle(element.shadowRoot |
| .querySelector('.mainHeader')).display, |
| 'none'); |
| }); |
| |
| test('Dropdown only triggers navigation on explicit select', async () => { |
| element._repoName = 'my-repo'; |
| element.params = { |
| repo: 'my-repo', |
| view: GerritNav.View.REPO, |
| detail: GerritNav.RepoDetailView.ACCESS, |
| }; |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| stubRestApi('getAccount').returns(Promise.resolve({_id: 1})); |
| await flush(); |
| const expectedFilteredLinks = [ |
| { |
| name: 'Repositories', |
| noBaseUrl: true, |
| url: '/admin/repos', |
| view: 'gr-repo-list', |
| viewableToAll: true, |
| subsection: { |
| name: 'my-repo', |
| view: 'repo', |
| children: [ |
| { |
| name: 'General', |
| view: 'repo', |
| url: '', |
| detailType: 'general', |
| }, |
| { |
| name: 'Access', |
| view: 'repo', |
| detailType: 'access', |
| url: '', |
| }, |
| { |
| name: 'Commands', |
| view: 'repo', |
| detailType: 'commands', |
| url: '', |
| }, |
| { |
| name: 'Branches', |
| view: 'repo', |
| detailType: 'branches', |
| url: '', |
| }, |
| { |
| name: 'Tags', |
| view: 'repo', |
| detailType: 'tags', |
| url: '', |
| }, |
| { |
| name: 'Dashboards', |
| view: 'repo', |
| detailType: 'dashboards', |
| url: '', |
| }, |
| ], |
| }, |
| }, |
| { |
| name: 'Groups', |
| section: 'Groups', |
| noBaseUrl: true, |
| url: '/admin/groups', |
| view: 'gr-admin-group-list', |
| }, |
| { |
| name: 'Plugins', |
| capability: 'viewPlugins', |
| section: 'Plugins', |
| noBaseUrl: true, |
| url: '/admin/plugins', |
| view: 'gr-plugin-list', |
| }, |
| ]; |
| const expectedSubsectionLinks = [ |
| { |
| text: 'Home', |
| value: 'repo', |
| view: 'repo', |
| url: undefined, |
| parent: 'my-repo', |
| detailType: undefined, |
| }, |
| { |
| text: 'General', |
| value: 'repogeneral', |
| view: 'repo', |
| url: '', |
| detailType: 'general', |
| parent: 'my-repo', |
| }, |
| { |
| text: 'Access', |
| value: 'repoaccess', |
| view: 'repo', |
| url: '', |
| detailType: 'access', |
| parent: 'my-repo', |
| }, |
| { |
| text: 'Commands', |
| value: 'repocommands', |
| view: 'repo', |
| url: '', |
| detailType: 'commands', |
| parent: 'my-repo', |
| }, |
| { |
| text: 'Branches', |
| value: 'repobranches', |
| view: 'repo', |
| url: '', |
| detailType: 'branches', |
| parent: 'my-repo', |
| }, |
| { |
| text: 'Tags', |
| value: 'repotags', |
| view: 'repo', |
| url: '', |
| detailType: 'tags', |
| parent: 'my-repo', |
| }, |
| { |
| text: 'Dashboards', |
| value: 'repodashboards', |
| view: 'repo', |
| url: '', |
| detailType: 'dashboards', |
| parent: 'my-repo', |
| }, |
| ]; |
| sinon.stub(GerritNav, 'navigateToRelativeUrl'); |
| sinon.spy(element, '_selectedIsCurrentPage'); |
| sinon.spy(element, '_handleSubsectionChange'); |
| await element.reload(); |
| assert.deepEqual(element._filteredLinks, expectedFilteredLinks); |
| assert.deepEqual(element._subsectionLinks, expectedSubsectionLinks); |
| assert.equal( |
| element.shadowRoot.querySelector('#pageSelect').value, |
| 'repoaccess' |
| ); |
| assert.isTrue(element._selectedIsCurrentPage.calledOnce); |
| // Doesn't trigger navigation from the page select menu. |
| assert.isFalse(GerritNav.navigateToRelativeUrl.called); |
| |
| // When explicitly changed, navigation is called |
| element.shadowRoot.querySelector('#pageSelect').value = 'repogeneral'; |
| assert.isTrue(element._selectedIsCurrentPage.calledTwice); |
| assert.isTrue(GerritNav.navigateToRelativeUrl.calledOnce); |
| }); |
| |
| test('_selectedIsCurrentPage', () => { |
| element._repoName = 'my-repo'; |
| element.params = {view: 'repo', repo: 'my-repo'}; |
| const selected = { |
| view: 'repo', |
| detailType: undefined, |
| parent: 'my-repo', |
| }; |
| assert.isTrue(element._selectedIsCurrentPage(selected)); |
| selected.parent = 'my-second-repo'; |
| assert.isFalse(element._selectedIsCurrentPage(selected)); |
| selected.detailType = 'detailType'; |
| assert.isFalse(element._selectedIsCurrentPage(selected)); |
| }); |
| |
| suite('_computeSelectedClass', () => { |
| setup(() => { |
| stubRestApi('getAccountCapabilities').returns( |
| Promise.resolve(createAdminCapabilities())); |
| stubRestApi('getAccount').returns(Promise.resolve({_id: 1})); |
| return element.reload(); |
| }); |
| |
| suite('repos', () => { |
| setup(() => { |
| stub('gr-repo-access', '_repoChanged').callsFake(() => {}); |
| }); |
| |
| test('repo list', () => { |
| element.params = { |
| view: GerritNav.View.ADMIN, |
| adminView: 'gr-repo-list', |
| openCreateModal: false, |
| }; |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'Repositories'); |
| }); |
| |
| test('repo', () => { |
| element.params = { |
| view: GerritNav.View.REPO, |
| repoName: 'foo', |
| }; |
| element._repoName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'foo'); |
| }); |
| }); |
| |
| test('repo access', () => { |
| element.params = { |
| view: GerritNav.View.REPO, |
| detail: GerritNav.RepoDetailView.ACCESS, |
| repoName: 'foo', |
| }; |
| element._repoName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'Access'); |
| }); |
| }); |
| |
| test('repo dashboards', () => { |
| element.params = { |
| view: GerritNav.View.REPO, |
| detail: GerritNav.RepoDetailView.DASHBOARDS, |
| repoName: 'foo', |
| }; |
| element._repoName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'Dashboards'); |
| }); |
| }); |
| }); |
| |
| suite('groups', () => { |
| let getGroupConfigStub; |
| setup(() => { |
| stub('gr-group', 'loadGroup').callsFake(() => Promise.resolve({})); |
| stub('gr-group-members', 'loadGroupDetails').callsFake(() => {}); |
| |
| getGroupConfigStub = stubRestApi('getGroupConfig'); |
| getGroupConfigStub.returns(Promise.resolve({ |
| name: 'foo', |
| id: 'c0f83e941ce90caea30e6ad88f0d4ea0e841a7a9', |
| })); |
| stubRestApi('getIsGroupOwner') |
| .returns(Promise.resolve(true)); |
| return element.reload(); |
| }); |
| |
| test('group list', () => { |
| element.params = { |
| view: GerritNav.View.ADMIN, |
| adminView: 'gr-admin-group-list', |
| openCreateModal: false, |
| }; |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'Groups'); |
| }); |
| |
| test('internal group', () => { |
| element.params = { |
| view: GerritNav.View.GROUP, |
| groupId: 1234, |
| }; |
| element._groupName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const subsectionItems = dom(element.root) |
| .querySelectorAll('.subsectionItem'); |
| assert.equal(subsectionItems.length, 2); |
| assert.isTrue(element._groupIsInternal); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'foo'); |
| }); |
| }); |
| |
| test('external group', () => { |
| getGroupConfigStub.returns(Promise.resolve({ |
| name: 'foo', |
| id: 'external-id', |
| })); |
| element.params = { |
| view: GerritNav.View.GROUP, |
| groupId: 1234, |
| }; |
| element._groupName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const subsectionItems = dom(element.root) |
| .querySelectorAll('.subsectionItem'); |
| assert.equal(subsectionItems.length, 0); |
| assert.isFalse(element._groupIsInternal); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'foo'); |
| }); |
| }); |
| |
| test('group members', () => { |
| element.params = { |
| view: GerritNav.View.GROUP, |
| detail: GerritNav.GroupDetailView.MEMBERS, |
| groupId: 1234, |
| }; |
| element._groupName = 'foo'; |
| return element.reload().then(() => { |
| flush(); |
| const selected = element.shadowRoot |
| .querySelector('gr-page-nav .selected'); |
| assert.isOk(selected); |
| assert.equal(selected.textContent.trim(), 'Members'); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |