mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-26 12:21:36 +03:00
Refactored webhook triggering to be asyc
refs https://github.com/TryGhost/Toolbox/issues/283 - In tests we need assurance that the triggering of webhooks has been finished before making assertions. Doing this was impossible with a previous fire-and-forget style of the request call. - The change also adds an optional "request" parameter to be able to override the request library used internally - this is purely for testing purposes.
This commit is contained in:
parent
67dca08df8
commit
21c2c5579b
@ -1,12 +1,19 @@
|
|||||||
const debug = require('@tryghost/debug')('services:webhooks:trigger');
|
const debug = require('@tryghost/debug')('services:webhooks:trigger');
|
||||||
const logging = require('@tryghost/logging');
|
const logging = require('@tryghost/logging');
|
||||||
const request = require('@tryghost/request');
|
|
||||||
const ghostVersion = require('@tryghost/version');
|
|
||||||
|
|
||||||
class WebhookTrigger {
|
class WebhookTrigger {
|
||||||
constructor({models, payload}){
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Object} options.models - Ghost models
|
||||||
|
* @param {Function} options.payload - Function to generate payload
|
||||||
|
* @param {Object} [options.request] - HTTP request handling library
|
||||||
|
*/
|
||||||
|
constructor({models, payload, request}){
|
||||||
this.models = models;
|
this.models = models;
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
|
|
||||||
|
this.request = request ?? require('@tryghost/request');
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll(event) {
|
getAll(event) {
|
||||||
@ -72,7 +79,7 @@ class WebhookTrigger {
|
|||||||
|
|
||||||
debug(`${hooks.models.length} webhooks found for ${event}.`);
|
debug(`${hooks.models.length} webhooks found for ${event}.`);
|
||||||
|
|
||||||
hooks.models.forEach(async (webhook) => {
|
for (const webhook of hooks.models) {
|
||||||
const hookPayload = await this.payload(webhook.get('event'), model);
|
const hookPayload = await this.payload(webhook.get('event'), model);
|
||||||
|
|
||||||
const reqPayload = JSON.stringify(hookPayload);
|
const reqPayload = JSON.stringify(hookPayload);
|
||||||
@ -89,10 +96,10 @@ class WebhookTrigger {
|
|||||||
|
|
||||||
logging.info(`Triggering webhook for "${webhook.get('event')}" with url "${url}"`);
|
logging.info(`Triggering webhook for "${webhook.get('event')}" with url "${url}"`);
|
||||||
|
|
||||||
request(url, opts)
|
await this.request(url, opts)
|
||||||
.then(response.onSuccess(webhook))
|
.then(response.onSuccess(webhook))
|
||||||
.catch(response.onError(webhook));
|
.catch(response.onError(webhook));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ describe('Webhook Service', function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const payload = sinon.stub().resolves(null);
|
let payload = sinon.stub().resolves(null);
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
sinon.restore();
|
sinon.restore();
|
||||||
@ -36,5 +36,46 @@ describe('Webhook Service', function () {
|
|||||||
should.equal(models.Webhook.findAllByEvent.called, true);
|
should.equal(models.Webhook.findAllByEvent.called, true);
|
||||||
should.equal(payload.called, false);
|
should.equal(payload.called, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Does triggers payload handler and request when event when model has a registered hook', async function () {
|
||||||
|
const postModelStub = sinon.stub();
|
||||||
|
const webhookModelStub = {
|
||||||
|
get: () => {}
|
||||||
|
};
|
||||||
|
sinon.stub(webhookModelStub, 'get')
|
||||||
|
.withArgs('event').returns('post.added')
|
||||||
|
.withArgs('target_url').returns('http://example.com');
|
||||||
|
|
||||||
|
const requestStub = sinon.stub().resolves({});
|
||||||
|
|
||||||
|
sinon.stub(models.Webhook, 'findAllByEvent')
|
||||||
|
.withArgs('post.added', {context: {internal: true}})
|
||||||
|
.resolves({models: [webhookModelStub]});
|
||||||
|
|
||||||
|
payload = sinon.stub().resolves({data: [1]});
|
||||||
|
|
||||||
|
const webhookTrigger = new WebhookTrigger({
|
||||||
|
models,
|
||||||
|
payload,
|
||||||
|
request: requestStub
|
||||||
|
});
|
||||||
|
|
||||||
|
sinon.stub(webhookTrigger, 'onSuccess').callsFake(function () {
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
sinon.stub(webhookTrigger, 'onError').callsFake(function () {
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
await webhookTrigger.trigger('post.added', postModelStub);
|
||||||
|
|
||||||
|
should.equal(models.Webhook.findAllByEvent.called, true);
|
||||||
|
should.equal(payload.called, true);
|
||||||
|
|
||||||
|
should.equal(requestStub.called, true);
|
||||||
|
should.equal(requestStub.args[0][0], 'http://example.com');
|
||||||
|
should.deepEqual(requestStub.args[0][1].body, '{"data":[1]}');
|
||||||
|
should.equal(requestStub.args[0][1].headers['Content-Length'], 12);
|
||||||
|
should.equal(requestStub.args[0][1].headers['Content-Length'], 'application/json');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user