Merge "Merge branch 'stable-2.14' into stable-2.15" into stable-2.15
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index c373cbc..4234ab2 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -34,10 +34,10 @@
== Getting started
To get started with the development of a plugin clone the sample
-plugin:
+plugins:
----
-$ git clone https://gerrit.googlesource.com/plugins/cookbook-plugin
+$ git clone https://gerrit.googlesource.com/plugins/examples
----
This is a project that demonstrates the various features of the
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
index 4de9a95..a76904e 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
@@ -117,7 +117,7 @@
<td>[[item.email]]</td>
<td class="deleteColumn">
<gr-button
- class="deleteButton"
+ class="deleteMembersButton"
on-tap="_handleDeleteMember">
Delete
</gr-button>
@@ -132,7 +132,8 @@
<span class="value">
<gr-autocomplete
id="includedGroupSearchInput"
- text="{{_includedGroupSearch}}"
+ text="{{_includedGroupSearchName}}"
+ value="{{_includedGroupSearchId}}"
query="[[_queryIncludedGroup]]"
placeholder="Group Name">
</gr-autocomplete>
@@ -140,7 +141,7 @@
<gr-button
id="saveIncludedGroups"
on-tap="_handleSavingIncludedGroups"
- disabled="[[!_includedGroupSearch]]">
+ disabled="[[!_includedGroupSearchId]]">
Add
</gr-button>
<table id="includedGroups">
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
index 5257e69..14ffa8b 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
@@ -27,7 +27,8 @@
groupId: Number,
_groupMemberSearchId: String,
_groupMemberSearchName: String,
- _includedGroupSearch: String,
+ _includedGroupSearchId: String,
+ _includedGroupSearchName: String,
_loading: {
type: Boolean,
value: true,
@@ -136,6 +137,7 @@
this.$.restAPI.getGroupMembers(this._groupName).then(members => {
this._groupMembers = members;
});
+ this._groupMemberSearchName = '';
this._groupMemberSearchId = '';
});
},
@@ -155,9 +157,9 @@
});
} else if (this._itemType === 'includedGroup') {
return this.$.restAPI.deleteIncludedGroup(this._groupName,
- this._itemName)
+ this._itemId)
.then(itemDeleted => {
- if (itemDeleted.status === 204) {
+ if (itemDeleted.status === 204 || itemDeleted.status === 205) {
this.$.restAPI.getIncludedGroup(this._groupName)
.then(includedGroup => {
this._includedGroups = includedGroup;
@@ -188,7 +190,7 @@
_handleSavingIncludedGroups() {
return this.$.restAPI.saveIncludedGroup(this._groupName,
- this._includedGroupSearch, err => {
+ this._includedGroupSearchId, err => {
if (err.status === 404) {
this.dispatchEvent(new CustomEvent('show-alert', {
detail: {message: SAVING_ERROR_TEXT},
@@ -206,16 +208,18 @@
.then(includedGroup => {
this._includedGroups = includedGroup;
});
- this._includedGroupSearch = '';
+ this._includedGroupSearchName = '';
+ this._includedGroupSearchId = '';
});
},
_handleDeleteIncludedGroup(e) {
+ const id = decodeURIComponent(e.model.get('item.id'));
const name = e.model.get('item.name');
- if (!name) {
- return '';
- }
- this._itemName = name;
+ const item = name || id;
+ if (!item) { return ''; }
+ this._itemName = item;
+ this._itemId = id;
this._itemType = 'includedGroup';
this.$.overlay.open();
},
@@ -252,7 +256,7 @@
if (!response.hasOwnProperty(key)) { continue; }
groups.push({
name: key,
- value: response[key],
+ value: decodeURIComponent(response[key].id),
});
}
return groups;
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
index d670d4d..9d7a797 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
@@ -114,6 +114,20 @@
return Promise.resolve({});
}
},
+ getSuggestedGroups(input) {
+ if (input.startsWith('test')) {
+ return Promise.resolve({
+ 'test-admin': {
+ id: '1ce023d3fb4e4260776fb92cd08b52bbd21ce70a',
+ },
+ 'test/Administrator (admin)': {
+ id: 'test%3Aadmin',
+ },
+ });
+ } else {
+ return Promise.resolve({});
+ }
+ },
getLoggedIn() { return Promise.resolve(true); },
getConfig() {
return Promise.resolve();
@@ -156,7 +170,7 @@
'https://test/site/group/url');
});
- test('save correctly', () => {
+ test('save members correctly', () => {
element._groupOwner = true;
const memberName = 'test-admin';
@@ -166,7 +180,7 @@
return Promise.resolve({});
});
- const button = Polymer.dom(element.root).querySelector('gr-button');
+ const button = element.$.saveGroupMember;
assert.isTrue(button.hasAttribute('disabled'));
@@ -183,6 +197,33 @@
});
});
+ test('save included groups correctly', () => {
+ element._groupOwner = true;
+
+ const includedGroupName = 'testName';
+
+ const saveIncludedGroupStub = sandbox.stub(
+ element.$.restAPI, 'saveIncludedGroup', () => {
+ return Promise.resolve({});
+ });
+
+ const button = element.$.saveIncludedGroups;
+
+ assert.isTrue(button.hasAttribute('disabled'));
+
+ element.$.includedGroupSearchInput.text = includedGroupName;
+ element.$.includedGroupSearchInput.value = 'testId';
+
+ assert.isFalse(button.hasAttribute('disabled'));
+
+ return element._handleSavingIncludedGroups().then(() => {
+ assert.isTrue(button.hasAttribute('disabled'));
+ assert.isFalse(element.$.Title.classList.contains('edited'));
+ assert.equal(saveIncludedGroupStub.lastCall.args[0], 'Administrators');
+ assert.equal(saveIncludedGroupStub.lastCall.args[1], 'testId');
+ });
+ });
+
test('add included group 404 shows helpful error text', () => {
element._groupOwner = true;
@@ -217,6 +258,20 @@
});
});
+ test('_getGroupSuggestions empty', () => {
+ return element._getGroupSuggestions('nonexistent').then(groups => {
+ assert.equal(groups.length, 0);
+ });
+ });
+
+ test('_getGroupSuggestions non-empty', () => {
+ return element._getGroupSuggestions('test').then(groups => {
+ assert.equal(groups.length, 2);
+ assert.equal(groups[0].name, 'test-admin');
+ assert.equal(groups[1].name, 'test/Administrator (admin)');
+ });
+ });
+
test('_computeHideItemClass returns string for admin', () => {
const admin = true;
const owner = false;
@@ -237,7 +292,7 @@
test('delete member', () => {
const deletelBtns = Polymer.dom(element.root)
- .querySelectorAll('.deleteButton');
+ .querySelectorAll('.deleteMembersButton');
MockInteractions.tap(deletelBtns[0]);
assert.equal(element._itemId, '1000097');
assert.equal(element._itemName, 'jane');
@@ -251,5 +306,19 @@
assert.equal(element._itemId, '1000098');
assert.equal(element._itemName, '1000098');
});
+
+ test('delete included groups', () => {
+ const deletelBtns = Polymer.dom(element.root)
+ .querySelectorAll('.deleteIncludedGroupButton');
+ MockInteractions.tap(deletelBtns[0]);
+ assert.equal(element._itemId, 'testId');
+ assert.equal(element._itemName, 'testName');
+ MockInteractions.tap(deletelBtns[1]);
+ assert.equal(element._itemId, 'testId2');
+ assert.equal(element._itemName, 'testName2');
+ MockInteractions.tap(deletelBtns[2]);
+ assert.equal(element._itemId, 'testId3');
+ assert.equal(element._itemName, 'testName3');
+ });
});
</script>