Report network failures to plugins

Usage:

plugin.get(url).then(doStuff).catch(onError);
plugin.post(url, payload).then(doStuff).catch(onError);

onError will receive an error string, that is one of the following:
- error message from Gerrit REST API, eg. "Cherry pick failed: ..."
- error message from Fetch API, eg "TypeError: Failed to fetch"
- HTTP failure code, eg "404"

Bug: Issue 6595
Change-Id: I1a598fe2c249c8e87bc575359d51ad2e15431356
This commit is contained in:
Viktar Donich
2017-06-28 15:07:51 -07:00
parent 6481922623
commit d6be68abd7
2 changed files with 57 additions and 19 deletions

View File

@@ -47,7 +47,7 @@ limitations under the License.
setup(() => { setup(() => {
sandbox = sinon.sandbox.create(); sandbox = sinon.sandbox.create();
getResponseObjectStub = sandbox.stub().returns(Promise.resolve()); getResponseObjectStub = sandbox.stub().returns(Promise.resolve());
sendStub = sandbox.stub().returns(Promise.resolve()); sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
stub('gr-rest-api-interface', { stub('gr-rest-api-interface', {
getAccount() { getAccount() {
return Promise.resolve({name: 'Judy Hopps'}); return Promise.resolve({name: 'Judy Hopps'});
@@ -76,24 +76,47 @@ limitations under the License.
'http://test.com/plugins/testplugin/static/test.js'); 'http://test.com/plugins/testplugin/static/test.js');
}); });
test('get', done => { test('_send on failure rejects with response text', () => {
const response = {foo: 'foo'}; sendStub.returns(Promise.resolve(
getResponseObjectStub.returns(Promise.resolve(response)); {status: 400, text() {return Promise.resolve('text');}}));
plugin.get('/url', r => { return plugin._send().catch(r => {
assert.isTrue(sendStub.calledWith('GET', '/url')); assert.equal(r, 'text');
assert.strictEqual(r, response);
done();
}); });
}); });
test('post', done => { test('_send on failure without text rejects with code', () => {
sendStub.returns(Promise.resolve(
{status: 400, text() {return Promise.resolve(null);}}));
return plugin._send().catch(r => {
assert.equal(r, '400');
});
});
test('get', () => {
const response = {foo: 'foo'};
getResponseObjectStub.returns(Promise.resolve(response));
return plugin.get('/url', r => {
assert.isTrue(sendStub.calledWith('GET', '/url'));
assert.strictEqual(r, response);
});
});
test('get using Promise', () => {
const response = {foo: 'foo'};
getResponseObjectStub.returns(Promise.resolve(response));
return plugin.get('/url', r => 'rubbish').then(r => {
assert.isTrue(sendStub.calledWith('GET', '/url'));
assert.strictEqual(r, response);
});
});
test('post', () => {
const payload = {foo: 'foo'}; const payload = {foo: 'foo'};
const response = {bar: 'bar'}; const response = {bar: 'bar'};
getResponseObjectStub.returns(Promise.resolve(response)); getResponseObjectStub.returns(Promise.resolve(response));
plugin.post('/url', payload, r => { return plugin.post('/url', payload, r => {
assert.isTrue(sendStub.calledWith('POST', '/url', payload)); assert.isTrue(sendStub.calledWith('POST', '/url', payload));
assert.strictEqual(r, response); assert.strictEqual(r, response);
done();
}); });
}); });

View File

@@ -106,18 +106,33 @@
return this._url.origin + '/plugins/' + this._name + (opt_path || '/'); return this._url.origin + '/plugins/' + this._name + (opt_path || '/');
}; };
Plugin.prototype._send = function(method, url, callback, opt_payload) { Plugin.prototype._send = function(method, url, opt_callback, opt_payload) {
return getRestAPI().send(method, url, opt_payload) return getRestAPI().send(method, url, opt_payload).then(response => {
.then(getRestAPI().getResponseObject) if (response.status < 200 || response.status >= 300) {
.then(callback); return response.text().then(text => {
if (text) {
return Promise.reject(text);
} else {
return Promise.reject(response.status);
}
});
} else {
return getRestAPI().getResponseObject(response);
}
}).then(response => {
if (opt_callback) {
opt_callback(response);
}
return response;
});
}; };
Plugin.prototype.get = function(url, callback) { Plugin.prototype.get = function(url, opt_callback) {
return this._send('GET', url, callback); return this._send('GET', url, opt_callback);
}, },
Plugin.prototype.post = function(url, payload, callback) { Plugin.prototype.post = function(url, payload, opt_callback) {
return this._send('POST', url, callback, payload); return this._send('POST', url, opt_callback, payload);
}, },
Plugin.prototype.changeActions = function() { Plugin.prototype.changeActions = function() {