@whook/whook
Version:
Build strong and efficient REST web services.
1,070 lines • 31.1 kB
JavaScript
import { describe, test, beforeEach, jest, expect } from '@jest/globals';
import { WHOOK_PROJECT_PLUGIN_NAME, } from '../index.js';
import initRoutesDefinitions from './ROUTES_DEFINITIONS.js';
import { YError } from 'yerror';
import { definition as getPingDefinition } from '../routes/getPing.js';
const APP_ENV = 'test';
const getUserModule = {
definition: {
path: '/users/{userId}',
method: 'get',
operation: {
operationId: 'getUser',
tags: ['user'],
parameters: [
{
$ref: `#/components/parameters/userId`,
},
],
responses: {
200: {
description: 'The user',
content: {
'application/json': {
schema: {
$ref: `#/components/schemas/User`,
},
},
},
},
},
},
},
userIdParameter: {
name: 'userId',
parameter: {
name: 'userId',
in: 'path',
schema: { type: 'number' },
},
},
userSchema: {
name: 'User',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
},
},
},
default: undefined,
};
const putUserModule = {
definition: {
path: '/users/{userId}',
method: 'put',
operation: {
operationId: 'putUser',
tags: ['user'],
parameters: [
{
$ref: `#/components/parameters/userId`,
},
],
requestBody: {
content: {
'application/json': {
schema: {
$ref: `#/components/schemas/User`,
},
},
},
},
responses: getUserModule.definition.operation.responses,
},
},
default: undefined,
};
describe('initRoutesDefinitions', () => {
const log = jest.fn();
const importer = jest.fn();
const readDir = jest.fn();
beforeEach(() => {
log.mockReset();
importer.mockReset();
readDir.mockReset();
});
describe('should work', () => {
test('with no routes folder', async () => {
readDir.mockImplementationOnce(() => {
throw new YError('E_NOT_SUPPOSED_TO_BE_HERE');
});
importer.mockImplementationOnce(() => {
throw new YError('E_NOT_SUPPOSED_TO_BE_HERE');
});
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: [],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {},
"importerCalls": [],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
],
"readDirCalls": [],
}
`);
});
test('with empty routes folder', async () => {
readDir.mockResolvedValueOnce([]);
importer.mockImplementationOnce(() => {
throw new YError('E_NOT_SUPPOSED_TO_BE_HERE');
});
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {},
"importerCalls": [],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/src/routes",
],
],
}
`);
});
test('with a few routes', async () => {
readDir.mockResolvedValueOnce(['getPing.ts', 'getUser.ts']);
importer.mockResolvedValueOnce({
definition: getPingDefinition,
default: undefined,
});
importer.mockResolvedValueOnce(getUserModule);
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"getPing": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getPing",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"pong": {
"enum": [
"pong",
],
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Pong",
},
},
"summary": "Checks API's availability.",
"tags": [
"system",
],
},
"path": "/ping",
},
},
"name": "getPing",
"pluginName": "__project__",
"url": "file:///home/whoiam/project/src/routes/getPing.ts",
},
"getUser": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
"userIdParameter": {
"name": "userId",
"parameter": {
"in": "path",
"name": "userId",
"schema": {
"type": "number",
},
},
},
"userSchema": {
"name": "User",
"schema": {
"properties": {
"name": {
"type": "string",
},
},
"type": "object",
},
},
},
"name": "getUser",
"pluginName": "__project__",
"url": "file:///home/whoiam/project/src/routes/getUser.ts",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/src/routes/getPing.ts",
],
[
"file:///home/whoiam/project/src/routes/getUser.ts",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/src/routes",
],
],
}
`);
});
test('with a few routes in different plugins paths', async () => {
readDir.mockResolvedValueOnce(['getPing.ts']);
readDir.mockResolvedValueOnce(['getUser.js']);
importer.mockResolvedValueOnce({
definition: getPingDefinition,
default: undefined,
});
importer.mockResolvedValueOnce(getUserModule);
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME, '@whook'];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: ['routes'],
},
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"getPing": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getPing",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"pong": {
"enum": [
"pong",
],
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Pong",
},
},
"summary": "Checks API's availability.",
"tags": [
"system",
],
},
"path": "/ping",
},
},
"name": "getPing",
"pluginName": "__project__",
"url": "file:///home/whoiam/project/src/routes/getPing.ts",
},
"getUser": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
"userIdParameter": {
"name": "userId",
"parameter": {
"in": "path",
"name": "userId",
"schema": {
"type": "number",
},
},
},
"userSchema": {
"name": "User",
"schema": {
"properties": {
"name": {
"type": "string",
},
},
"type": "object",
},
},
},
"name": "getUser",
"pluginName": "@whook",
"url": "file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/src/routes/getPing.ts",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/src/routes",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
test('with a few routes in different plugins paths and an overridden one', async () => {
readDir.mockResolvedValueOnce(['getPing.ts']);
readDir.mockResolvedValueOnce(['getPing.js', 'getUser.js']);
importer.mockResolvedValueOnce({
definition: getPingDefinition,
default: undefined,
});
importer.mockResolvedValueOnce(getUserModule);
importer.mockRejectedValueOnce(new YError('E_NOT_SUPPOSED_TO_BE_HERE'));
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME, '@whook'];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: ['routes'],
},
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"getPing": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getPing",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"pong": {
"enum": [
"pong",
],
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Pong",
},
},
"summary": "Checks API's availability.",
"tags": [
"system",
],
},
"path": "/ping",
},
},
"name": "getPing",
"pluginName": "__project__",
"url": "file:///home/whoiam/project/src/routes/getPing.ts",
},
"getUser": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
"userIdParameter": {
"name": "userId",
"parameter": {
"in": "path",
"name": "userId",
"schema": {
"type": "number",
},
},
},
"userSchema": {
"name": "User",
"schema": {
"properties": {
"name": {
"type": "string",
},
},
"type": "object",
},
},
},
"name": "getUser",
"pluginName": "@whook",
"url": "file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/src/routes/getPing.ts",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
[
"debug",
"⏳ - Skipped "getPing.js" since already loaded upstream.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/src/routes",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
test('with a few routes in different plugins paths and an overridden one but with a different extension', async () => {
readDir.mockResolvedValueOnce(['getPing.ts']);
readDir.mockResolvedValueOnce(['getPing.js', 'getUser.js']);
importer.mockResolvedValueOnce({
definition: getPingDefinition,
default: undefined,
});
importer.mockResolvedValueOnce(getUserModule);
importer.mockRejectedValueOnce(new YError('E_NOT_SUPPOSED_TO_BE_HERE'));
const WHOOK_PLUGINS = [WHOOK_PROJECT_PLUGIN_NAME, '@whook'];
const WHOOK_RESOLVED_PLUGINS = {
[WHOOK_PROJECT_PLUGIN_NAME]: {
mainURL: 'file:///home/whoiam/project/src/index.ts',
types: ['routes'],
},
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"getPing": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getPing",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"pong": {
"enum": [
"pong",
],
"type": "string",
},
},
"type": "object",
},
},
},
"description": "Pong",
},
},
"summary": "Checks API's availability.",
"tags": [
"system",
],
},
"path": "/ping",
},
},
"name": "getPing",
"pluginName": "__project__",
"url": "file:///home/whoiam/project/src/routes/getPing.ts",
},
"getUser": {
"module": {
"default": undefined,
"definition": {
"method": "get",
"operation": {
"operationId": "getUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
"userIdParameter": {
"name": "userId",
"parameter": {
"in": "path",
"name": "userId",
"schema": {
"type": "number",
},
},
},
"userSchema": {
"name": "User",
"schema": {
"properties": {
"name": {
"type": "string",
},
},
"type": "object",
},
},
},
"name": "getUser",
"pluginName": "@whook",
"url": "file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/src/routes/getPing.ts",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
[
"debug",
"⏳ - Skipped "getPing.js" since already loaded upstream.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/src/routes",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
test('with a several routes at the same path', async () => {
readDir.mockResolvedValueOnce(['getUser', 'putUser']);
importer.mockResolvedValueOnce(getUserModule);
importer.mockResolvedValueOnce(putUserModule);
const WHOOK_PLUGINS = ['@whook'];
const WHOOK_RESOLVED_PLUGINS = {
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {},
"importerCalls": [],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
[
"debug",
"⏳ - Skipped "getUser" per file patterns.",
],
[
"debug",
"⏳ - Skipped "putUser" per file patterns.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
test('with a disabled handler at the same path', async () => {
const getUserModuleDisabled = {
...getUserModule,
definition: {
...getUserModule.definition,
config: {
environments: ['dev'],
},
},
};
readDir.mockResolvedValueOnce(['getUser.js', 'putUser.js']);
importer.mockResolvedValueOnce(getUserModuleDisabled);
importer.mockResolvedValueOnce(putUserModule);
const WHOOK_PLUGINS = ['@whook'];
const WHOOK_RESOLVED_PLUGINS = {
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"putUser": {
"module": {
"default": undefined,
"definition": {
"method": "put",
"operation": {
"operationId": "putUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
},
"name": "putUser",
"pluginName": "@whook",
"url": "file:///home/whoiam/project/node_modules/@whook/dist/routes/putUser.js",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/putUser.js",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
[
"debug",
"⏳ - Skipped "getUser.js" since disabled by the application environment (test)!",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
test('with a filtered handler', async () => {
const getUserModuleDisabled = {
...getUserModule,
definition: {
...getUserModule.definition,
operation: {
...getUserModule.definition.operation,
tags: ['other'],
},
},
};
readDir.mockResolvedValueOnce(['getUser.ts', 'putUser.ts']);
importer.mockResolvedValueOnce(getUserModuleDisabled);
importer.mockResolvedValueOnce(putUserModule);
const WHOOK_PLUGINS = ['@whook'];
const WHOOK_RESOLVED_PLUGINS = {
'@whook': {
mainURL: 'file:///home/whoiam/project/node_modules/@whook/dist/index.js',
types: ['routes'],
},
};
const ROUTES_DEFINITIONS = await initRoutesDefinitions({
APP_ENV,
WHOOK_PLUGINS,
WHOOK_RESOLVED_PLUGINS,
ROUTE_DEFINITION_FILTER: (definition) => !(definition.operation.tags || []).includes('user'),
log,
readDir,
importer,
});
expect({
ROUTES_DEFINITIONS,
logCalls: log.mock.calls.filter(([type]) => !type.endsWith('stack')),
readDirCalls: readDir.mock.calls,
importerCalls: importer.mock.calls,
}).toMatchInlineSnapshot(`
{
"ROUTES_DEFINITIONS": {
"putUser": {
"module": {
"default": undefined,
"definition": {
"method": "put",
"operation": {
"operationId": "putUser",
"parameters": [
{
"$ref": "#/components/parameters/userId",
},
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User",
},
},
},
"description": "The user",
},
},
"tags": [
"user",
],
},
"path": "/users/{userId}",
},
},
"name": "putUser",
"pluginName": "@whook",
"url": "file:///home/whoiam/project/node_modules/@whook/dist/routes/putUser.js",
},
},
"importerCalls": [
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/getUser.js",
],
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes/putUser.js",
],
],
"logCalls": [
[
"debug",
"🈁 - Gathering the routes modules.",
],
[
"debug",
"⏳ - Skipped "getUser.ts" due to routes handlers filter.",
],
],
"readDirCalls": [
[
"file:///home/whoiam/project/node_modules/@whook/dist/routes",
],
],
}
`);
});
});
});
//# sourceMappingURL=ROUTES_DEFINITIONS.test.js.map