0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Fixed undefined error when serializing webhooks

closes: https://github.com/TryGhost/Toolbox/issues/318
refs: https://github.com/TryGhost/Toolbox/issues/320
refs: 2a11d5100e

- The underlying problem was caused by the removal of API versions
  - commit 2a11d5100e
  - I missed doing the same refactor as was done for the post-emailserializer here: 2a11d5100e (diff-0f7477bb5e5a9fdcb4c909a9e9e61ab5bb76b640b2d63a5791a9d6c8904f2758R7)
  - The removal of api versions included a change to remove circular references in the api module
- Written some basic unit tests to prove that webhook serialization works
  - I'm not 100% happy with the output, and not sure if it's the tests or reality, needs further work
  - Future work tracked in https://github.com/TryGhost/Toolbox/issues/320
This commit is contained in:
Hannah Wolfe 2022-05-03 11:31:45 +01:00
parent 3d397bb5f1
commit d01c1cba64
No known key found for this signature in database
GPG key ID: AB586C3B5AE5C037
2 changed files with 86 additions and 2 deletions

View file

@ -2,6 +2,7 @@ module.exports = (event, model) => {
const _ = require('lodash');
const {sequence} = require('@tryghost/promise');
const api = require('../../api').endpoints;
const apiShared = require('../../api').shared;
const resourceName = event.match(/(\w+)\./)[1];
const docName = `${resourceName}s`;
@ -17,7 +18,7 @@ module.exports = (event, model) => {
frame.options.withRelated = ['tags', 'authors'];
}
return api.shared
return apiShared
.serializers
.handle
.output(model, {docName: docName, method: 'read'}, api.serializers.output, frame)
@ -40,7 +41,7 @@ module.exports = (event, model) => {
frame.options.withRelated = ['tags', 'authors'];
}
return api.shared
return apiShared
.serializers
.handle
.output(model, {docName: docName, method: 'read'}, api.serializers.output, frame)

View file

@ -0,0 +1,83 @@
const sinon = require('sinon');
const assert = require('assert');
const models = require('../../../../../core/server/models');
const serialize = require('../../../../../core/server/services/webhooks/serialize');
// Mocked internals
const membersService = require('../../../../../core/server/services/members');
const {fixtureManager} = require('../../../../utils/e2e-framework');
describe('WebhookService - Serialize', function () {
before(function () {
models.init();
});
beforeEach(function () {
sinon.stub(membersService, 'api').get(() => {
return {
productRepository: {
list: sinon.stub().returns({})
}
};
});
});
it('rejects with no arguments', async function () {
assert.rejects(await serialize, {name: 'TypeError'});
});
it('rejects with no model', async function () {
await assert.rejects(
async () => {
await serialize('fake.hook');
},
(error) => {
assert.strictEqual(error.name, 'TypeError');
assert.strictEqual(error.message, 'Cannot read properties of undefined (reading \'attributes\')');
return true;
}
);
});
it('can serialize a basic model', async function () {
const fakeModel = {
attributes: {},
_previousAttributes: {}
};
const result = await serialize('test.hook', fakeModel);
assert.deepEqual(result, {test: {current: {}, previous: {}}});
});
it('can serialize a new post', async function () {
const post = fixtureManager.get('posts', 1);
const postModel = new models.Post(post);
const result = await serialize('post.added', postModel);
assert.ok(result.post, 'Should be wrapped in post');
assert.deepEqual(result.post.previous, {});
// @TODO: use snapshot matching here
assert.equal(result.post.current.reading_time, 1, 'The reading time generated field should be present');
});
it('can serialize an edited post', async function () {
const post = fixtureManager.get('posts', 1);
const postModel = new models.Post(post);
// We use both _previousAttributes and _changed in the webhook serializer
postModel._previousAttributes.title = post.title;
postModel._changed = {title: post.title};
postModel.attributes.title = 'A brand new title';
const result = await serialize('post.edited', postModel);
assert.ok(result.post, 'Should be wrapped in post');
// @TODO: use snapshot matching here
assert.equal(result.post.current.title, 'A brand new title', 'The updated title should be present');
assert.equal(result.post.previous.title, 'Ghostly Kitchen Sink', 'The previous title should also be present');
});
});