blob: 25b14e2ec68d24891054139916f1eb16be0a9552 [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 {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
const basicFixture = fixtureFromElement('gr-admin-view');
suite('gr-admin-view tests', () => {
let element;
setup(done => {
element = basicFixture.instantiate();
stub('gr-rest-api-interface', {
getProjectConfig() {
return Promise.resolve({});
},
});
const pluginsLoaded = Promise.resolve();
sinon.stub(pluginLoader, 'awaitPluginsLoaded').returns(pluginsLoaded);
pluginsLoaded.then(() => flush(done));
});
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');
sinon.stub(element, 'getBaseUrl').returns('/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',
};
flushAsynchronousOperations();
assert.equal(dom(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', done => {
sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
})
);
element.reload().then(() => {
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);
done();
});
});
test('_filteredLinks non admin authenticated', done => {
sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({})
);
element.reload().then(() => {
assert.equal(element._filteredLinks.length, 2);
// Repos
assert.isNotOk(element._filteredLinks[0].subsection);
// Groups
assert.isNotOk(element._filteredLinks[0].subsection);
done();
});
});
test('_filteredLinks non admin unathenticated', done => {
element.reload().then(() => {
assert.equal(element._filteredLinks.length, 1);
// Repos
assert.isNotOk(element._filteredLinks[0].subsection);
done();
});
});
test('_filteredLinks from plugin', () => {
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: null,
url: '/internal/link/url',
name: 'internal link text',
noBaseUrl: true,
view: null,
viewableToAll: true,
target: null,
});
assert.deepEqual(element._filteredLinks[2], {
capability: null,
url: 'http://external/link/url',
name: 'external link text',
noBaseUrl: false,
view: null,
viewableToAll: true,
target: '_blank',
});
});
});
test('Repo shows up in nav', done => {
element._repoName = 'Test Repo';
sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
element.reload().then(() => {
flushAsynchronousOperations();
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,
6
);
done();
});
});
test('Group shows up in nav', done => {
element._groupId = 'a15262';
element._groupName = 'my-group';
element._groupIsInternal = true;
element._isAdmin = true;
element._groupOwner = false;
sinon.stub(element.$.restAPI, 'getAccount').returns(Promise.resolve({
name: 'test-user',
}));
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
element.reload().then(() => {
flushAsynchronousOperations();
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);
done();
});
});
test('Nav is reloaded when repo changes', () => {
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
sinon.stub(
element.$.restAPI,
'getAccount')
.callsFake(() => Promise.resolve({_id: 1}));
sinon.stub(element, 'reload');
element.params = {repo: 'Test Repo', adminView: 'gr-repo'};
assert.equal(element.reload.callCount, 1);
element.params = {repo: 'Test Repo 2',
adminView: 'gr-repo'};
assert.equal(element.reload.callCount, 2);
});
test('Nav is reloaded when group changes', () => {
sinon.stub(element, '_computeGroupName');
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
sinon.stub(
element.$.restAPI,
'getAccount')
.callsFake(() => Promise.resolve({_id: 1}));
sinon.stub(element, 'reload');
element.params = {groupId: '1', adminView: 'gr-group'};
assert.equal(element.reload.callCount, 1);
});
test('Nav is reloaded when group name changes', done => {
const newName = 'newName';
sinon.stub(element, '_computeGroupName');
sinon.stub(element, 'reload').callsFake(() => {
assert.equal(element._groupName, newName);
assert.isTrue(element.reload.called);
done();
});
element.params = {group: 1, view: GerritNav.View.GROUP};
element._groupName = 'oldName';
flushAsynchronousOperations();
element.shadowRoot
.querySelector('gr-group').dispatchEvent(
new CustomEvent('name-changed', {
detail: {name: newName},
composed: true, bubbles: true,
}));
});
test('dropdown displays if there is a subsection', () => {
assert.isNotOk(element.shadowRoot
.querySelector('.mainHeader'));
element._subsectionLinks = [
{
text: 'Home',
value: 'repo',
view: 'repo',
url: '',
parent: 'my-repo',
detailType: undefined,
},
];
flushAsynchronousOperations();
assert.isOk(element.shadowRoot
.querySelector('.mainHeader'));
element._subsectionLinks = undefined;
flushAsynchronousOperations();
assert.equal(
getComputedStyle(element.shadowRoot
.querySelector('.mainHeader')).display,
'none');
});
test('Dropdown only triggers navigation on explicit select', done => {
element._repoName = 'my-repo';
element.params = {
repo: 'my-repo',
view: GerritNav.View.REPO,
detail: GerritNav.RepoDetailView.ACCESS,
};
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
sinon.stub(
element.$.restAPI,
'getAccount')
.callsFake(() => Promise.resolve({_id: 1}));
flushAsynchronousOperations();
const expectedFilteredLinks = [
{
name: 'Repositories',
noBaseUrl: true,
url: '/admin/repos',
view: 'gr-repo-list',
viewableToAll: true,
subsection: {
name: 'my-repo',
view: 'repo',
url: '',
children: [
{
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: '',
parent: 'my-repo',
detailType: undefined,
},
{
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');
element.reload().then(() => {
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 = 'repo';
assert.isTrue(element._selectedIsCurrentPage.calledTwice);
assert.isTrue(GerritNav.navigateToRelativeUrl.calledOnce);
done();
});
});
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(() => {
sinon.stub(
element.$.restAPI,
'getAccountCapabilities')
.callsFake(() => Promise.resolve({
createGroup: true,
createProject: true,
viewPlugins: true,
}));
sinon.stub(
element.$.restAPI,
'getAccount')
.callsFake(() => Promise.resolve({_id: 1}));
return element.reload();
});
suite('repos', () => {
setup(() => {
stub('gr-repo-access', {
_repoChanged: () => {},
});
});
test('repo list', () => {
element.params = {
view: GerritNav.View.ADMIN,
adminView: 'gr-repo-list',
openCreateModal: false,
};
flushAsynchronousOperations();
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(() => {
flushAsynchronousOperations();
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(() => {
flushAsynchronousOperations();
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(() => {
flushAsynchronousOperations();
const selected = element.shadowRoot
.querySelector('gr-page-nav .selected');
assert.isOk(selected);
assert.equal(selected.textContent.trim(), 'Dashboards');
});
});
});
suite('groups', () => {
setup(() => {
stub('gr-group', {
_loadGroup: () => Promise.resolve({}),
});
stub('gr-group-members', {
_loadGroupDetails: () => {},
});
sinon.stub(element.$.restAPI, 'getGroupConfig')
.returns(Promise.resolve({
name: 'foo',
id: 'c0f83e941ce90caea30e6ad88f0d4ea0e841a7a9',
}));
sinon.stub(element.$.restAPI, 'getIsGroupOwner')
.returns(Promise.resolve(true));
return element.reload();
});
test('group list', () => {
element.params = {
view: GerritNav.View.ADMIN,
adminView: 'gr-admin-group-list',
openCreateModal: false,
};
flushAsynchronousOperations();
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(() => {
flushAsynchronousOperations();
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', () => {
element.$.restAPI.getGroupConfig.restore();
sinon.stub(element.$.restAPI, 'getGroupConfig')
.returns(Promise.resolve({
name: 'foo',
id: 'external-id',
}));
element.params = {
view: GerritNav.View.GROUP,
groupId: 1234,
};
element._groupName = 'foo';
return element.reload().then(() => {
flushAsynchronousOperations();
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(() => {
flushAsynchronousOperations();
const selected = element.shadowRoot
.querySelector('gr-page-nav .selected');
assert.isOk(selected);
assert.equal(selected.textContent.trim(), 'Members');
});
});
});
});
});