adapt test-api-handler for blitz API routes
This commit is contained in:
parent
43f89216ae
commit
ca917d3ebc
@ -1,6 +1,6 @@
|
|||||||
import { testApiHandler } from "next-test-api-route-handler";
|
|
||||||
import twilio from "twilio";
|
import twilio from "twilio";
|
||||||
|
|
||||||
|
import { testApiHandler } from "../../../../test/test-api-handler";
|
||||||
import db from "db";
|
import db from "db";
|
||||||
import handler from "./incoming-message";
|
import handler from "./incoming-message";
|
||||||
import insertIncomingMessageQueue from "../queue/insert-incoming-message";
|
import insertIncomingMessageQueue from "../queue/insert-incoming-message";
|
||||||
|
24190
package-lock.json
generated
24190
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -81,19 +81,22 @@
|
|||||||
"@types/pino": "6.3.11",
|
"@types/pino": "6.3.11",
|
||||||
"@types/preview-email": "2.0.1",
|
"@types/preview-email": "2.0.1",
|
||||||
"@types/react": "17.0.19",
|
"@types/react": "17.0.19",
|
||||||
|
"@types/test-listen": "1.1.0",
|
||||||
"@types/web-push": "3.3.2",
|
"@types/web-push": "3.3.2",
|
||||||
"autoprefixer": "10.3.3",
|
"autoprefixer": "10.3.3",
|
||||||
"concurrently": "6.2.1",
|
"concurrently": "6.2.1",
|
||||||
"eslint": "7.32.0",
|
"eslint": "7.32.0",
|
||||||
"husky": "6.0.0",
|
"husky": "6.0.0",
|
||||||
|
"isomorphic-unfetch": "3.1.0",
|
||||||
"lint-staged": "11.1.2",
|
"lint-staged": "11.1.2",
|
||||||
"next-test-api-route-handler": "2.2.0",
|
|
||||||
"postcss": "8.3.6",
|
"postcss": "8.3.6",
|
||||||
"prettier": "2.3.2",
|
"prettier": "2.3.2",
|
||||||
"prettier-plugin-prisma": "2.30.0",
|
"prettier-plugin-prisma": "2.30.0",
|
||||||
"pretty-quick": "3.1.1",
|
"pretty-quick": "3.1.1",
|
||||||
"preview-email": "3.0.5",
|
"preview-email": "3.0.5",
|
||||||
"prisma": "2.30.0",
|
"prisma": "2.30.0",
|
||||||
|
"test-listen": "1.1.0",
|
||||||
|
"type-fest": "2.1.0",
|
||||||
"typescript": "4.4.2"
|
"typescript": "4.4.2"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
|
120
test/test-api-handler.ts
Normal file
120
test/test-api-handler.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import listen from "test-listen";
|
||||||
|
import fetch from "isomorphic-unfetch";
|
||||||
|
import { createServer } from "http";
|
||||||
|
import { parse as parseUrl } from "url";
|
||||||
|
import { apiResolver } from "next/dist/server/api-utils";
|
||||||
|
|
||||||
|
import type { PromiseValue } from "type-fest";
|
||||||
|
import type { NextApiHandler } from "next";
|
||||||
|
import type { IncomingMessage, ServerResponse } from "http";
|
||||||
|
|
||||||
|
type FetchReturnValue = PromiseValue<ReturnType<typeof fetch>>;
|
||||||
|
type FetchReturnType<NextResponseJsonType> = Promise<
|
||||||
|
Omit<FetchReturnValue, "json"> & {
|
||||||
|
json: (...args: Parameters<FetchReturnValue["json"]>) => Promise<NextResponseJsonType>;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters expected by `testApiHandler`.
|
||||||
|
*/
|
||||||
|
export type TestParameters<NextResponseJsonType = unknown> = {
|
||||||
|
/**
|
||||||
|
* A function that receives an `IncomingMessage` object. Use this function to
|
||||||
|
* edit the request before it's injected into the handler.
|
||||||
|
*/
|
||||||
|
requestPatcher?: (req: IncomingMessage) => void;
|
||||||
|
/**
|
||||||
|
* A function that receives a `ServerResponse` object. Use this functions to
|
||||||
|
* edit the request before it's injected into the handler.
|
||||||
|
*/
|
||||||
|
responsePatcher?: (res: ServerResponse) => void;
|
||||||
|
/**
|
||||||
|
* A function that receives an object representing "processed" dynamic routes;
|
||||||
|
* _modifications_ to this object are passed directly to the handler. This
|
||||||
|
* should not be confused with query string parsing, which is handled
|
||||||
|
* automatically.
|
||||||
|
*/
|
||||||
|
paramsPatcher?: (params: Record<string, unknown>) => void;
|
||||||
|
/**
|
||||||
|
* `params` is passed directly to the handler and represent processed dynamic
|
||||||
|
* routes. This should not be confused with query string parsing, which is
|
||||||
|
* handled automatically.
|
||||||
|
*
|
||||||
|
* `params: { id: 'some-id' }` is shorthand for `paramsPatcher: (params) =>
|
||||||
|
* (params.id = 'some-id')`. This is most useful for quickly setting many
|
||||||
|
* params at once.
|
||||||
|
*/
|
||||||
|
params?: Record<string, string | string[]>;
|
||||||
|
/**
|
||||||
|
* `url: 'your-url'` is shorthand for `requestPatcher: (req) => (req.url =
|
||||||
|
* 'your-url')`
|
||||||
|
*/
|
||||||
|
url?: string;
|
||||||
|
/**
|
||||||
|
* The actual handler under test. It should be an async function that accepts
|
||||||
|
* `NextApiRequest` and `NextApiResult` objects (in that order) as its two
|
||||||
|
* parameters.
|
||||||
|
*/
|
||||||
|
handler: NextApiHandler<NextResponseJsonType>;
|
||||||
|
/**
|
||||||
|
* `test` must be a function that runs your test assertions, returning a
|
||||||
|
* promise (or async). This function receives one parameter: `fetch`, which is
|
||||||
|
* the unfetch package's `fetch(...)` function but with the first parameter
|
||||||
|
* omitted.
|
||||||
|
*/
|
||||||
|
test: (obj: { fetch: (init?: RequestInit) => FetchReturnType<NextResponseJsonType> }) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses Next's internal `apiResolver` to execute api route handlers in a
|
||||||
|
* Next-like testing environment.
|
||||||
|
*/
|
||||||
|
export async function testApiHandler<NextResponseJsonType = any>({
|
||||||
|
requestPatcher,
|
||||||
|
responsePatcher,
|
||||||
|
paramsPatcher,
|
||||||
|
params,
|
||||||
|
url,
|
||||||
|
handler,
|
||||||
|
test,
|
||||||
|
}: TestParameters<NextResponseJsonType>) {
|
||||||
|
let server = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const localUrl = await listen(
|
||||||
|
(server = createServer((req, res) => {
|
||||||
|
if (!apiResolver) {
|
||||||
|
res.end();
|
||||||
|
throw new Error("missing apiResolver export from next-server/api-utils");
|
||||||
|
}
|
||||||
|
|
||||||
|
url && (req.url = url);
|
||||||
|
requestPatcher && requestPatcher(req);
|
||||||
|
responsePatcher && responsePatcher(res);
|
||||||
|
|
||||||
|
const finalParams = { ...parseUrl(req.url || "", true).query, ...params };
|
||||||
|
paramsPatcher && paramsPatcher(finalParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*? From next internals:
|
||||||
|
** apiResolver(
|
||||||
|
** req: IncomingMessage,
|
||||||
|
** res: ServerResponse,
|
||||||
|
** query: any,
|
||||||
|
** resolverModule: any,
|
||||||
|
** apiContext: __ApiPreviewProps,
|
||||||
|
** propagateError: boolean
|
||||||
|
** )
|
||||||
|
*/
|
||||||
|
void apiResolver(req, res, finalParams, handler, undefined as any, true, { route: "", config: {} });
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
await test({
|
||||||
|
fetch: (init?: RequestInit) => fetch(localUrl, init) as FetchReturnType<NextResponseJsonType>,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
server?.close();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user