Extracted webhook mock receiver into a package

refs https://github.com/TryGhost/Toolbox/issues/320

- Following the rule of having minimum code changes in the Ghost core codebase. This module belongs to "framework" along with other testing tools anyway.
- The bump includes a noteworthy changes - the "snapshotManager" was extracted into a separate exposed property of express-test API (maybe should be even it's own separate concept eventually, for now exposing it was enough). "snapshotManager" had to be exposed to be able to pass it to the webhook mock receiver - to use same instance configured with mocha hooks. snapshotManager has to be a singleton in the system to configure snapshots correctly through mochaHooks.
This commit is contained in:
Naz 2022-05-30 15:03:27 +08:00 committed by naz
parent 0f4aeaaa80
commit c7e833545b
4 changed files with 9 additions and 93 deletions

View File

@ -193,6 +193,7 @@
"@lodder/grunt-postcss": "3.1.1",
"@playwright/test": "1.22.2",
"@tryghost/express-test": "0.11.1",
"@tryghost/webhook-mock-receiver": "0.1.0",
"c8": "7.11.3",
"cli-progress": "3.11.1",
"coffeescript": "2.7.0",

View File

@ -5,7 +5,8 @@ const nock = require('nock');
// Helper services
const configUtils = require('./configUtils');
const WebhookMockReceiver = require('./webhook-mock-receiver');
const WebhookMockReceiver = require('@tryghost/webhook-mock-receiver');
const {snapshotManager} = require('@tryghost/express-test').snapshot;
let mocks = {};
let emailCount = 0;
@ -50,7 +51,7 @@ const mockMail = (response = 'Mail is disabled') => {
};
const mockWebhookRequests = () => {
mocks.webhookMockReceiver = new WebhookMockReceiver();
mocks.webhookMockReceiver = new WebhookMockReceiver({snapshotManager});
return mocks.webhookMockReceiver;
};

View File

@ -1,91 +0,0 @@
const nock = require('nock');
const assert = require('assert');
const {snapshotManager} = require('@tryghost/jest-snapshot');
// NOTE: this is a shameless copy-pasta from express-test utils.
// needs to get refactored into reusable package, just like this whole module
const makeMessageFromMatchMessage = (message, errorMessage) => {
const messageLines = message.split('\n');
messageLines.splice(0, 1, errorMessage);
return messageLines.join('\n');
};
class WebhookMockReceiver {
constructor() {
this.bodyResponse;
this.receiver;
this.recordBodyResponse = this.recordBodyResponse.bind(this);
}
recordBodyResponse(body) {
this.bodyResponse = {body};
// let the nock continue with the response
return true;
}
mock() {
this.receiver = nock('https://test-webhook-receiver.com')
.post('/webhook', this.recordBodyResponse)
.reply(200, {status: 'OK'});
return this;
}
reset() {
nock.restore();
this.bodyResponse = undefined;
}
_assertSnapshot(response, assertion) {
const {properties, field, error} = assertion;
if (!response[field]) {
error.message = `Unable to match snapshot on undefined field ${field} ${error.contextString}`;
error.expected = field;
error.actual = 'undefined';
assert.notEqual(response[field], undefined, error);
}
const hint = `[${field}]`;
const match = snapshotManager.match(response[field], properties, hint);
Object.keys(properties).forEach((prop) => {
const errorMessage = `"response.${field}" is missing the expected property "${prop}"`;
error.message = makeMessageFromMatchMessage(match.message(), errorMessage);
error.expected = prop;
error.actual = 'undefined';
error.showDiff = false; // Disable mocha's diff output as it's already present in match.message()
assert.notEqual(response[field][prop], undefined, error);
});
if (match.pass !== true) {
const errorMessage = `"response.${field}" does not match snapshot.`;
error.message = makeMessageFromMatchMessage(match.message(), errorMessage);
error.expected = match.expected;
error.actual = match.actual;
error.showDiff = false; // Disable mocha's diff output as it's already present in match.message()
}
assert.equal(match.pass, true, error);
}
async matchBodySnapshot(properties = {}) {
while (!this.receiver.isDone()) {
await new Promise((resolve) => setTimeout(resolve, 50));
}
let assertion = {
fn: this._assertSnapshot,
properties: properties,
field: 'body',
type: 'body'
};
this._assertSnapshot(this.bodyResponse, assertion);
}
}
module.exports = WebhookMockReceiver;

View File

@ -2256,6 +2256,11 @@
resolved "https://registry.yarnpkg.com/@tryghost/vhost-middleware/-/vhost-middleware-1.0.26.tgz#8e5fc668f47d3960af6295bf4275a37e7c4fc4e1"
integrity sha512-7IYYeRLIzWS/Wl3PLSVDTpk08AB9SZbulh67buXdzjWXZCkFtWPPMB4BS3fCUuJCFDOfz6f92rfMkMu7Xji/TA==
"@tryghost/webhook-mock-receiver@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@tryghost/webhook-mock-receiver/-/webhook-mock-receiver-0.1.0.tgz#273375a1265eb9d17f9e1e1cb99be36621304dbd"
integrity sha512-zhU7wjZ5x1hiqa5wCevW7IyWKPUWMGE73SCIGNxT7+ww9teWjxeWbDeA233qG86SBZR/11QJSNG7RX/I7lYF7Q==
"@tryghost/zip@1.1.26":
version "1.1.26"
resolved "https://registry.yarnpkg.com/@tryghost/zip/-/zip-1.1.26.tgz#5e6bafd8157d89ce63d034da477fd4c0511f28c7"