Merge "Ensure Change and Reply plugin APIs have element set"

This commit is contained in:
Kasper Nilsson
2017-11-14 22:56:34 +00:00
committed by Gerrit Code Review
4 changed files with 234 additions and 124 deletions

View File

@@ -14,21 +14,49 @@
(function(window) {
'use strict';
/**
* Ensure GrChangeActionsInterface instance has access to gr-change-actions
* element and retrieve if the interface was created before element.
* @param {!GrChangeActionsInterface} api
*/
function ensureEl(api) {
if (!api._el) {
const sharedApiElement = document.createElement('gr-js-api-interface');
setEl(api, sharedApiElement.getElement(
sharedApiElement.Element.CHANGE_ACTIONS));
}
}
/**
* Set gr-change-actions element to a GrChangeActionsInterface instance.
* @param {!GrChangeActionsInterface} api
* @param {!Element} el gr-change-actions
*/
function setEl(api, el) {
if (!el) {
console.warn('changeActions() is not ready');
return;
}
api._el = el;
api.RevisionActions = el.RevisionActions;
api.ChangeActions = el.ChangeActions;
api.ActionType = el.ActionType;
}
function GrChangeActionsInterface(plugin, el) {
this.plugin = plugin;
this._el = el;
this.RevisionActions = el.RevisionActions;
this.ChangeActions = el.ChangeActions;
this.ActionType = el.ActionType;
setEl(this, el);
}
GrChangeActionsInterface.prototype.addPrimaryActionKey = function(key) {
ensureEl(this);
if (this._el.primaryActionKeys.includes(key)) { return; }
this._el.push('primaryActionKeys', key);
};
GrChangeActionsInterface.prototype.removePrimaryActionKey = function(key) {
ensureEl(this);
this._el.primaryActionKeys = this._el.primaryActionKeys.filter(k => {
return k !== key;
});
@@ -36,45 +64,55 @@
GrChangeActionsInterface.prototype.setActionOverflow = function(type, key,
overflow) {
ensureEl(this);
return this._el.setActionOverflow(type, key, overflow);
};
GrChangeActionsInterface.prototype.setActionPriority = function(type, key,
priority) {
ensureEl(this);
return this._el.setActionPriority(type, key, priority);
};
GrChangeActionsInterface.prototype.setActionHidden = function(type, key,
hidden) {
ensureEl(this);
return this._el.setActionHidden(type, key, hidden);
};
GrChangeActionsInterface.prototype.add = function(type, label) {
ensureEl(this);
return this._el.addActionButton(type, label);
};
GrChangeActionsInterface.prototype.remove = function(key) {
ensureEl(this);
return this._el.removeActionButton(key);
};
GrChangeActionsInterface.prototype.addTapListener = function(key, handler) {
ensureEl(this);
this._el.addEventListener(key + '-tap', handler);
};
GrChangeActionsInterface.prototype.removeTapListener = function(key,
handler) {
ensureEl(this);
this._el.removeEventListener(key + '-tap', handler);
};
GrChangeActionsInterface.prototype.setLabel = function(key, text) {
ensureEl(this);
this._el.setActionButtonProp(key, 'label', text);
};
GrChangeActionsInterface.prototype.setEnabled = function(key, enabled) {
ensureEl(this);
this._el.setActionButtonProp(key, 'enabled', enabled);
};
GrChangeActionsInterface.prototype.getActionDetails = function(action) {
ensureEl(this);
return this._el.getActionDetails(action) ||
this._el.getActionDetails(this.plugin.getPluginName() + '~' + action);
};

View File

@@ -39,6 +39,7 @@ breaking changes to gr-change-actions wont be noticed.
suite('gr-js-api-interface tests', () => {
let element;
let changeActions;
let plugin;
// Because deepEqual doesnt behave in Safari.
function assertArraysEqual(actual, expected) {
@@ -48,132 +49,152 @@ breaking changes to gr-change-actions wont be noticed.
}
}
setup(() => {
element = fixture('basic');
element.change = {};
element._hasKnownChainState = false;
let plugin;
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeActions = plugin.changeActions();
});
suite('early init', () => {
setup(() => {
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeActions = plugin.changeActions();
element = fixture('basic');
});
teardown(() => {
changeActions = null;
});
teardown(() => {
changeActions = null;
});
test('property existence', () => {
const properties = [
'ActionType',
'ChangeActions',
'RevisionActions',
];
for (const p of properties) {
assertArraysEqual(changeActions[p], element[p]);
}
});
test('add/remove primary action keys', () => {
element.primaryActionKeys = [];
changeActions.addPrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['foo']);
changeActions.addPrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['foo']);
changeActions.addPrimaryActionKey('bar');
assertArraysEqual(element.primaryActionKeys, ['foo', 'bar']);
changeActions.removePrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['bar']);
changeActions.removePrimaryActionKey('baz');
assertArraysEqual(element.primaryActionKeys, ['bar']);
changeActions.removePrimaryActionKey('bar');
assertArraysEqual(element.primaryActionKeys, []);
});
test('action buttons', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
const handler = sinon.spy();
changeActions.addTapListener(key, handler);
flush(() => {
MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
assert(handler.calledOnce);
changeActions.removeTapListener(key, handler);
MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
assert(handler.calledOnce);
changeActions.remove(key);
flush(() => {
assert.isNull(element.$$('[data-action-key="' + key + '"]'));
done();
test('does not throw', ()=> {
assert.doesNotThrow(() => {
changeActions.add('change', 'foo');
});
});
});
test('action button properties', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
const button = element.$$('[data-action-key="' + key + '"]');
assert.isOk(button);
assert.equal(button.getAttribute('data-label'), 'Bork!');
assert.isNotOk(button.disabled);
changeActions.setLabel(key, 'Yo');
changeActions.setEnabled(key, false);
suite('normal init', () => {
setup(() => {
element = fixture('basic');
element.change = {};
element._hasKnownChainState = false;
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeActions = plugin.changeActions();
});
teardown(() => {
changeActions = null;
});
test('property existence', () => {
const properties = [
'ActionType',
'ChangeActions',
'RevisionActions',
];
for (const p of properties) {
assertArraysEqual(changeActions[p], element[p]);
}
});
test('add/remove primary action keys', () => {
element.primaryActionKeys = [];
changeActions.addPrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['foo']);
changeActions.addPrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['foo']);
changeActions.addPrimaryActionKey('bar');
assertArraysEqual(element.primaryActionKeys, ['foo', 'bar']);
changeActions.removePrimaryActionKey('foo');
assertArraysEqual(element.primaryActionKeys, ['bar']);
changeActions.removePrimaryActionKey('baz');
assertArraysEqual(element.primaryActionKeys, ['bar']);
changeActions.removePrimaryActionKey('bar');
assertArraysEqual(element.primaryActionKeys, []);
});
test('action buttons', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
const handler = sinon.spy();
changeActions.addTapListener(key, handler);
flush(() => {
assert.equal(button.getAttribute('data-label'), 'Yo');
assert.isTrue(button.disabled);
done();
MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
assert(handler.calledOnce);
changeActions.removeTapListener(key, handler);
MockInteractions.tap(element.$$('[data-action-key="' + key + '"]'));
assert(handler.calledOnce);
changeActions.remove(key);
flush(() => {
assert.isNull(element.$$('[data-action-key="' + key + '"]'));
done();
});
});
});
});
test('hide action buttons', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
const button = element.$$('[data-action-key="' + key + '"]');
assert.isOk(button);
assert.isFalse(button.hasAttribute('hidden'));
changeActions.setActionHidden(
changeActions.ActionType.REVISION, key, true);
test('action button properties', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
const button = element.$$('[data-action-key="' + key + '"]');
assert.isNotOk(button);
done();
assert.isOk(button);
assert.equal(button.getAttribute('data-label'), 'Bork!');
assert.isNotOk(button.disabled);
changeActions.setLabel(key, 'Yo');
changeActions.setEnabled(key, false);
flush(() => {
assert.equal(button.getAttribute('data-label'), 'Yo');
assert.isTrue(button.disabled);
done();
});
});
});
});
test('move action button to overflow', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
assert.isTrue(element.$.moreActions.hidden);
assert.isOk(element.$$('[data-action-key="' + key + '"]'));
changeActions.setActionOverflow(
changeActions.ActionType.REVISION, key, true);
test('hide action buttons', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
assert.isNotOk(element.$$('[data-action-key="' + key + '"]'));
assert.isFalse(element.$.moreActions.hidden);
assert.strictEqual(element.$.moreActions.items[0].name, 'Bork!');
done();
const button = element.$$('[data-action-key="' + key + '"]');
assert.isOk(button);
assert.isFalse(button.hasAttribute('hidden'));
changeActions.setActionHidden(
changeActions.ActionType.REVISION, key, true);
flush(() => {
const button = element.$$('[data-action-key="' + key + '"]');
assert.isNotOk(button);
done();
});
});
});
});
test('change actions priority', done => {
const key1 =
test('move action button to overflow', done => {
const key = changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
flush(() => {
assert.isTrue(element.$.moreActions.hidden);
assert.isOk(element.$$('[data-action-key="' + key + '"]'));
changeActions.setActionOverflow(
changeActions.ActionType.REVISION, key, true);
flush(() => {
assert.isNotOk(element.$$('[data-action-key="' + key + '"]'));
assert.isFalse(element.$.moreActions.hidden);
assert.strictEqual(element.$.moreActions.items[0].name, 'Bork!');
done();
});
});
});
test('change actions priority', done => {
const key1 =
changeActions.add(changeActions.ActionType.REVISION, 'Bork!');
const key2 =
const key2 =
changeActions.add(changeActions.ActionType.CHANGE, 'Squanch?');
flush(() => {
let buttons =
Polymer.dom(element.root).querySelectorAll('[data-action-key]');
assert.equal(buttons[0].getAttribute('data-action-key'), key1);
assert.equal(buttons[1].getAttribute('data-action-key'), key2);
changeActions.setActionPriority(
changeActions.ActionType.REVISION, key1, 10);
flush(() => {
buttons =
let buttons =
Polymer.dom(element.root).querySelectorAll('[data-action-key]');
assert.equal(buttons[0].getAttribute('data-action-key'), key1);
assert.equal(buttons[1].getAttribute('data-action-key'), key2);
changeActions.setActionPriority(
changeActions.ActionType.REVISION, key1, 10);
flush(() => {
buttons =
Polymer.dom(element.root).querySelectorAll('[data-action-key]');
assert.equal(buttons[0].getAttribute('data-action-key'), key2);
assert.equal(buttons[1].getAttribute('data-action-key'), key1);
done();
assert.equal(buttons[0].getAttribute('data-action-key'), key2);
assert.equal(buttons[1].getAttribute('data-action-key'), key1);
done();
});
});
});
});

View File

@@ -14,6 +14,19 @@
(function(window) {
'use strict';
/**
* Ensure GrChangeReplyInterface instance has access to gr-reply-dialog
* element and retrieve if the interface was created before element.
* @param {!GrChangeReplyInterfaceOld} api
*/
function ensureEl(api) {
if (!api._el) {
const sharedApiElement = document.createElement('gr-js-api-interface');
api._el = sharedApiElement.getElement(
sharedApiElement.Element.REPLY_DIALOG);
}
}
/**
* @deprecated
*/
@@ -22,14 +35,17 @@
}
GrChangeReplyInterfaceOld.prototype.getLabelValue = function(label) {
ensureEl(this);
return this._el.getLabelValue(label);
};
GrChangeReplyInterfaceOld.prototype.setLabelValue = function(label, value) {
ensureEl(this);
this._el.setLabelValue(label, value);
};
GrChangeReplyInterfaceOld.prototype.send = function(opt_includeComments) {
ensureEl(this);
return this._el.send(opt_includeComments);
};

View File

@@ -40,37 +40,72 @@ breaking changes to gr-reply-dialog wont be noticed.
let element;
let sandbox;
let changeReply;
let plugin;
setup(() => {
sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
getAccount() { return Promise.resolve(null); },
});
element = fixture('basic');
sandbox = sinon.sandbox.create();
let plugin;
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeReply = plugin.changeReply();
});
teardown(() => {
changeReply = null;
sandbox.restore();
});
test('calls', () => {
sandbox.stub(element, 'getLabelValue').returns('+123');
assert.equal(changeReply.getLabelValue('My-Label'), '+123');
suite('early init', () => {
setup(() => {
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeReply = plugin.changeReply();
element = fixture('basic');
});
sandbox.stub(element, 'setLabelValue');
changeReply.setLabelValue('My-Label', '+1337');
assert.isTrue(
element.setLabelValue.calledWithExactly('My-Label', '+1337'));
teardown(() => {
changeReply = null;
});
sandbox.stub(element, 'send');
changeReply.send(false);
assert.isTrue(element.send.calledWithExactly(false));
test('works', () => {
sandbox.stub(element, 'getLabelValue').returns('+123');
assert.equal(changeReply.getLabelValue('My-Label'), '+123');
sandbox.stub(element, 'setLabelValue');
changeReply.setLabelValue('My-Label', '+1337');
assert.isTrue(
element.setLabelValue.calledWithExactly('My-Label', '+1337'));
sandbox.stub(element, 'send');
changeReply.send(false);
assert.isTrue(element.send.calledWithExactly(false));
});
});
suite('normal init', () => {
setup(() => {
element = fixture('basic');
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
changeReply = plugin.changeReply();
});
teardown(() => {
changeReply = null;
});
test('works', () => {
sandbox.stub(element, 'getLabelValue').returns('+123');
assert.equal(changeReply.getLabelValue('My-Label'), '+123');
sandbox.stub(element, 'setLabelValue');
changeReply.setLabelValue('My-Label', '+1337');
assert.isTrue(
element.setLabelValue.calledWithExactly('My-Label', '+1337'));
sandbox.stub(element, 'send');
changeReply.send(false);
assert.isTrue(element.send.calledWithExactly(false));
});
});
});
</script>