Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"ecmaVersion": 2022
},
"globals": {
"generateFixture": "readonly"
"generateFixture": "readonly",
"mockObjectProperty": "readonly"
},
"rules": {
"arrow-parens": ["error", "as-needed"],
Expand Down
49 changes: 49 additions & 0 deletions jest.setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ const { extname, join, resolve } = require('path');

global.__basedir = __dirname;

jest.mock('express', () => {
const mockExpress = function () {
return {
delete: jest.fn(),
get: jest.fn(),
patch: jest.fn(),
post: jest.fn(),
put: jest.fn(),
use: jest.fn(),
listen: jest.fn()
};
};

mockExpress.static = jest.fn();
return mockExpress;
});

jest.mock('http-terminator', () => ({
createHttpTerminator: () => ({
terminate: () => 'success'
})
}));

/**
* Generate a fixture from string literals.
*
Expand Down Expand Up @@ -39,3 +62,29 @@ const generateFixture = (
};

global.generateFixture = generateFixture;

/**
* Shallow mock specific properties, restore with callback, mockClear.
* A simple object property mock for scenarios where the property is not a function/Jest fails.
*
* @param {object} object
* @param {object} propertiesValues
* @returns {{mockClear: Function}}
*/
const mockObjectProperty = (object = {}, propertiesValues) => {
const updatedObject = object;
const originalPropertiesValues = {};

Object.entries(propertiesValues).forEach(([key, value]) => {
originalPropertiesValues[key] = updatedObject[key];
updatedObject[key] = value;
});

return {
mockClear: () => {
Object.assign(updatedObject, originalPropertiesValues);
}
};
};

global.mockObjectProperty = mockObjectProperty;
87 changes: 87 additions & 0 deletions src/__tests__/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ApiDocMock should generate an api response from annotations: apiDocMock, parsed 1`] = `
{
"CACHE": {
"app": {
"delete": [MockFunction],
"get": [MockFunction] {
"calls": [
[
"/hello/world/",
[Function],
],
],
"results": [
{
"type": "return",
"value": undefined,
},
],
},
"listen": [MockFunction] {
"calls": [
[
undefined,
[Function],
],
],
"results": [
{
"type": "return",
"value": undefined,
},
],
},
"patch": [MockFunction],
"post": [MockFunction],
"put": [MockFunction],
"use": [MockFunction] {
"calls": [
[
"/docs",
undefined,
],
[
[Function],
],
],
"results": [
{
"type": "return",
"value": undefined,
},
{
"type": "return",
"value": undefined,
},
],
},
},
"httpTerminator": {
"terminate": [Function],
},
},
"apiJson": "[
{
"errorExamples": [
{
"title": "Error-Response:",
"content": "HTTP/1.1 400 OK\\n{\\n \\"error\\": \\"test\\"\\n}",
"type": "json"
}
],
"successExamples": [
{
"title": "Success-Response:",
"content": "HTTP/1.1 200 OK\\n{\\n \\"success\\": \\"test\\"\\n}",
"type": "json"
}
]
}
]",
"httpTerminator": {
"terminate": [Function],
},
}
`;
37 changes: 37 additions & 0 deletions src/__tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { apiDocMock, setupResponse } = require('../');
const { OPTIONS } = require('../global');

describe('ApiDocMock', () => {
it('should have specific defined properties', () => {
Expand All @@ -14,4 +15,40 @@ describe('ApiDocMock', () => {
const func = async () => apiDocMock();
await expect(func).rejects.toThrow('Server failed to load');
});

it('should generate an api response from annotations', async () => {
const apiFixture = generateFixture(
`/**
* @api {get} /hello/world/
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* "success": "test"
* }
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 400 OK
* {
* "error": "test"
* }
*/`,
{ dir: './.fixtures/apiDocMock', filename: 'apiDocMock.js' }
);

const { mockClear } = mockObjectProperty(OPTIONS, {
watchPath: [apiFixture.dir],
docsPath: 'lorem-ipsum'
});

const { apiJson, ...rest } = await apiDocMock();
expect({
apiJson: JSON.stringify(
apiJson.map(({ error, success }) => ({ errorExamples: error?.examples, successExamples: success?.examples })),
null,
2
),
...rest
}).toMatchSnapshot('apiDocMock, parsed');

mockClear();
});
});
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ const apiDocMock = async ({ port, watchPath, docsPath } = OPTIONS) => {
throw new Error('Server failed to load');
}

return httpTerminator;
return {
apiJson,
CACHE,
httpTerminator
};
};

module.exports = { apiDocMock, setupDocs, setupResponse, OPTIONS };