Files
gerrit/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.html
Becky Siegel 1610fee6e0 Introduce gr-access-section
This element houses permissions for a particular project access section.

Here is the access hierarchy:

Project access
- Sections  <-- This is the component for this change
  - Permissions
    - Rules

- It has the ability to add new permission, or remove itself (with an undo
  option).
- Permissions that already exist in a particular section will not be
  present in the dropdown options.
- Section references can be re-named, with the exception of the
  'GLOBAL_CAPABILITIES' section

Change-Id: I1044b32551c79f324a4d05baadcab9e12560ea3d
2017-08-23 17:02:58 -07:00

467 lines
15 KiB
HTML

<!DOCTYPE html>
<!--
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._sectionChanged(element.section);
flushAsynchronousOperations();
});
test('_sectionChanged', () => {
// _sectionChanged 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('_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('_handleEditReference', () => {
element._handleEditReference();
assert.isTrue(element._editingRef);
});
test('_undoReferenceEdit', () => {
element._originalId = 'refs/for/old';
element.section.id = 'refs/for/new';
element.editing = true;
element._undoReferenceEdit();
assert.isFalse(element._editingRef);
assert.equal(element.section.id, 'refs/for/old');
});
test('_computeSectionClass', () => {
let editingRef = false;
let editing = false;
let deleted = false;
assert.equal(element._computeSectionClass(editing, editingRef, deleted),
'');
editing = true;
assert.equal(element._computeSectionClass(editing, editingRef, deleted),
'editing');
editingRef = true;
assert.equal(element._computeSectionClass(editing, editingRef, deleted),
'editing editingRef');
deleted = true;
assert.equal(element._computeSectionClass(editing, editingRef, deleted),
'editing editingRef deleted');
editingRef = false;
assert.equal(element._computeSectionClass(editing, 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._sectionChanged(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'));
});
});
suite('Non-global section', () => {
setup(() => {
element.section = {
id: 'refs/*',
value: {
permissions: {
read: {
rules: {},
},
},
},
};
element.capabilities = {};
element._sectionChanged(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'));
});
test('add permission', () => {
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: {
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: {
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);
});
test('edit section reference', () => {
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'));
MockInteractions.tap(element.$.undoEdit);
flushAsynchronousOperations();
assert.isFalse(element._editingRef);
assert.isFalse(element.$.section.classList.contains('editingRef'));
assert.equal(element.section.id, 'refs/*');
});
test('remove section', () => {
element.editing = true;
assert.isFalse(element._deleted);
MockInteractions.tap(element.$.deleteBtn);
flushAsynchronousOperations();
assert.isTrue(element._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);
});
});
});
});
</script>