af94855349
refs: https://github.com/TryGhost/Ghost/issues/14882 - I found a common pattern where catch predicates were being used to catch non-existent models in destroy methods, and sometimes elsewhere in the API endpoints - The use of predicates is deprecated, and we're working to remove them from everywhere, so that we can remove bluebird - In order to still handle these errors correctly, we needed a small change to mw-error-handler so that it can detect EmptyResponse errors from bookshelf, as well as 404s Note: there is a small change as a result of this - the context on these errors now says "Resource not found" instead of "{ModelName} not found". - I think this is acceptable for now, as we will be reviewing these errors in more depth later. It's quite easy to make changes, we just have to decide what with proper design input
150 lines
4.6 KiB
JavaScript
150 lines
4.6 KiB
JavaScript
const {agentProvider, fixtureManager, matchers} = require('../../utils/e2e-framework');
|
|
const {anyEtag, anyErrorId, anyObjectId, anyISODate, stringMatching, anyContentLength} = matchers;
|
|
|
|
const webhookMatcher = {
|
|
id: anyObjectId,
|
|
api_version: stringMatching(/v\d+\.\d+/),
|
|
integration_id: anyObjectId,
|
|
created_at: anyISODate,
|
|
updated_at: anyISODate
|
|
};
|
|
|
|
describe('Webhooks API', function () {
|
|
let agent;
|
|
let createdWebhookId;
|
|
let webhookData;
|
|
|
|
before(async function () {
|
|
agent = await agentProvider.getAdminAPIAgent();
|
|
await fixtureManager.init('integrations');
|
|
await agent.loginAsOwner();
|
|
|
|
// create a webhook linked to a real integration
|
|
webhookData = {
|
|
event: 'test.create',
|
|
target_url: 'http://example.com/webhooks/test/extra/1',
|
|
name: 'test',
|
|
secret: 'thisissecret',
|
|
integration_id: fixtureManager.get('integrations', 0).id
|
|
};
|
|
});
|
|
|
|
it('Can create a webhook', async function () {
|
|
const {body} = await agent.post('/webhooks/')
|
|
.body({webhooks: [webhookData]})
|
|
.expectStatus(201)
|
|
.matchHeaderSnapshot({
|
|
// Note: No location header as there is no read method for webhooks
|
|
etag: anyEtag,
|
|
'content-length': anyContentLength
|
|
|
|
})
|
|
.matchBodySnapshot({
|
|
webhooks: [webhookMatcher]
|
|
});
|
|
|
|
// Store an id for use in future tests. Not the best pattern but does keep the tests readable.
|
|
createdWebhookId = body.webhooks[0].id;
|
|
});
|
|
|
|
it('Fails nicely when adding a duplicate webhook', async function () {
|
|
await agent.post('/webhooks/')
|
|
.body({webhooks: [webhookData]})
|
|
.expectStatus(422)
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag
|
|
})
|
|
.matchBodySnapshot({
|
|
errors: [{
|
|
id: anyErrorId
|
|
}]
|
|
});
|
|
});
|
|
|
|
it('Fails nicely when creating an orphaned webhook', async function () {
|
|
await agent
|
|
.post('/webhooks/')
|
|
.body({webhooks: [{
|
|
event: 'test.create',
|
|
target_url: 'http://example.com/webhooks/test/extra/10',
|
|
name: 'test',
|
|
secret: 'thisissecret',
|
|
integration_id: `fake-integration`
|
|
}]})
|
|
.expectStatus(422)
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag
|
|
})
|
|
.matchBodySnapshot({
|
|
errors: [{
|
|
id: anyErrorId
|
|
}]
|
|
});
|
|
});
|
|
|
|
it('Can edit a webhook', async function () {
|
|
await agent.put(`/webhooks/${createdWebhookId}/`)
|
|
.body({
|
|
webhooks: [{
|
|
name: 'Edit Test',
|
|
event: 'member.added',
|
|
target_url: 'https://example.com/new-member',
|
|
integration_id: 'ignore_me'
|
|
}]
|
|
})
|
|
.expectStatus(200)
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag,
|
|
'content-length': anyContentLength
|
|
})
|
|
.matchBodySnapshot({
|
|
webhooks: [webhookMatcher]
|
|
});
|
|
});
|
|
|
|
it('Cannot edit a non-existent webhook', async function () {
|
|
await agent.put('/webhooks/abcd1234abcd1234abcd1234/')
|
|
.body({
|
|
webhooks: [{
|
|
name: 'Edit Test',
|
|
event: 'member.added',
|
|
target_url: 'https://example.com/new-member',
|
|
integration_id: 'ignore_me'
|
|
}]
|
|
})
|
|
.expectStatus(404)
|
|
.matchBodySnapshot({
|
|
errors: [{
|
|
id: anyErrorId
|
|
}]
|
|
})
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag
|
|
});
|
|
});
|
|
|
|
it('Can delete a webhook', async function () {
|
|
await agent
|
|
.delete(`/webhooks/${createdWebhookId}/`)
|
|
.expectStatus(204)
|
|
.expectEmptyBody()
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag
|
|
});
|
|
});
|
|
|
|
it('Cannot delete a non-existent webhook', async function () {
|
|
await agent
|
|
.delete('/webhooks/abcd1234abcd1234abcd1234/')
|
|
.expectStatus(404)
|
|
.matchBodySnapshot({
|
|
errors: [{
|
|
id: anyErrorId
|
|
}]
|
|
})
|
|
.matchHeaderSnapshot({
|
|
etag: anyEtag
|
|
});
|
|
});
|
|
});
|