blob: 63b90a5e9f38b9fb560b02a16779c3a0f9a20488 [file] [log] [blame]
/**
* @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');
});
});
});
});
});