
Updates the conditions of gr-access-section to be disabled if can_upload is false AND also not an owner of the section. This is needed for the direct save option. Bug: Issue 8298 Change-Id: I0c13159aaf2c52649bc9ed7c568c8b315911b1db
551 lines
18 KiB
HTML
551 lines
18 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-access-section</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-access-section.html">
|
|
|
|
<script>void(0);</script>
|
|
|
|
<test-fixture id="basic">
|
|
<template>
|
|
<gr-access-section></gr-access-section>
|
|
</template>
|
|
</test-fixture>
|
|
|
|
<script>
|
|
suite('gr-access-section tests', () => {
|
|
let element;
|
|
let sandbox;
|
|
|
|
setup(() => {
|
|
sandbox = sinon.sandbox.create();
|
|
element = fixture('basic');
|
|
});
|
|
|
|
teardown(() => {
|
|
sandbox.restore();
|
|
});
|
|
|
|
suite('unit tests', () => {
|
|
setup(() => {
|
|
element.section = {
|
|
id: 'refs/*',
|
|
value: {
|
|
permissions: {
|
|
read: {
|
|
rules: {},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
element.capabilities = {
|
|
accessDatabase: {
|
|
id: 'accessDatabase',
|
|
name: 'Access Database',
|
|
},
|
|
administrateServer: {
|
|
id: 'administrateServer',
|
|
name: 'Administrate Server',
|
|
},
|
|
batchChangesLimit: {
|
|
id: 'batchChangesLimit',
|
|
name: 'Batch Changes Limit',
|
|
},
|
|
createAccount: {
|
|
id: 'createAccount',
|
|
name: 'Create Account',
|
|
},
|
|
};
|
|
element.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',
|
|
},
|
|
default_value: 0,
|
|
},
|
|
};
|
|
element._updateSection(element.section);
|
|
flushAsynchronousOperations();
|
|
});
|
|
|
|
test('_updateSection', () => {
|
|
// _updateSection was called in setup, so just make assertions.
|
|
const expectedPermissions = [
|
|
{
|
|
id: 'read',
|
|
value: {
|
|
rules: {},
|
|
},
|
|
},
|
|
];
|
|
assert.deepEqual(element._permissions, expectedPermissions);
|
|
assert.equal(element._originalId, element.section.id);
|
|
});
|
|
|
|
test('_computeLabelOptions', () => {
|
|
const expectedLabelOptions = [
|
|
{
|
|
id: 'label-Code-Review',
|
|
value: {
|
|
name: 'Label Code-Review',
|
|
id: 'label-Code-Review',
|
|
},
|
|
},
|
|
{
|
|
id: 'labelAs-Code-Review',
|
|
value: {
|
|
name: 'Label Code-Review (On Behalf Of)',
|
|
id: 'labelAs-Code-Review',
|
|
},
|
|
},
|
|
];
|
|
|
|
assert.deepEqual(element._computeLabelOptions(element.labels),
|
|
expectedLabelOptions);
|
|
});
|
|
|
|
test('_handleAccessSaved', () => {
|
|
assert.equal(element._originalId, 'refs/*');
|
|
element.section.id = 'refs/for/bar';
|
|
element._handleAccessSaved();
|
|
assert.equal(element._originalId, 'refs/for/bar');
|
|
});
|
|
|
|
test('_computePermissions', () => {
|
|
sandbox.stub(element, 'toSortedArray').returns(
|
|
[{
|
|
id: 'push',
|
|
value: {
|
|
rules: {},
|
|
},
|
|
},
|
|
{
|
|
id: 'read',
|
|
value: {
|
|
rules: {},
|
|
},
|
|
},
|
|
]);
|
|
|
|
const expectedPermissions = [{
|
|
id: 'push',
|
|
value: {
|
|
rules: {},
|
|
},
|
|
},
|
|
];
|
|
const labelOptions = [
|
|
{
|
|
id: 'label-Code-Review',
|
|
value: {
|
|
name: 'Label Code-Review',
|
|
id: 'label-Code-Review',
|
|
},
|
|
},
|
|
{
|
|
id: 'labelAs-Code-Review',
|
|
value: {
|
|
name: 'Label Code-Review (On Behalf Of)',
|
|
id: 'labelAs-Code-Review',
|
|
},
|
|
},
|
|
];
|
|
|
|
// For global capabilities, just return the sorted array filtered by
|
|
// existing permissions.
|
|
let name = 'GLOBAL_CAPABILITIES';
|
|
assert.deepEqual(element._computePermissions(name, element.capabilities,
|
|
element.labels), expectedPermissions);
|
|
|
|
// Uses the capabilities array to come up with possible values.
|
|
assert.isTrue(element.toSortedArray.lastCall.
|
|
calledWithExactly(element.capabilities));
|
|
|
|
|
|
// For everything else, include possible label values before filtering.
|
|
name = 'refs/for/*';
|
|
assert.deepEqual(element._computePermissions(name, element.capabilities,
|
|
element.labels), labelOptions.concat(expectedPermissions));
|
|
|
|
// Uses permissionValues (defined in gr-access-behavior) to come up with
|
|
// possible values.
|
|
assert.isTrue(element.toSortedArray.lastCall.
|
|
calledWithExactly(element.permissionValues));
|
|
});
|
|
|
|
test('_computePermissionName', () => {
|
|
let name = 'GLOBAL_CAPABILITIES';
|
|
let permission = {
|
|
id: 'administrateServer',
|
|
value: {},
|
|
};
|
|
assert.equal(element._computePermissionName(name, permission,
|
|
element.permissionValues, element.capabilities),
|
|
element.capabilities[permission.id].name);
|
|
|
|
name = 'refs/for/*';
|
|
permission = {
|
|
id: 'abandon',
|
|
value: {},
|
|
};
|
|
|
|
assert.equal(element._computePermissionName(
|
|
name, permission, element.permissionValues, element.capabilities),
|
|
element.permissionValues[permission.id].name);
|
|
|
|
name = 'refs/for/*';
|
|
permission = {
|
|
id: 'label-Code-Review',
|
|
value: {
|
|
label: 'Code-Review',
|
|
},
|
|
};
|
|
|
|
assert.equal(element._computePermissionName(name, permission,
|
|
element.permissionValues, element.capabilities),
|
|
'Label Code-Review');
|
|
|
|
permission = {
|
|
id: 'labelAs-Code-Review',
|
|
value: {
|
|
label: 'Code-Review',
|
|
},
|
|
};
|
|
|
|
assert.equal(element._computePermissionName(name, permission,
|
|
element.permissionValues, element.capabilities),
|
|
'Label Code-Review(On Behalf Of)');
|
|
});
|
|
|
|
test('_computeSectionName', () => {
|
|
let name;
|
|
// When computing the section name for an undefined name, it means a
|
|
// new section is being added. In this case, it should defualt to
|
|
// 'refs/heads/*'.
|
|
element._editingRef = false;
|
|
assert.equal(element._computeSectionName(name),
|
|
'Reference: refs/heads/*');
|
|
assert.isTrue(element._editingRef);
|
|
assert.equal(element.section.id, 'refs/heads/*');
|
|
|
|
// Reset editing to false.
|
|
element._editingRef = false;
|
|
name = 'GLOBAL_CAPABILITIES';
|
|
assert.equal(element._computeSectionName(name), 'Global Capabilities');
|
|
assert.isFalse(element._editingRef);
|
|
|
|
name = 'refs/for/*';
|
|
assert.equal(element._computeSectionName(name),
|
|
'Reference: refs/for/*');
|
|
assert.isFalse(element._editingRef);
|
|
});
|
|
|
|
test('editReference', () => {
|
|
element.editReference();
|
|
assert.isTrue(element._editingRef);
|
|
});
|
|
|
|
test('_computeSectionClass', () => {
|
|
let editingRef = false;
|
|
let canUpload = false;
|
|
let ownerOf = [];
|
|
let editing = false;
|
|
let deleted = false;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), '');
|
|
|
|
editing = true;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), '');
|
|
|
|
ownerOf = ['refs/*'];
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), 'editing');
|
|
|
|
ownerOf = [];
|
|
canUpload = true;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), 'editing');
|
|
|
|
editingRef = true;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), 'editing editingRef');
|
|
|
|
deleted = true;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), 'editing editingRef deleted');
|
|
|
|
editingRef = false;
|
|
assert.equal(element._computeSectionClass(editing, canUpload, ownerOf,
|
|
editingRef, deleted), 'editing deleted');
|
|
});
|
|
|
|
test('_computeEditBtnClass', () => {
|
|
let name = 'GLOBAL_CAPABILITIES';
|
|
assert.equal(element._computeEditBtnClass(name), 'global');
|
|
name = 'refs/for/*';
|
|
assert.equal(element._computeEditBtnClass(name), '');
|
|
});
|
|
});
|
|
|
|
suite('interactive tests', () => {
|
|
setup(() => {
|
|
element.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',
|
|
},
|
|
default_value: 0,
|
|
},
|
|
};
|
|
});
|
|
suite('Global section', () => {
|
|
setup(() => {
|
|
element.section = {
|
|
id: 'GLOBAL_CAPABILITIES',
|
|
value: {
|
|
permissions: {
|
|
accessDatabase: {
|
|
rules: {},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
element.capabilities = {
|
|
accessDatabase: {
|
|
id: 'accessDatabase',
|
|
name: 'Access Database',
|
|
},
|
|
administrateServer: {
|
|
id: 'administrateServer',
|
|
name: 'Administrate Server',
|
|
},
|
|
batchChangesLimit: {
|
|
id: 'batchChangesLimit',
|
|
name: 'Batch Changes Limit',
|
|
},
|
|
createAccount: {
|
|
id: 'createAccount',
|
|
name: 'Create Account',
|
|
},
|
|
};
|
|
element._updateSection(element.section);
|
|
flushAsynchronousOperations();
|
|
});
|
|
|
|
test('classes are assigned correctly', () => {
|
|
assert.isFalse(element.$.section.classList.contains('editing'));
|
|
assert.isFalse(element.$.section.classList.contains('deleted'));
|
|
assert.isTrue(element.$.editBtn.classList.contains('global'));
|
|
element.editing = true;
|
|
element.canUpload = true;
|
|
element.ownerOf = [];
|
|
assert.equal(getComputedStyle(element.$.editBtn).display, 'none');
|
|
});
|
|
});
|
|
|
|
suite('Non-global section', () => {
|
|
setup(() => {
|
|
element.section = {
|
|
id: 'refs/*',
|
|
value: {
|
|
permissions: {
|
|
read: {
|
|
rules: {},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
element.capabilities = {};
|
|
element._updateSection(element.section);
|
|
flushAsynchronousOperations();
|
|
});
|
|
|
|
test('classes are assigned correctly', () => {
|
|
assert.isFalse(element.$.section.classList.contains('editing'));
|
|
assert.isFalse(element.$.section.classList.contains('deleted'));
|
|
assert.isFalse(element.$.editBtn.classList.contains('global'));
|
|
element.editing = true;
|
|
element.canUpload = true;
|
|
element.ownerOf = [];
|
|
flushAsynchronousOperations();
|
|
assert.notEqual(getComputedStyle(element.$.editBtn).display, 'none');
|
|
});
|
|
|
|
test('add permission', () => {
|
|
element.editing = true;
|
|
element.$.permissionSelect.value = 'label-Code-Review';
|
|
assert.equal(element._permissions.length, 1);
|
|
assert.equal(Object.keys(element.section.value.permissions).length,
|
|
1);
|
|
MockInteractions.tap(element.$.addBtn);
|
|
flushAsynchronousOperations();
|
|
|
|
// The permission is added to both the permissions array and also
|
|
// the section's permission object.
|
|
assert.equal(element._permissions.length, 2);
|
|
let permission = {
|
|
id: 'label-Code-Review',
|
|
value: {
|
|
added: true,
|
|
label: 'Code-Review',
|
|
rules: {},
|
|
},
|
|
};
|
|
assert.equal(element._permissions.length, 2);
|
|
assert.deepEqual(element._permissions[1], permission);
|
|
assert.equal(Object.keys(element.section.value.permissions).length,
|
|
2);
|
|
assert.deepEqual(
|
|
element.section.value.permissions['label-Code-Review'],
|
|
permission.value);
|
|
|
|
element.$.permissionSelect.value = 'abandon';
|
|
MockInteractions.tap(element.$.addBtn);
|
|
flushAsynchronousOperations();
|
|
|
|
permission = {
|
|
id: 'abandon',
|
|
value: {
|
|
added: true,
|
|
rules: {},
|
|
},
|
|
};
|
|
|
|
assert.equal(element._permissions.length, 3);
|
|
assert.deepEqual(element._permissions[2], permission);
|
|
assert.equal(Object.keys(element.section.value.permissions).length,
|
|
3);
|
|
assert.deepEqual(element.section.value.permissions['abandon'],
|
|
permission.value);
|
|
|
|
// Unsaved changes are discarded when editing is cancelled.
|
|
element.editing = false;
|
|
assert.equal(element._permissions.length, 1);
|
|
assert.equal(Object.keys(element.section.value.permissions).length,
|
|
1);
|
|
});
|
|
|
|
test('edit section reference', () => {
|
|
element.canUpload = true;
|
|
element.ownerOf = [];
|
|
element.section = {id: 'refs/for/bar', value: {permissions: {}}};
|
|
assert.isFalse(element.$.section.classList.contains('editing'));
|
|
element.editing = true;
|
|
assert.isTrue(element.$.section.classList.contains('editing'));
|
|
assert.isFalse(element._editingRef);
|
|
MockInteractions.tap(element.$.editBtn);
|
|
element.$.editRefInput.bindValue='new/ref';
|
|
flushAsynchronousOperations();
|
|
assert.equal(element.section.id, 'new/ref');
|
|
assert.isTrue(element._editingRef);
|
|
assert.isTrue(element.$.section.classList.contains('editingRef'));
|
|
element.editing = false;
|
|
assert.isFalse(element._editingRef);
|
|
assert.equal(element.section.id, 'refs/for/bar');
|
|
});
|
|
|
|
test('_handleValueChange', () => {
|
|
// For an exising section.
|
|
const modifiedHandler = sandbox.stub();
|
|
element.section = {id: 'refs/for/bar', value: {permissions: {}}};
|
|
assert.notOk(element.section.value.updatedId);
|
|
element.section.id = 'refs/for/baz';
|
|
element.addEventListener('access-modified', modifiedHandler);
|
|
assert.isNotOk(element.section.value.modified);
|
|
element._handleValueChange();
|
|
assert.equal(element.section.value.updatedId, 'refs/for/baz');
|
|
assert.isTrue(element.section.value.modified);
|
|
assert.equal(modifiedHandler.callCount, 1);
|
|
element.section.id = 'refs/for/bar';
|
|
element._handleValueChange();
|
|
assert.isFalse(element.section.value.modified);
|
|
assert.equal(modifiedHandler.callCount, 2);
|
|
|
|
// For a new section.
|
|
element.section.value.added = true;
|
|
element._handleValueChange();
|
|
assert.isFalse(element.section.value.modified);
|
|
assert.equal(modifiedHandler.callCount, 2);
|
|
element.section.id = 'refs/for/bar';
|
|
element._handleValueChange();
|
|
assert.isFalse(element.section.value.modified);
|
|
assert.equal(modifiedHandler.callCount, 2);
|
|
});
|
|
|
|
test('remove section', () => {
|
|
element.editing = true;
|
|
element.canUpload = true;
|
|
element.ownerOf = [];
|
|
assert.isFalse(element._deleted);
|
|
assert.isNotOk(element.section.value.deleted);
|
|
MockInteractions.tap(element.$.deleteBtn);
|
|
flushAsynchronousOperations();
|
|
assert.isTrue(element._deleted);
|
|
assert.isTrue(element.section.value.deleted);
|
|
assert.isTrue(element.$.section.classList.contains('deleted'));
|
|
assert.isTrue(element.section.value.deleted);
|
|
|
|
MockInteractions.tap(element.$.undoRemoveBtn);
|
|
flushAsynchronousOperations();
|
|
assert.isFalse(element._deleted);
|
|
assert.isNotOk(element.section.value.deleted);
|
|
|
|
MockInteractions.tap(element.$.deleteBtn);
|
|
assert.isTrue(element._deleted);
|
|
assert.isTrue(element.section.value.deleted);
|
|
element.editing = false;
|
|
assert.isFalse(element._deleted);
|
|
assert.isNotOk(element.section.value.deleted);
|
|
});
|
|
|
|
test('removing an added permission', () => {
|
|
element.editing = true;
|
|
assert.equal(element._permissions.length, 1);
|
|
element.$$('gr-permission').fire('added-permission-removed');
|
|
flushAsynchronousOperations();
|
|
assert.equal(element._permissions.length, 0);
|
|
});
|
|
|
|
test('remove an added section', () => {
|
|
const removeStub = sandbox.stub();
|
|
element.addEventListener('added-section-removed', removeStub);
|
|
element.editing = true;
|
|
element.section.value.added = true;
|
|
MockInteractions.tap(element.$.deleteBtn);
|
|
assert.isTrue(removeStub.called);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
</script>
|