Introduce gr-rule-editor
This is the most granular component in the project access editor.
It allows the user to modify the value of a particular rule.
Here is the access hierarchy:
Project access
- Sections
- Permissions
- Rules <-- This is the component for this change.
It will be fed in the group, permission, optional labels, ruls, and
section from its parent(s).
There are a variety of different ways this can behave that are outlined
in the tests. Generally they are:
- Some permission types have different option values
- When there are label options, they should be presented
- Some permission types should display a push option, and their labels
vary based on whether it is an edit or a push.
Change-Id: Iaf0aab09418c4e2589753419d82c375d8d5cf673
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../../../styles/gr-form-styles.html">
|
||||
<link rel="import" href="../../../styles/shared-styles.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-select/gr-select.html">
|
||||
|
||||
<dom-module id="gr-rule-editor">
|
||||
<template>
|
||||
<style include="shared-styles">
|
||||
:host {
|
||||
border-bottom: 1px solid #d1d2d3;
|
||||
padding: .7em;
|
||||
display: block;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
}
|
||||
.buttons gr-button {
|
||||
margin-left: .3em;
|
||||
}
|
||||
#mainContainer {
|
||||
align-items: baseline;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.buttons gr-button {
|
||||
float: left;
|
||||
margin-left: .3em;
|
||||
}
|
||||
#undoBtn,
|
||||
#force,
|
||||
#deletedContainer,
|
||||
#mainContainer.deleted {
|
||||
display: none;
|
||||
}
|
||||
#undoBtn.modified,
|
||||
#force.force,
|
||||
#deletedContainer.deleted {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<style include="gr-form-styles"></style>
|
||||
<div id="mainContainer"
|
||||
class$="gr-form-styles [[_computeDeletedClass(_deleted)]]">
|
||||
<div id="options">
|
||||
<gr-select id="action"
|
||||
bind-value="{{rule.value.action}}"
|
||||
on-change="_handleValueChange">
|
||||
<select>
|
||||
<template is="dom-repeat" items="[[_computeOptions(permission)]]">
|
||||
<option value="[[item]]">[[item]]</option>
|
||||
</template>
|
||||
</select>
|
||||
</gr-select>
|
||||
<template is="dom-if" if="[[label]]">
|
||||
<gr-select
|
||||
id="labelMin"
|
||||
bind-value="{{rule.value.min}}"
|
||||
on-change="_handleValueChange">
|
||||
<select>
|
||||
<template is="dom-repeat" items="[[label.values]]">
|
||||
<option value="[[item.value]]">[[item.value]]</option>
|
||||
</template>
|
||||
</select>
|
||||
</gr-select>
|
||||
<gr-select
|
||||
id="labelMax"
|
||||
bind-value="{{rule.value.max}}"
|
||||
on-change="_handleValueChange">
|
||||
<select>
|
||||
<template is="dom-repeat" items="[[label.values]]">
|
||||
<option value="[[item.value]]">[[item.value]]</option>
|
||||
</template>
|
||||
</select>
|
||||
</gr-select>
|
||||
</template>
|
||||
[[group]]
|
||||
<gr-select
|
||||
id="force"
|
||||
class$="[[_computeForceClass(permission)]]"
|
||||
bind-value="{{rule.value.force}}"
|
||||
on-change="_handleValueChange">
|
||||
<select>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_computeForceOptions(permission)]]">
|
||||
<option value="[[item.value]]">[[item.name]]</option>
|
||||
</template>
|
||||
</select>
|
||||
</gr-select>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<gr-button
|
||||
id="undoBtn"
|
||||
on-tap="_handleUndoChange"
|
||||
class$="[[_computeModifiedClass(_modified)]]">Undo</gr-button>
|
||||
<gr-button id="removeBtn" on-tap="_handleRemoveRule">Remove</gr-button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="deletedContainer"
|
||||
class$="gr-form-styles [[_computeDeletedClass(_deleted)]]">
|
||||
[[group]] was deleted
|
||||
<gr-button id="undoRemoveBtn" on-tap="_handleUndoRemove">Undo</gr-button>
|
||||
</div>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
</template>
|
||||
<script src="gr-rule-editor.js"></script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,169 @@
|
||||
// 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.
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const PRIORITY_OPTIONS = [
|
||||
'BATCH',
|
||||
'INTERACTIVE',
|
||||
];
|
||||
|
||||
const DROPDOWN_OPTIONS = [
|
||||
'ALLOW',
|
||||
'DENY',
|
||||
'BLOCK',
|
||||
];
|
||||
|
||||
const FORCE_PUSH_OPTIONS = [
|
||||
{
|
||||
name: 'No Force Push',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
name: 'Force Push',
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
const FORCE_EDIT_OPTIONS = [
|
||||
{
|
||||
name: 'No Force Edit',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
name: 'Force Edit',
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
Polymer({
|
||||
is: 'gr-rule-editor',
|
||||
|
||||
properties: {
|
||||
/** @type {?} */
|
||||
label: Object,
|
||||
group: String,
|
||||
permission: String,
|
||||
/** @type {?} */
|
||||
rule: {
|
||||
type: Object,
|
||||
notify: true,
|
||||
},
|
||||
section: String,
|
||||
_modified: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
_originalRuleValues: Object,
|
||||
_deleted: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
observers: [
|
||||
'_handleValueChange(rule.value.*)',
|
||||
],
|
||||
|
||||
ready() {
|
||||
// Called on ready rather than the observer because when new rules are
|
||||
// added, the observer is triggered prior to being ready.
|
||||
if (!this.rule) { return; } // Check needed for test purposes.
|
||||
this._setupValues(this.rule);
|
||||
},
|
||||
|
||||
_setupValues(rule) {
|
||||
if (!rule.value) {
|
||||
this._setDefaultRuleValues();
|
||||
}
|
||||
this._setOriginalRuleValues(rule.value);
|
||||
},
|
||||
|
||||
_computeForce(permission) {
|
||||
return 'push' === permission || 'editTopicName' === permission;
|
||||
},
|
||||
|
||||
_computeForceClass(permission) {
|
||||
return this._computeForce(permission) ? 'force' : '';
|
||||
},
|
||||
|
||||
_computeDeletedClass(deleted) {
|
||||
return deleted ? 'deleted' : '';
|
||||
},
|
||||
|
||||
_computeForceOptions(permission) {
|
||||
if (permission === 'push') {
|
||||
return FORCE_PUSH_OPTIONS;
|
||||
} else if (permission === 'editTopicName') {
|
||||
return FORCE_EDIT_OPTIONS;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
_getDefaultRuleValues(permission, label) {
|
||||
const value = {};
|
||||
if (permission === 'priority') {
|
||||
value.action = PRIORITY_OPTIONS[0];
|
||||
return value;
|
||||
} else if (label) {
|
||||
value.min = label.values[0].value;
|
||||
value.max = label.values[label.values.length - 1].value;
|
||||
} else if (this._computeForce(permission)) {
|
||||
value.force = this._computeForceOptions(permission)[0].value;
|
||||
}
|
||||
value.action = DROPDOWN_OPTIONS[0];
|
||||
return value;
|
||||
},
|
||||
|
||||
_setDefaultRuleValues() {
|
||||
this.set('rule.value',
|
||||
this._getDefaultRuleValues(this.permission, this.label));
|
||||
},
|
||||
|
||||
_computeOptions(permission) {
|
||||
if (permission === 'priority') {
|
||||
return PRIORITY_OPTIONS;
|
||||
}
|
||||
return DROPDOWN_OPTIONS;
|
||||
},
|
||||
|
||||
_handleRemoveRule() {
|
||||
this._deleted = true;
|
||||
this.rule.deleted = true;
|
||||
},
|
||||
|
||||
_handleUndoRemove() {
|
||||
this._deleted = false;
|
||||
delete this.rule.deleted;
|
||||
},
|
||||
|
||||
_handleUndoChange() {
|
||||
this.set('rule.value', Object.assign({}, this._originalRuleValues));
|
||||
this._modified = false;
|
||||
},
|
||||
|
||||
_handleValueChange() {
|
||||
if (!this._originalRuleValues) { return; }
|
||||
this._modified = true;
|
||||
},
|
||||
|
||||
_setOriginalRuleValues(value) {
|
||||
this._originalRuleValues = Object.assign({}, value);
|
||||
},
|
||||
|
||||
_computeModifiedClass(modified) {
|
||||
return modified ? 'modified' : '';
|
||||
},
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,571 @@
|
||||
<!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-rule-editor</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-rule-editor.html">
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<gr-rule-editor></gr-rule-editor>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-rule-editor tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
suite('unit tests', () => {
|
||||
test('_computeForce, _computeForceClass, and _computeForceOptions',
|
||||
() => {
|
||||
const FORCE_PUSH_OPTIONS = [
|
||||
{
|
||||
name: 'No Force Push',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
name: 'Force Push',
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
const FORCE_EDIT_OPTIONS = [
|
||||
{
|
||||
name: 'No Force Edit',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
name: 'Force Edit',
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
let permission = 'push';
|
||||
assert.isTrue(element._computeForce(permission));
|
||||
assert.equal(element._computeForceClass(permission), 'force');
|
||||
assert.deepEqual(element._computeForceOptions(permission),
|
||||
FORCE_PUSH_OPTIONS);
|
||||
permission = 'editTopicName';
|
||||
assert.isTrue(element._computeForce(permission));
|
||||
assert.equal(element._computeForceClass(permission), 'force');
|
||||
assert.deepEqual(element._computeForceOptions(permission),
|
||||
FORCE_EDIT_OPTIONS);
|
||||
permission = 'submit';
|
||||
assert.isFalse(element._computeForce(permission));
|
||||
assert.equal(element._computeForceClass(permission), '');
|
||||
assert.deepEqual(element._computeForceOptions(permission), []);
|
||||
});
|
||||
|
||||
test('_computeDeletedClass', () => {
|
||||
assert.equal(element._computeDeletedClass(true), 'deleted');
|
||||
assert.equal(element._computeDeletedClass(false), '');
|
||||
});
|
||||
|
||||
test('_getDefaultRuleValues', () => {
|
||||
let permission = 'priority';
|
||||
let label;
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'BATCH'});
|
||||
permission = 'label-Code-Review';
|
||||
label = {values: [
|
||||
{value: -2, text: 'This shall not be merged'},
|
||||
{value: -1, text: 'I would prefer this is not merged 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'},
|
||||
]};
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'ALLOW', max: 2, min: -2});
|
||||
permission = 'push';
|
||||
label = undefined;
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'ALLOW', force: false});
|
||||
permission = 'submit';
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'ALLOW'});
|
||||
});
|
||||
|
||||
test('_setDefaultRuleValues', () => {
|
||||
element.rule = {id: 123};
|
||||
const defaultValue = {action: 'ALLOW'};
|
||||
sandbox.stub(element, '_getDefaultRuleValues').returns(defaultValue);
|
||||
element._setDefaultRuleValues();
|
||||
assert.isTrue(element._getDefaultRuleValues.called);
|
||||
assert.equal(element.rule.value, defaultValue);
|
||||
});
|
||||
|
||||
test('_computeOptions', () => {
|
||||
const PRIORITY_OPTIONS = [
|
||||
'BATCH',
|
||||
'INTERACTIVE',
|
||||
];
|
||||
const DROPDOWN_OPTIONS = [
|
||||
'ALLOW',
|
||||
'DENY',
|
||||
'BLOCK',
|
||||
];
|
||||
let permission = 'priority';
|
||||
assert.deepEqual(element._computeOptions(permission), PRIORITY_OPTIONS);
|
||||
permission = 'submit';
|
||||
assert.deepEqual(element._computeOptions(permission), DROPDOWN_OPTIONS);
|
||||
});
|
||||
|
||||
test('_handleValueChange', () => {
|
||||
element._handleValueChange();
|
||||
assert.isFalse(element._modified);
|
||||
element._originalRuleValues = {};
|
||||
element._handleValueChange();
|
||||
assert.isTrue(element._modified);
|
||||
});
|
||||
|
||||
test('_setOriginalRuleValues', () => {
|
||||
const value = {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
};
|
||||
element._setOriginalRuleValues(value);
|
||||
assert.deepEqual(element._originalRuleValues, value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('already existing generic rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'submit';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
value: {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
},
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
|
||||
// Typically called on ready since elements will have properies defined
|
||||
// by the parent element.
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMin'));
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMax'));
|
||||
assert.isFalse(element.$.force.classList.contains('force'));
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.action.bindValue = 'DENY';
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
assert.equal(element.$.action.bindValue, 'ALLOW');
|
||||
assert.isFalse(element._modified);
|
||||
});
|
||||
|
||||
test('remove rule and undo remove', () => {
|
||||
element.rule = {id: 123};
|
||||
assert.isFalse(
|
||||
element.$.deletedContainer.classList.contains('deleted'));
|
||||
MockInteractions.tap(element.$.removeBtn);
|
||||
assert.isTrue(element.$.deletedContainer.classList.contains('deleted'));
|
||||
assert.isTrue(element.rule.deleted);
|
||||
|
||||
MockInteractions.tap(element.$.undoRemoveBtn);
|
||||
assert.isNotOk(element.rule.deleted);
|
||||
});
|
||||
});
|
||||
|
||||
suite('new edit rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'editTopicName';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
// Since the element does not already have default values, they should
|
||||
// be set. The original values should be set to those too.
|
||||
assert.isFalse(element._modified);
|
||||
const expectedRuleValue = {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
};
|
||||
assert.deepEqual(element.rule.value, expectedRuleValue);
|
||||
assert.deepEqual(element._originalRuleValues, expectedRuleValue);
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(element.$.action.bindValue, expectedRuleValue.action);
|
||||
assert.equal(element.$.force.bindValue, expectedRuleValue.action);
|
||||
});
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.force.bindValue = true;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('already existing rule with labels', () => {
|
||||
setup(() => {
|
||||
element.label = {values: [
|
||||
{value: -2, text: 'This shall not be merged'},
|
||||
{value: -1, text: 'I would prefer this is not merged 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'},
|
||||
]};
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'label-Code-Review';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
value: {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
max: 2,
|
||||
min: -2,
|
||||
},
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#labelMin').bindValue,
|
||||
element.rule.value.min);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#labelMax').bindValue,
|
||||
element.rule.value.max);
|
||||
assert.isFalse(element.$.force.classList.contains('force'));
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
Polymer.dom(element.root).querySelector('#labelMin').bindValue = 1;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('new rule with labels', () => {
|
||||
setup(() => {
|
||||
sandbox.spy(element, '_setDefaultRuleValues');
|
||||
element.label = {values: [
|
||||
{value: -2, text: 'This shall not be merged'},
|
||||
{value: -1, text: 'I would prefer this is not merged 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'},
|
||||
]};
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'label-Code-Review';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
// Since the element does not already have default values, they should
|
||||
// be set. The original values should be set to those too.
|
||||
assert.isFalse(element._modified);
|
||||
assert.isTrue(element._setDefaultRuleValues.called);
|
||||
|
||||
const expectedRuleValue = {
|
||||
max: element.label.values[element.label.values.length - 1].value,
|
||||
min: element.label.values[0].value,
|
||||
action: 'ALLOW',
|
||||
};
|
||||
assert.deepEqual(element.rule.value, expectedRuleValue);
|
||||
assert.deepEqual(element._originalRuleValues, expectedRuleValue);
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(
|
||||
element.$.action.bindValue,
|
||||
expectedRuleValue.action);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#labelMin').bindValue,
|
||||
expectedRuleValue.min);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#labelMax').bindValue,
|
||||
expectedRuleValue.max);
|
||||
});
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
Polymer.dom(element.root).querySelector('#labelMin').bindValue = 1;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('already existing push rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'push';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
value: {
|
||||
action: 'ALLOW',
|
||||
force: true,
|
||||
},
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
|
||||
test('values are set correctly', () => {
|
||||
assert.isTrue(element.$.force.classList.contains('force'));
|
||||
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#force').bindValue,
|
||||
element.rule.value.force);
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMin'));
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMax'));
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.action.bindValue = false;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('new push rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'push';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
// Since the element does not already have default values, they should
|
||||
// be set. The original values should be set to those too.
|
||||
assert.isFalse(element._modified);
|
||||
const expectedRuleValue = {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
};
|
||||
assert.deepEqual(element.rule.value, expectedRuleValue);
|
||||
assert.deepEqual(element._originalRuleValues, expectedRuleValue);
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(element.$.action.bindValue, expectedRuleValue.action);
|
||||
assert.equal(element.$.force.bindValue, expectedRuleValue.action);
|
||||
});
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.force.bindValue = true;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('already existing edit rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'editTopicName';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
value: {
|
||||
action: 'ALLOW',
|
||||
force: true,
|
||||
},
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
|
||||
test('values are set correctly', () => {
|
||||
assert.isTrue(element.$.force.classList.contains('force'));
|
||||
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
||||
assert.equal(
|
||||
Polymer.dom(element.root).querySelector('#force').bindValue,
|
||||
element.rule.value.force);
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMin'));
|
||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMax'));
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.action.bindValue = false;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
|
||||
suite('new edit rule', () => {
|
||||
setup(() => {
|
||||
element.group = 'Group Name';
|
||||
element.permission = 'editTopicName';
|
||||
element.rule = {
|
||||
id: '123',
|
||||
};
|
||||
element.section = 'refs/*';
|
||||
element._setupValues(element.rule);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('_ruleValues and _originalRuleValues are set correctly', () => {
|
||||
// Since the element does not already have default values, they should
|
||||
// be set. The original values should be set to those too.
|
||||
assert.isFalse(element._modified);
|
||||
const expectedRuleValue = {
|
||||
action: 'ALLOW',
|
||||
force: false,
|
||||
};
|
||||
assert.deepEqual(element.rule.value, expectedRuleValue);
|
||||
assert.deepEqual(element._originalRuleValues, expectedRuleValue);
|
||||
test('values are set correctly', () => {
|
||||
assert.equal(element.$.action.bindValue, expectedRuleValue.action);
|
||||
assert.equal(element.$.force.bindValue, expectedRuleValue.action);
|
||||
});
|
||||
});
|
||||
|
||||
test('modify and undo value', () => {
|
||||
assert.isFalse(element._modified);
|
||||
assert.isFalse(element.$.undoBtn.classList.contains('modified'));
|
||||
element.$.force.bindValue = true;
|
||||
flushAsynchronousOperations();
|
||||
assert.isTrue(element._modified);
|
||||
assert.isTrue(element.$.undoBtn.classList.contains('modified'));
|
||||
|
||||
// The original value should now differ from the rule values.
|
||||
assert.notDeepEqual(element._originalRuleValues, element.rule.value);
|
||||
|
||||
// After undoing the change, the original value should get reset.
|
||||
MockInteractions.tap(element.$.undoBtn);
|
||||
assert.deepEqual(element._originalRuleValues, element.rule.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -43,6 +43,7 @@ limitations under the License.
|
||||
'admin/gr-plugin-list/gr-plugin-list_test.html',
|
||||
'admin/gr-project/gr-project_test.html',
|
||||
'admin/gr-project-detail-list/gr-project-detail-list_test.html',
|
||||
'admin/gr-rule-editor/gr-rule-editor_test.html',
|
||||
'change-list/gr-change-list-item/gr-change-list-item_test.html',
|
||||
'change-list/gr-change-list-view/gr-change-list-view_test.html',
|
||||
'change-list/gr-change-list/gr-change-list_test.html',
|
||||
|
||||
Reference in New Issue
Block a user