blob: 2909694a0be6605343a5b54e5eb01e3df9542faa [file] [log] [blame]
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as sinon from 'sinon';
import '../../../test/common-test-setup';
import './gr-permission';
import {GrPermission} from './gr-permission';
import {query, stubRestApi, waitEventLoop} from '../../../test/test-utils';
import {GitRef, GroupId, GroupName} from '../../../types/common';
import {PermissionAction} from '../../../constants/constants';
import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
import {queryAndAssert} from '../../../test/test-utils';
import {GrRuleEditor} from '../gr-rule-editor/gr-rule-editor';
import {GrButton} from '../../shared/gr-button/gr-button';
import {fixture, html, assert} from '@open-wc/testing';
import {PaperToggleButtonElement} from '@polymer/paper-toggle-button';
import {AutocompleteCommitEventDetail} from '../../../types/events';
suite('gr-permission tests', () => {
let element: GrPermission;
setup(async () => {
element = await fixture(html`<gr-permission></gr-permission>`);
stubRestApi('getSuggestedGroups').returns(
Promise.resolve({
Administrators: {
id: '4c97682e6ce61b7247f3381b6f1789356666de7f' as GroupId,
},
'Anonymous Users': {
id: 'global%3AAnonymous-Users' as GroupId,
},
})
);
});
suite('unit tests', () => {
test('sortPermission', async () => {
const permission = {
id: 'submit' as GitRef,
value: {
rules: {
'global:Project-Owners': {
action: PermissionAction.ALLOW,
force: false,
},
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
action: PermissionAction.ALLOW,
force: false,
},
},
},
};
const expectedRules = [
{
id: '4c97682e6ce6b7247f3381b6f1789356666de7f' as GitRef,
value: {action: PermissionAction.ALLOW, force: false},
},
{
id: 'global:Project-Owners' as GitRef,
value: {action: PermissionAction.ALLOW, force: false},
},
];
element.sortPermission(permission);
await element.updateComplete;
assert.deepEqual(element.rules, expectedRules);
});
test('computeLabel and computeLabelValues', async () => {
const labels = {
'Code-Review': {
default_value: 0,
values: {
' 0': 'No score',
'-1': 'I would prefer this is not submitted as is',
'-2': 'This shall not be submitted',
'+1': 'Looks good to me, but someone else must approve',
'+2': 'Looks good to me, approved',
},
},
};
let permission = {
id: 'label-Code-Review' as GitRef,
value: {
label: 'Code-Review',
rules: {
'global:Project-Owners': {
action: PermissionAction.ALLOW,
force: false,
min: -2,
max: 2,
},
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
action: PermissionAction.ALLOW,
force: false,
min: -2,
max: 2,
},
},
},
};
const expectedLabelValues = [
{value: -2, text: 'This shall not be submitted'},
{value: -1, text: 'I would prefer this is not submitted as is'},
{value: 0, text: 'No score'},
{value: 1, text: 'Looks good to me, but someone else must approve'},
{value: 2, text: 'Looks good to me, approved'},
];
const expectedLabel = {
name: 'Code-Review',
values: expectedLabelValues,
};
element.permission = permission;
element.labels = labels;
await element.updateComplete;
assert.deepEqual(
element.computeLabelValues(labels['Code-Review'].values),
expectedLabelValues
);
assert.deepEqual(element.computeLabel(), expectedLabel);
permission = {
id: 'label-reviewDB' as GitRef,
value: {
label: 'reviewDB',
rules: {
'global:Project-Owners': {
action: PermissionAction.ALLOW,
force: false,
min: 0,
max: 0,
},
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
action: PermissionAction.ALLOW,
force: false,
min: 0,
max: 0,
},
},
},
};
element.permission = permission;
await element.updateComplete;
assert.isNotOk(element.computeLabel());
});
test('computeSectionClass', async () => {
let deleted = true;
let editing = false;
assert.equal(element.computeSectionClass(editing, deleted), 'deleted');
deleted = false;
assert.equal(element.computeSectionClass(editing, deleted), '');
editing = true;
assert.equal(element.computeSectionClass(editing, deleted), 'editing');
deleted = true;
assert.equal(
element.computeSectionClass(editing, deleted),
'editing deleted'
);
});
test('computeGroupName', async () => {
const groups = {
abc123: {id: '1' as GroupId, name: 'test group' as GroupName},
bcd234: {id: '1' as GroupId},
};
assert.equal(
element.computeGroupName(groups, 'abc123' as GitRef),
'test group' as GroupName
);
assert.equal(
element.computeGroupName(groups, 'bcd234' as GitRef),
'bcd234' as GroupName
);
});
test('computeGroupsWithRules', async () => {
const rules = [
{
id: '4c97682e6ce6b7247f3381b6f1789356666de7f' as GitRef,
value: {action: PermissionAction.ALLOW, force: false},
},
{
id: 'global:Project-Owners' as GitRef,
value: {action: PermissionAction.ALLOW, force: false},
},
];
const groupsWithRules = {
'4c97682e6ce6b7247f3381b6f1789356666de7f': true,
'global:Project-Owners': true,
};
assert.deepEqual(element.computeGroupsWithRules(rules), groupsWithRules);
});
test('getGroupSuggestions without existing rules', async () => {
element.groupsWithRules = {};
await element.updateComplete;
const groups = await element.getGroupSuggestions();
assert.deepEqual(groups, [
{
name: 'Administrators',
value: '4c97682e6ce61b7247f3381b6f1789356666de7f',
},
{
name: 'Anonymous Users',
value: 'global%3AAnonymous-Users',
},
]);
});
test('getGroupSuggestions with existing rules filters them', async () => {
element.groupsWithRules = {
'4c97682e6ce61b7247f3381b6f1789356666de7f': true,
};
await element.updateComplete;
const groups = await element.getGroupSuggestions();
assert.deepEqual(groups, [
{
name: 'Anonymous Users',
value: 'global%3AAnonymous-Users',
},
]);
});
test('handleRemovePermission', async () => {
element.editing = true;
element.permission = {id: 'test' as GitRef, value: {rules: {}}};
element.handleRemovePermission();
await element.updateComplete;
assert.isTrue(element.deleted);
assert.isTrue(element.permission.value.deleted);
element.editing = false;
await element.updateComplete;
assert.isFalse(element.deleted);
assert.isNotOk(element.permission.value.deleted);
});
test('handleUndoRemove', async () => {
element.permission = {
id: 'test' as GitRef,
value: {deleted: true, rules: {}},
};
element.handleUndoRemove();
await element.updateComplete;
assert.isFalse(element.deleted);
assert.isNotOk(element.permission.value.deleted);
});
test('computeHasRange', async () => {
assert.isTrue(element.computeHasRange('Query Limit'));
assert.isTrue(element.computeHasRange('Batch Changes Limit'));
assert.isFalse(element.computeHasRange('test'));
});
});
suite('interactions', () => {
setup(async () => {
sinon.spy(element, 'computeLabel');
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
element.labels = {
'Code-Review': {
values: {
' 0': 'No score',
'-1': 'I would prefer this is not submitted as is',
'-2': 'This shall not be submitted',
'+1': 'Looks good to me, but someone else must approve',
'+2': 'Looks good to me, approved',
},
default_value: 0,
},
};
element.permission = {
id: 'label-Code-Review' as GitRef,
value: {
label: 'Code-Review',
rules: {
'global:Project-Owners': {
action: PermissionAction.ALLOW,
force: false,
min: -2,
max: 2,
},
'4c97682e6ce6b7247f3381b6f1789356666de7f': {
action: PermissionAction.ALLOW,
force: false,
min: -2,
max: 2,
},
},
},
};
element.setupValues();
await element.updateComplete;
await waitEventLoop();
});
test('render', () => {
assert.shadowDom.equal(
element,
/* HTML */ `
<section class="gr-form-styles" id="permission">
<div id="mainContainer">
<div class="header">
<span class="title"> Priority </span>
<div class="right">
<paper-toggle-button
aria-disabled="true"
aria-pressed="false"
disabled=""
id="exclusiveToggle"
role="button"
style="pointer-events: none; touch-action: none;"
tabindex="-1"
toggles=""
>
</paper-toggle-button>
Not Exclusive
<gr-button
aria-disabled="false"
id="removeBtn"
link=""
role="button"
tabindex="0"
>
Remove
</gr-button>
</div>
</div>
<div class="rules">
<gr-rule-editor> </gr-rule-editor>
<gr-rule-editor> </gr-rule-editor>
<div id="addRule">
<gr-autocomplete
id="groupAutocomplete"
placeholder="Add group"
>
</gr-autocomplete>
</div>
</div>
</div>
<div id="deletedContainer">
<span> Priority was deleted </span>
<gr-button
aria-disabled="false"
id="undoRemoveBtn"
link=""
role="button"
tabindex="0"
>
Undo
</gr-button>
</div>
</section>
`,
// touch-action varies on paper-toggle-button between local and CI
{
ignoreAttributes: [
{tags: ['paper-toggle-button'], attributes: ['style']},
],
}
);
});
test('adding a rule', async () => {
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
element.groups = {};
await element.updateComplete;
queryAndAssert<GrAutocomplete>(element, '#groupAutocomplete').text =
'ldap/tests te.st';
const e = {
detail: {
value: 'ldap:CN=test+te.st',
},
} as CustomEvent<AutocompleteCommitEventDetail>;
element.editing = true;
assert.equal(element.rules!.length, 2);
assert.equal(Object.keys(element.groupsWithRules!).length, 2);
await element.handleAddRuleItem(e);
assert.deepEqual(element.groups, {
'ldap:CN=test te.st': {
name: 'ldap/tests te.st',
},
});
assert.equal(element.rules!.length, 3);
assert.equal(Object.keys(element.groupsWithRules!).length, 3);
assert.deepEqual(element.permission!.value.rules['ldap:CN=test te.st'], {
action: PermissionAction.ALLOW,
min: -2,
max: 2,
added: true,
});
assert.equal(
queryAndAssert<GrAutocomplete>(element, '#groupAutocomplete').text,
''
);
// New rule should be removed if cancel from editing.
element.editing = false;
await element.updateComplete;
assert.equal(element.rules!.length, 2);
assert.equal(Object.keys(element.permission!.value.rules).length, 2);
});
test('removing an added rule', async () => {
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
element.groups = {};
await element.updateComplete;
queryAndAssert<GrAutocomplete>(element, '#groupAutocomplete').text =
'new group name';
assert.equal(element.rules!.length, 2);
queryAndAssert<GrRuleEditor>(element, 'gr-rule-editor').dispatchEvent(
new CustomEvent('added-rule-removed', {
composed: true,
bubbles: true,
})
);
await waitEventLoop();
assert.equal(element.rules!.length, 1);
});
test('removing an added permission', async () => {
const removeStub = sinon.stub();
element.addEventListener('added-permission-removed', removeStub);
element.editing = true;
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
element.permission!.value.added = true;
await element.updateComplete;
queryAndAssert<GrButton>(element, '#removeBtn').click();
await element.updateComplete;
assert.isTrue(removeStub.called);
});
test('removing the permission', async () => {
element.editing = true;
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
await element.updateComplete;
const removeStub = sinon.stub();
element.addEventListener('added-permission-removed', removeStub);
assert.isFalse(
queryAndAssert(element, '#permission').classList.contains('deleted')
);
assert.isFalse(element.deleted);
queryAndAssert<GrButton>(element, '#removeBtn').click();
await element.updateComplete;
assert.isTrue(
queryAndAssert(element, '#permission').classList.contains('deleted')
);
assert.isTrue(element.deleted);
queryAndAssert<GrButton>(element, '#undoRemoveBtn').click();
await element.updateComplete;
assert.isFalse(
queryAndAssert(element, '#permission').classList.contains('deleted')
);
assert.isFalse(element.deleted);
assert.isFalse(removeStub.called);
});
test('modify a permission', async () => {
element.editing = true;
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
await element.updateComplete;
assert.isFalse(element.originalExclusiveValue);
assert.isNotOk(element.permission!.value.modified);
queryAndAssert<PaperToggleButtonElement>(
element,
'#exclusiveToggle'
).click();
await element.updateComplete;
assert.isTrue(element.permission!.value.exclusive);
assert.isTrue(element.permission!.value.modified);
assert.isFalse(element.originalExclusiveValue);
element.editing = false;
await element.updateComplete;
assert.isFalse(element.permission!.value.exclusive);
});
test('modifying emits access-modified event', async () => {
const modifiedHandler = sinon.stub();
element.editing = true;
element.name = 'Priority';
element.section = 'refs/*' as GitRef;
element.permission = {id: '0' as GitRef, value: {rules: {}}};
element.addEventListener('access-modified', modifiedHandler);
await element.updateComplete;
assert.isNotOk(element.permission.value.modified);
queryAndAssert<PaperToggleButtonElement>(
element,
'#exclusiveToggle'
).click();
await element.updateComplete;
assert.isTrue(element.permission.value.modified);
assert.isTrue(modifiedHandler.called);
});
test('Exclusive hidden for owner permission', async () => {
queryAndAssert(element, '#exclusiveToggle');
element.permission!.id = 'owner' as GitRef;
element.requestUpdate();
await element.updateComplete;
assert.notOk(query(element, '#exclusiveToggle'));
});
test('Exclusive hidden for any global permissions', async () => {
queryAndAssert(element, '#exclusiveToggle');
element.section = 'GLOBAL_CAPABILITIES' as GitRef;
await element.updateComplete;
assert.notOk(query(element, '#exclusiveToggle'));
});
});
});