Files
trpc-openapi/test/adapters/koa.test.ts

118 lines
3.6 KiB
TypeScript

import { initTRPC } from '@trpc/server';
import Koa from 'koa';
import fetch from 'node-fetch';
import { z } from 'zod';
import {
CreateOpenApiKoaMiddlewareOptions,
OpenApiMeta,
OpenApiRouter,
createOpenApiKoaMiddleware,
} from '../../src';
const createContextMock = jest.fn();
const responseMetaMock = jest.fn();
const onErrorMock = jest.fn();
const clearMocks = () => {
createContextMock.mockClear();
responseMetaMock.mockClear();
onErrorMock.mockClear();
};
const createKoaServerWithRouter = <TRouter extends OpenApiRouter>(
handlerOpts: CreateOpenApiKoaMiddlewareOptions<TRouter>,
) => {
const openApiKoaMiddleware = createOpenApiKoaMiddleware({
router: handlerOpts.router,
createContext: handlerOpts.createContext ?? createContextMock,
responseMeta: handlerOpts.responseMeta ?? (responseMetaMock as any),
onError: handlerOpts.onError ?? (onErrorMock as any),
maxBodySize: handlerOpts.maxBodySize,
});
const app = new Koa();
// eslint-disable-next-line @typescript-eslint/no-misused-promises
app.use(openApiKoaMiddleware);
const server = app.listen(0);
const port = (server.address() as any).port as number;
const url = `http://localhost:${port}`;
return {
url,
close: () => server.close(),
};
};
const t = initTRPC.meta<OpenApiMeta>().context<any>().create();
describe('koa adapter', () => {
afterEach(() => {
clearMocks();
});
test('with valid routes', async () => {
const appRouter = t.router({
sayHelloQuery: t.procedure
.meta({ openapi: { method: 'GET', path: '/say-hello' } })
.input(z.object({ name: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => ({ greeting: `Hello ${input.name}!` })),
sayHelloMutation: t.procedure
.meta({ openapi: { method: 'POST', path: '/say-hello' } })
.input(z.object({ name: z.string() }))
.output(z.object({ greeting: z.string() }))
.mutation(({ input }) => ({ greeting: `Hello ${input.name}!` })),
sayHelloSlash: t.procedure
.meta({ openapi: { method: 'GET', path: '/say/hello' } })
.input(z.object({ name: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => ({ greeting: `Hello ${input.name}!` })),
});
const { url, close } = createKoaServerWithRouter({
router: appRouter,
});
{
const res = await fetch(`${url}/say-hello?name=Lily`, { method: 'GET' });
expect(res.status).toBe(200);
expect(await res.json()).toEqual({ greeting: 'Hello Lily!' });
expect(createContextMock).toHaveBeenCalledTimes(1);
expect(responseMetaMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
clearMocks();
}
{
const res = await fetch(`${url}/say-hello`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Lily' }),
});
expect(res.status).toBe(200);
expect(await res.json()).toEqual({ greeting: 'Hello Lily!' });
expect(createContextMock).toHaveBeenCalledTimes(1);
expect(responseMetaMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
clearMocks();
}
{
const res = await fetch(`${url}/say/hello?name=Lily`, { method: 'GET' });
expect(res.status).toBe(200);
expect(await res.json()).toEqual({ greeting: 'Hello Lily!' });
expect(createContextMock).toHaveBeenCalledTimes(1);
expect(responseMetaMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
}
close();
});
});