Skip to content

Commit

Permalink
feat(@whook/example): add a time mock example
Browse files Browse the repository at this point in the history
  • Loading branch information
nfroidure committed Dec 4, 2024
1 parent b44541b commit 21d4987
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 40 deletions.
36 changes: 18 additions & 18 deletions packages/whook-create/src/services/createWhook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ describe('initCreateWhook', () => {
await createWhook();

expect(
JSON.parse(
outputFile.mock.calls.
find((call) => call[0].toString().endsWith('package.json'))?.[1]?.
toString() || ''
)
).toMatchInlineSnapshot(`
JSON.parse(
outputFile.mock.calls
.find((call) => call[0].toString().endsWith('package.json'))?.[1]
?.toString() || '',
),
).toMatchInlineSnapshot(`
{
"author": {
"email": "[email protected]",
Expand Down Expand Up @@ -344,12 +344,12 @@ describe('initCreateWhook', () => {
await createWhook();

expect(
JSON.parse(
outputFile.mock.calls.
find((call) => call[0].toString().endsWith('package.json'))?.[1]?.
toString() || ''
)
).toMatchInlineSnapshot(`
JSON.parse(
outputFile.mock.calls
.find((call) => call[0].toString().endsWith('package.json'))?.[1]
?.toString() || '',
),
).toMatchInlineSnapshot(`
{
"author": {
"email": "[email protected]",
Expand Down Expand Up @@ -527,12 +527,12 @@ describe('initCreateWhook', () => {
await createWhook();

expect(
JSON.parse(
outputFile.mock.calls.
find((call) => call[0].toString().endsWith('package.json'))?.[1]?.
toString() || ''
)
).toMatchInlineSnapshot(`
JSON.parse(
outputFile.mock.calls
.find((call) => call[0].toString().endsWith('package.json'))?.[1]
?.toString() || '',
),
).toMatchInlineSnapshot(`
{
"author": {
"email": "[email protected]",
Expand Down
6 changes: 6 additions & 0 deletions packages/whook-example/src/config/test/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import type { AppConfig } from 'application-services';
const CONFIG: AppConfig = {
...COMMON_CONFIG,
HOST: 'localhost',
// Let's mock the time starting at a special date
CLOCK_MOCK: {
isFixed: false,
mockedTime: Date.parse('2012-01-15T00:00:00Z'),
referenceTime: Date.now(),
},
};

export default CONFIG;
9 changes: 9 additions & 0 deletions packages/whook-example/src/config/test/overrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ export const OVERRIDES: Overrides = {
// You could debug logs by substituting the normal log
// service by another named `debugLog`.
// log: 'debugLog',
// Let's replace the time service per the mock one
time: 'timeMock',
// And keep real time for mocks internals
timeMock: {
time: 'time',
},
putTime: {
time: 'time',
},
};

export default OVERRIDES;
87 changes: 87 additions & 0 deletions packages/whook-example/src/handlers/putTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
type WhookAPIHandlerDefinition,
type WhookResponse,
} from '@whook/whook';
import { type LogService } from 'common-services';
import { type ClockMockService } from 'application-services';
import { autoHandler } from 'knifecycle';
import { YError } from 'yerror';
import { env } from 'node:process';

import { type AppEnv } from '../index.js';
import { type TimeMockService } from 'application-services/dist/services/timeMock.js';

export const definition: WhookAPIHandlerDefinition = {
path: '/time',
method: 'put',
operation: {
'x-whook': {
type: 'http',
disabled: env.APP_ENV !== 'test',
},
operationId: 'putTime',
summary: 'Allows to set the time like the great random god',
tags: ['system'],
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties: {
time: { type: 'number' },
isFixed: { type: 'boolean' },
},
},
},
},
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'number',
},
},
},
},
},
},
};

export default autoHandler(putTime);

async function putTime(
{
APP_ENV,
CLOCK_MOCK,
time,
log,
}: {
APP_ENV: AppEnv;
CLOCK_MOCK: ClockMockService;
time: TimeMockService;
log: LogService;
},
{ body }: { body: { time: number; isFixed: boolean } },
): Promise<WhookResponse<201, void, number>> {
if (APP_ENV !== 'local' && APP_ENV !== 'test') {
throw new YError('E_NO_MOCK_IN_PROD', APP_ENV);
}

CLOCK_MOCK.isFixed = body.isFixed;
CLOCK_MOCK.mockedTime = body.time;

if (!CLOCK_MOCK.isFixed) {
CLOCK_MOCK.referenceTime = time();
}

log('warning', `⌚ - Set time to "${body.time}".`);

return {
status: 201,
body: time(),
};
}
6 changes: 6 additions & 0 deletions packages/whook-example/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ describe('runProcess', () => {
[
"⌛ - Delay service initialized.",
],
[
"⏳ - Ignored handler "putTime" since disabled by its definition!",
],
[
"✅ - Module path of "API" found at "file:///home/whoiam/projects/whook/packages/whook-example/src/services/API.ts".",
],
Expand Down Expand Up @@ -1134,6 +1137,9 @@ describe('runProcess', () => {
[
"🛂 - Dynamic import of "file:///home/whoiam/projects/whook/packages/whook-example/src/handlers/putEcho.ts".",
],
[
"🛂 - Dynamic import of "file:///home/whoiam/projects/whook/packages/whook-example/src/handlers/putTime.ts".",
],
[
"🛂 - Dynamic import of "file:///home/whoiam/projects/whook/packages/whook-example/src/services/API.ts".",
],
Expand Down
5 changes: 4 additions & 1 deletion packages/whook-example/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import initHTTPRouter from '@whook/http-router';
import { initErrorHandlerWithCORS } from '@whook/cors';
import wrapHTTPRouterWithSwaggerUI from '@whook/swagger-ui';
import { extractAppEnv } from 'application-services';
import { extractAppEnv, initTimeMock } from 'application-services';

/* Architecture Note #1: A Whook baked API
This API server uses the Whook engine. Thoses architecture
Expand Down Expand Up @@ -234,5 +234,8 @@ export async function prepareEnvironment<T extends Knifecycle>(
// Add the CORS wrapped error handler
$.register(initErrorHandlerWithCORS);

// Add the time mock service for testing
$.register(initTimeMock);

return $;
}
30 changes: 27 additions & 3 deletions packages/whook-example/src/openAPISchema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ declare namespace API {
export type $200 = Components.Responses.getTimeResponse200<200>;
}
}
export namespace PutTime {
export type Body = Components.RequestBodies.PutTimeRequestBody;
export type Output = Responses.$200;
export type Input = {
readonly body: Body;
};
export namespace Responses {
export type $200 = Components.Responses.putTimeResponse200<200>;
}
}
export namespace PutEcho {
export type Body = Components.RequestBodies.Echo;
export type Output = Responses.$200;
Expand All @@ -76,6 +86,8 @@ declare namespace API {
declare namespace Components {
export namespace RequestBodies {
export type Echo = Components.Schemas.Echo;
export type PutTimeRequestBody =
Components.Schemas.RequestBodiesputTimeRequestBodyBody0;
}
export namespace Parameters {
export type Duration = number;
Expand Down Expand Up @@ -128,6 +140,13 @@ declare namespace Components {
};
readonly body: Components.Schemas.TimeSchema;
};
export type putTimeResponse200<S extends number> = {
readonly status: S;
readonly headers?: {
readonly [name: string]: unknown;
};
readonly body: Components.Schemas.ResponsesputTimeResponse200Body0;
};
export type getPingResponse200<S extends number> = {
readonly status: S;
readonly headers?: {
Expand All @@ -137,12 +156,13 @@ declare namespace Components {
};
}
export namespace Schemas {
export type TimeSchema = {
currentDate?: string;
};
export type Echo = {
echo: string;
};
export type RequestBodiesputTimeRequestBodyBody0 = {
time?: number;
isFixed?: boolean;
};
export type ResponsesDiagnosticBody0 = {
transactions: {
[pattern: string]: unknown;
Expand All @@ -156,6 +176,10 @@ declare namespace Components {
pathParam2?: string;
queryParam?: string[];
};
export type TimeSchema = {
currentDate?: string;
};
export type ResponsesputTimeResponse200Body0 = number;
export type ResponsesgetPingResponse200Body0 = {
pong?: 'pong';
};
Expand Down
5 changes: 3 additions & 2 deletions packages/whook-example/src/whook.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
import type { WhookAPIOperationCORSConfig, WhookCORSConfig } from '@whook/cors';
import type { APIConfig } from './services/API.js';
import type { JWTServiceConfig } from 'jwt-service';
import type { BaseAppEnvVars } from 'application-services';
import type { BaseAppEnvVars, TimeMockConfig } from 'application-services';
import type { JWTEnvVars } from 'jwt-service';
import type { FilterAPIDefinitionEnvVars } from './services/FILTER_API_DEFINITION.ts';

Expand All @@ -39,7 +39,8 @@ The configuration is typed so that you are sure you cannot
WhookSwaggerUIConfig,
WhookCORSConfig,
APIConfig,
JWTServiceConfig {}
JWTServiceConfig,
TimeMockConfig {}
}

declare module '@whook/whook' {
Expand Down
5 changes: 4 additions & 1 deletion packages/whook-graphql/src/handlers/getGraphQL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import initPostGraphQL, {
definition as postGraphQLDefinition,
} from './postGraphQL.js';
import { YHTTPError } from 'yhttperror';
import { type WhookAPIHandlerDefinition, type WhookOperation } from '@whook/whook';
import {
type WhookAPIHandlerDefinition,
type WhookOperation,
} from '@whook/whook';

export const definition: WhookAPIHandlerDefinition = {
path: postGraphQLDefinition.path,
Expand Down
30 changes: 15 additions & 15 deletions packages/whook/src/services/compiler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ describe('Compiler', () => {
const result = await compiler(path.join('src', 'services', 'compiler.ts'));

expect({
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls
}).toMatchInlineSnapshot(`
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls,
}).toMatchInlineSnapshot(`
{
"contentsLength": 65048,
"extension": ".mjs",
Expand All @@ -66,11 +66,11 @@ describe('Compiler', () => {
const result = await compiler(path.join('src', 'services', 'compiler.ts'));

expect({
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls
}).toMatchInlineSnapshot(`
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls,
}).toMatchInlineSnapshot(`
{
"contentsLength": 3618,
"extension": ".mjs",
Expand Down Expand Up @@ -100,11 +100,11 @@ describe('Compiler', () => {
const result = await compiler(path.join('src', 'services', 'compiler.ts'));

expect({
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls
}).toMatchInlineSnapshot(`
extension: result.extension,
contentsLength: result?.contents?.length,
mappingsLength: result?.mappings?.length,
logCalls: log.mock.calls,
}).toMatchInlineSnapshot(`
{
"contentsLength": 5291,
"extension": ".cjs",
Expand Down

0 comments on commit 21d4987

Please sign in to comment.