| /** |
| * @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')); |
| }); |
| }); |
| }); |