
These tags are preserved by the Closure compiler and vulcanize in order to serve the license notices embedded in the outputs. In a standalone Gerrit server, these license are also covered in the LICENSES.txt served with the documentation. When serving PG assets from a CDN, it's less obvious what the corresponding LICENSES.txt file is, since the CDN is not directly linked to a running Gerrit server. Safer to embed the licenses in the assets themselves. Change-Id: Id1add1451fad1baa7916882a6bda02c326ccc988
999 lines
30 KiB
HTML
999 lines
30 KiB
HTML
<!DOCTYPE html>
|
|
<!--
|
|
@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.
|
|
-->
|
|
|
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
|
<title>gr-repo-access</title>
|
|
|
|
<script src="../../../bower_components/page/page.js"></script>
|
|
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
|
<link rel="import" href="../../../test/common-test-setup.html"/>
|
|
<link rel="import" href="gr-repo-access.html">
|
|
|
|
<script>void(0);</script>
|
|
|
|
<test-fixture id="basic">
|
|
<template>
|
|
<gr-repo-access></gr-repo-access>
|
|
</template>
|
|
</test-fixture>
|
|
|
|
<script>
|
|
suite('gr-repo-access tests', () => {
|
|
let element;
|
|
let sandbox;
|
|
let repoStub;
|
|
|
|
const accessRes = {
|
|
local: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
123: {action: 'DENY'},
|
|
},
|
|
},
|
|
read: {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
groups: {
|
|
Administrators: {
|
|
name: 'Administrators',
|
|
},
|
|
Maintainers: {
|
|
name: 'Maintainers',
|
|
},
|
|
},
|
|
config_web_links: [{
|
|
name: 'gitiles',
|
|
target: '_blank',
|
|
url: 'https://my/site/+log/123/project.config',
|
|
}],
|
|
can_upload: true,
|
|
};
|
|
const accessRes2 = {
|
|
local: {
|
|
GLOBAL_CAPABILITIES: {
|
|
permissions: {
|
|
accessDatabase: {
|
|
rules: {
|
|
group1: {
|
|
action: 'ALLOW',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const repoRes = {
|
|
labels: {
|
|
'Code-Review': {
|
|
values: {
|
|
' 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',
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const capabilitiesRes = {
|
|
accessDatabase: {
|
|
id: 'accessDatabase',
|
|
name: 'Access Database',
|
|
},
|
|
createAccount: {
|
|
id: 'createAccount',
|
|
name: 'Create Account',
|
|
},
|
|
};
|
|
setup(() => {
|
|
sandbox = sinon.sandbox.create();
|
|
element = fixture('basic');
|
|
stub('gr-rest-api-interface', {
|
|
getAccount() { return Promise.resolve(null); },
|
|
});
|
|
repoStub = sandbox.stub(element.$.restAPI, 'getRepo').returns(
|
|
Promise.resolve(repoRes));
|
|
element._loading = false;
|
|
});
|
|
|
|
teardown(() => {
|
|
sandbox.restore();
|
|
});
|
|
|
|
test('_repoChanged called when repo name changes', () => {
|
|
sandbox.stub(element, '_repoChanged');
|
|
element.repo = 'New Repo';
|
|
assert.isTrue(element._repoChanged.called);
|
|
});
|
|
|
|
test('_repoChanged', done => {
|
|
const accessStub = sandbox.stub(element.$.restAPI,
|
|
'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 = sandbox.stub(element.$.restAPI,
|
|
'getCapabilities');
|
|
capabilitiesStub.returns(Promise.resolve(capabilitiesRes));
|
|
const adminStub = sandbox.stub(element.$.restAPI, 'getIsAdmin').returns(
|
|
Promise.resolve(true));
|
|
|
|
element._repoChanged('New Repo').then(() => {
|
|
assert.isTrue(accessStub.called);
|
|
assert.isTrue(capabilitiesStub.called);
|
|
assert.isTrue(repoStub.called);
|
|
assert.isTrue(adminStub.called);
|
|
assert.isNotOk(element._inheritsFrom);
|
|
assert.deepEqual(element._local, accessRes.local);
|
|
assert.deepEqual(element._sections,
|
|
element.toSortedArray(accessRes.local));
|
|
assert.deepEqual(element._labels, repoRes.labels);
|
|
assert.equal(getComputedStyle(element.$$('.weblinks')).display,
|
|
'block');
|
|
return element._repoChanged('Another New Repo');
|
|
})
|
|
.then(() => {
|
|
assert.deepEqual(element._sections,
|
|
element.toSortedArray(accessRes2.local));
|
|
assert.equal(getComputedStyle(element.$$('.weblinks')).display,
|
|
'none');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('_repoChanged when repo changes to undefined returns', done => {
|
|
const capabilitiesRes = {
|
|
accessDatabase: {
|
|
id: 'accessDatabase',
|
|
name: 'Access Database',
|
|
},
|
|
};
|
|
const accessStub = sandbox.stub(element.$.restAPI, 'getRepoAccessRights')
|
|
.returns(Promise.resolve(JSON.parse(JSON.stringify(accessRes2))));
|
|
const capabilitiesStub = sandbox.stub(element.$.restAPI,
|
|
'getCapabilities').returns(Promise.resolve(capabilitiesRes));
|
|
|
|
element._repoChanged().then(() => {
|
|
assert.isFalse(accessStub.called);
|
|
assert.isFalse(capabilitiesStub.called);
|
|
assert.isFalse(repoStub.called);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('_computeParentHref', () => {
|
|
const repoName = 'test-repo';
|
|
assert.equal(element._computeParentHref(repoName),
|
|
'/admin/repos/test-repo,access');
|
|
});
|
|
|
|
test('_computeAdminClass', () => {
|
|
let isAdmin = true;
|
|
assert.equal(element._computeAdminClass(isAdmin), 'admin');
|
|
isAdmin = false;
|
|
assert.equal(element._computeAdminClass(isAdmin), '');
|
|
});
|
|
|
|
test('inherit section', () => {
|
|
sandbox.stub(element, '_computeParentHref');
|
|
assert.isNotOk(Polymer.dom(element.root).querySelector('#inheritsFrom'));
|
|
assert.isFalse(element._computeParentHref.called);
|
|
element._inheritsFrom = {
|
|
name: 'another-repo',
|
|
};
|
|
flushAsynchronousOperations();
|
|
assert.isOk(Polymer.dom(element.root).querySelector('#inheritsFrom'));
|
|
assert.isTrue(element._computeParentHref.called);
|
|
});
|
|
|
|
test('_computeLoadingClass', () => {
|
|
assert.equal(element._computeLoadingClass(true), 'loading');
|
|
assert.equal(element._computeLoadingClass(false), '');
|
|
});
|
|
|
|
test('fires page-error', done => {
|
|
const response = {status: 404};
|
|
|
|
sandbox.stub(
|
|
element.$.restAPI, 'getRepoAccessRights', (repoName, errFn) => {
|
|
errFn(response);
|
|
});
|
|
|
|
element.addEventListener('page-error', e => {
|
|
assert.deepEqual(e.detail.response, response);
|
|
done();
|
|
});
|
|
|
|
element.repo = 'test';
|
|
});
|
|
|
|
suite('with defined sections', () => {
|
|
const testEditSaveCancelBtns = () => {
|
|
// Edit button is visible and Save button is hidden.
|
|
assert.equal(getComputedStyle(element.$.saveBtn).display, 'none');
|
|
assert.notEqual(getComputedStyle(element.$.editBtn).display, 'none');
|
|
assert.equal(element.$.editBtn.innerText, 'EDIT');
|
|
|
|
MockInteractions.tap(element.$.editBtn);
|
|
|
|
// Edit button changes to Cancel button, and Save button is visible but
|
|
// disabled.
|
|
assert.equal(element.$.editBtn.innerText, 'CANCEL');
|
|
assert.notEqual(getComputedStyle(element.$.saveBtn).display, 'none');
|
|
assert.isTrue(element.$.saveBtn.disabled);
|
|
|
|
// Save button should be enabled after access is modified
|
|
element.fire('access-modified');
|
|
assert.isFalse(element.$.saveBtn.disabled);
|
|
};
|
|
|
|
setup(() => {
|
|
// Create deep copies of these objects so the originals are not modified
|
|
// by any tests.
|
|
element._local = JSON.parse(JSON.stringify(accessRes.local));
|
|
element._sections = element.toSortedArray(element._local);
|
|
element._groups = JSON.parse(JSON.stringify(accessRes.groups));
|
|
element._capabilities = JSON.parse(JSON.stringify(capabilitiesRes));
|
|
element._labels = JSON.parse(JSON.stringify(repoRes.labels));
|
|
flushAsynchronousOperations();
|
|
});
|
|
|
|
test('button visibility for non admin', () => {
|
|
assert.equal(getComputedStyle(element.$.saveBtn).display, 'none');
|
|
assert.equal(getComputedStyle(element.$.editBtn).display, 'none');
|
|
});
|
|
|
|
test('button visibility for non admin with upload privilege', () => {
|
|
element._canUpload = true;
|
|
testEditSaveCancelBtns();
|
|
});
|
|
|
|
test('button visibility for admin', () => {
|
|
element._isAdmin = true;
|
|
testEditSaveCancelBtns();
|
|
});
|
|
|
|
test('_handleAccessModified called with event fired', () => {
|
|
sandbox.spy(element, '_handleAccessModified');
|
|
element.fire('access-modified');
|
|
assert.isTrue(element._handleAccessModified.called);
|
|
});
|
|
|
|
test('_handleAccessModified called with event fired', () => {
|
|
const saveStub =
|
|
sandbox.stub(element.$.restAPI, 'setProjectAccessRightsForReview');
|
|
sandbox.stub(element, '_computeAddAndRemove').returns({
|
|
add: {},
|
|
remove: {},
|
|
});
|
|
element._handleSaveForReview();
|
|
assert.isFalse(saveStub.called);
|
|
});
|
|
|
|
test('_recursivelyRemoveDeleted', () => {
|
|
const obj = {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
123: {action: 'DENY', deleted: true},
|
|
},
|
|
},
|
|
read: {
|
|
deleted: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const expectedResult = {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
element._recursivelyRemoveDeleted(obj);
|
|
assert.deepEqual(obj, expectedResult);
|
|
});
|
|
|
|
test('_handleSaveForReview with no changes', () => {
|
|
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
|
|
});
|
|
|
|
test('_handleSaveForReview rules', () => {
|
|
// Delete a rule.
|
|
element._local['refs/*'].permissions.owner.rules[123].deleted = true;
|
|
let expectedInput = {
|
|
add: {},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
123: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Undo deleting a rule.
|
|
delete element._local['refs/*'].permissions.owner.rules[123].deleted;
|
|
|
|
// Modify a rule.
|
|
element._local['refs/*'].permissions.owner.rules[123].modified = true;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
123: {action: 'DENY', modified: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
123: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
});
|
|
|
|
test('_computeAddAndRemove permissions', () => {
|
|
// Add a new rule to a permission.
|
|
let expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
|
|
element.$$('gr-access-section').$$('gr-permission')._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
|
|
flushAsynchronousOperations();
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Remove the added rule.
|
|
delete element._local['refs/*'].permissions.owner.rules.Maintainers;
|
|
|
|
// Delete a permission.
|
|
element._local['refs/*'].permissions.owner.deleted = true;
|
|
expectedInput = {
|
|
add: {},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Undo delete permission.
|
|
delete element._local['refs/*'].permissions.owner.deleted;
|
|
|
|
// Modify a permission.
|
|
element._local['refs/*'].permissions.owner.modified = true;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
modified: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
123: {action: 'DENY'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
});
|
|
|
|
test('_computeAddAndRemove sections', () => {
|
|
// Add a new permission to a section
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
element.$$('gr-access-section')._handleAddPermission();
|
|
flushAsynchronousOperations();
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Add a new rule to the new permission.
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
min: -2,
|
|
max: 2,
|
|
action: 'ALLOW',
|
|
added: true,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
const newPermission =
|
|
Polymer.dom(element.$$('gr-access-section').root).querySelectorAll(
|
|
'gr-permission')[2];
|
|
newPermission._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Modify a section reference.
|
|
element._local['refs/*'].updatedId = 'refs/for/bar';
|
|
element._local['refs/*'].modified = true;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/bar': {
|
|
modified: true,
|
|
updatedId: 'refs/for/bar',
|
|
permissions: {
|
|
'owner': {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
123: {action: 'DENY'},
|
|
},
|
|
},
|
|
'read': {
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
min: -2,
|
|
max: 2,
|
|
action: 'ALLOW',
|
|
added: true,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Delete a section.
|
|
element._local['refs/*'].deleted = true;
|
|
expectedInput = {
|
|
add: {},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
});
|
|
|
|
test('_computeAddAndRemove new section', () => {
|
|
// Add a new permission to a section
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/*': {
|
|
added: true,
|
|
permissions: {},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
MockInteractions.tap(element.$.addReferenceBtn);
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/*': {
|
|
added: true,
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
const newSection = Polymer.dom(element.root)
|
|
.querySelectorAll('gr-access-section')[1];
|
|
newSection._handleAddPermission();
|
|
flushAsynchronousOperations();
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Add rule to the new permission.
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/*': {
|
|
added: true,
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
|
|
newSection.$$('gr-permission')._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
|
|
flushAsynchronousOperations();
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Modify a the reference from the default value.
|
|
element._local['refs/for/*'].updatedId = 'refs/for/new';
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/new': {
|
|
added: true,
|
|
updatedId: 'refs/for/new',
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
});
|
|
|
|
test('_computeAddAndRemove combinations', () => {
|
|
// 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;
|
|
let expectedInput = {
|
|
add: {},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
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;
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Also modify a different rule inside of another permission.
|
|
element._local['refs/*'].permissions.read.modified = true;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
read: {
|
|
modified: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
read: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
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;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
read: {
|
|
exclusive: true,
|
|
modified: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
read: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Add a rule to the existing permission;
|
|
const readPermission =
|
|
Polymer.dom(element.$$('gr-access-section').root).querySelectorAll(
|
|
'gr-permission')[1];
|
|
readPermission._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
|
|
expectedInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
read: {
|
|
exclusive: true,
|
|
modified: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
Maintainers: {action: 'ALLOW', added: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {rules: {}},
|
|
read: {rules: {}},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Change one of the refs
|
|
element._local['refs/*'].updatedId = 'refs/for/bar';
|
|
element._local['refs/*'].modified = true;
|
|
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/bar': {
|
|
modified: true,
|
|
updatedId: 'refs/for/bar',
|
|
permissions: {
|
|
read: {
|
|
exclusive: true,
|
|
modified: true,
|
|
rules: {
|
|
234: {action: 'ALLOW'},
|
|
Maintainers: {action: 'ALLOW', added: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
expectedInput = {
|
|
add: {},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
element._local['refs/*'].deleted = true;
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Add a new section.
|
|
MockInteractions.tap(element.$.addReferenceBtn);
|
|
let newSection = Polymer.dom(element.root)
|
|
.querySelectorAll('gr-access-section')[1];
|
|
newSection._handleAddPermission();
|
|
flushAsynchronousOperations();
|
|
newSection.$$('gr-permission')._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
// Modify a the reference from the default value.
|
|
element._local['refs/for/*'].updatedId = 'refs/for/new';
|
|
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/new': {
|
|
added: true,
|
|
updatedId: 'refs/for/new',
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Modify newly added rule inside new ref.
|
|
element._local['refs/for/*'].permissions['label-Code-Review'].
|
|
rules['Maintainers'].modified = true;
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/new': {
|
|
added: true,
|
|
updatedId: 'refs/for/new',
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
modified: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
|
|
// Add a second new section.
|
|
MockInteractions.tap(element.$.addReferenceBtn);
|
|
newSection = Polymer.dom(element.root)
|
|
.querySelectorAll('gr-access-section')[2];
|
|
newSection._handleAddPermission();
|
|
flushAsynchronousOperations();
|
|
newSection.$$('gr-permission')._handleAddRuleItem(
|
|
{detail: {value: {id: 'Maintainers'}}});
|
|
// Modify a the reference from the default value.
|
|
element._local['refs/for/**'].updatedId = 'refs/for/new2';
|
|
expectedInput = {
|
|
add: {
|
|
'refs/for/new': {
|
|
added: true,
|
|
updatedId: 'refs/for/new',
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
modified: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
'refs/for/new2': {
|
|
added: true,
|
|
updatedId: 'refs/for/new2',
|
|
permissions: {
|
|
'label-Code-Review': {
|
|
added: true,
|
|
rules: {
|
|
Maintainers: {
|
|
action: 'ALLOW',
|
|
added: true,
|
|
max: 2,
|
|
min: -2,
|
|
},
|
|
},
|
|
label: 'Code-Review',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {},
|
|
},
|
|
},
|
|
};
|
|
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
|
});
|
|
|
|
test('Unsaved added refs are discarded when edit cancelled', () => {
|
|
// Unsaved changes are discarded when editing is cancelled.
|
|
MockInteractions.tap(element.$.editBtn);
|
|
assert.equal(element._sections.length, 1);
|
|
assert.equal(Object.keys(element._local).length, 1);
|
|
MockInteractions.tap(element.$.addReferenceBtn);
|
|
assert.equal(element._sections.length, 2);
|
|
assert.equal(Object.keys(element._local).length, 2);
|
|
MockInteractions.tap(element.$.editBtn);
|
|
assert.equal(element._sections.length, 1);
|
|
assert.equal(Object.keys(element._local).length, 1);
|
|
});
|
|
|
|
test('_handleSaveForReview', done => {
|
|
const repoAccessInput = {
|
|
add: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
123: {action: 'DENY', modified: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
remove: {
|
|
'refs/*': {
|
|
permissions: {
|
|
owner: {
|
|
rules: {
|
|
123: {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
sandbox.stub(element.$.restAPI, 'getRepoAccessRights').returns(
|
|
Promise.resolve(JSON.parse(JSON.stringify(accessRes))));
|
|
sandbox.stub(Gerrit.Nav, 'navigateToChange');
|
|
const saveForReviewStub = sandbox.stub(element.$.restAPI,
|
|
'setProjectAccessRightsForReview')
|
|
.returns(Promise.resolve({_number: 1}));
|
|
|
|
element.repo = 'test-repo';
|
|
sandbox.stub(element, '_computeAddAndRemove').returns(repoAccessInput);
|
|
|
|
element._handleSaveForReview().then(() => {
|
|
assert.isTrue(saveForReviewStub.called);
|
|
assert.isTrue(Gerrit.Nav.navigateToChange
|
|
.lastCall.calledWithExactly({_number: 1}));
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
</script>
|