From a48555f127b9420527a53d27ac8367246d4474ad Mon Sep 17 00:00:00 2001 From: "Xunnamius (Romulus)" Date: Tue, 16 Apr 2024 18:56:53 -0700 Subject: [PATCH] build(readme): add section on jsdom support --- README.md | 424 +++++++++++++++++++++++++++++------------------------- 1 file changed, 227 insertions(+), 197 deletions(-) diff --git a/README.md b/README.md index 98b39668..86bdbbf6 100644 --- a/README.md +++ b/README.md @@ -32,22 +32,22 @@ Confidently test your Next.js API routes in an isolated Next-like environment **Trying to unit test your Next.js API routes?** Tired of hacking something together with express or node-mocks-http or writing a bunch of boring dummy infra just to get some passing tests? And what does a "passing test" mean anyway -when your handlers aren't receiving _actual_ [`NextRequest`][3] objects and +when your handlers aren't receiving _actual_ [`NextRequest`][1] objects and aren't being run by Next.js itself? > Next.js patches the global `fetch` function, for instance. If your tests > aren't doing the same, you're making space for bugs! -Is it vexing that everything explodes when your [App Router][4] handlers call +Is it vexing that everything explodes when your [App Router][2] handlers call `headers()` or `cookies()` or any of the other route-specific [helper -functions][5]? Or maybe you want your [Pages Router][6] handlers to receive -_actual_ [`NextApiRequest`][7] and [`NextApiResponse`][7] objects? +functions][3]? Or maybe you want your [Pages Router][4] handlers to receive +_actual_ [`NextApiRequest`][5] and [`NextApiResponse`][5] objects? Sound interesting? Then want no longer! 🤩 [`next-test-api-route-handler`][x-badge-repo-link] (NTARH) uses Next.js's internal resolvers to precisely emulate route handling. To guarantee stability, -this package is [automatically tested][8] against [each release of Next.js][9] +this package is [automatically tested][6] against [each release of Next.js][7] and Node.js. Go forth and test confidently!
@@ -57,7 +57,7 @@ and Node.js. Go forth and test confidently! ✨ ✨ -Note that App Router support begins with `next@14.0.4` ([why?][10]) +Note that App Router support begins with `next@14.0.4` ([why?][8]) @@ -88,6 +88,7 @@ src="https://xunn.at/ntarh-compat" /> ✨ - [Appendix](#appendix) - [Limitations with App Router and Edge Runtime Emulation](#limitations-with-app-router-and-edge-runtime-emulation) - [Legacy Runtime Support](#legacy-runtime-support) + - [Jsdom Support](#jsdom-support) - [Inspiration](#inspiration) - [Published Package Details](#published-package-details) - [License](#license) @@ -103,13 +104,16 @@ src="https://xunn.at/ntarh-compat" /> ✨ npm install --save-dev next-test-api-route-handler ``` -> See [the appendix][11] for legacy support options. +> See [the appendix][9] for legacy Next.js support options. + +> Also see [the appendix][10] if you're using `jest` and +> `jest-environment-jsdom`. ## Usage > \[!IMPORTANT]\ > **NTARH must always be the first import in your test file.** This is due to the -> way Next.js is written and distributed. See [the appendix][12] for technical details. +> way Next.js is written and distributed. See [the appendix][11] for technical details. ```typescript // ESM @@ -228,7 +232,7 @@ At minimum, `options` must contain the following properties: For example: > \[!CAUTION]\ -> Ensuring `testApiHandler` is imported [_before_][13] any Next.js package (like +> Ensuring `testApiHandler` is imported [_before_][12] any Next.js package (like > `'next/headers'` below) is crucial to the proper function of NTARH. Doing otherwise > will result in undefined behavior. @@ -261,14 +265,14 @@ await testApiHandler({ ### `appHandler` -> ⪢ API reference: [`appHandler`][14] +> ⪢ API reference: [`appHandler`][13] The actual route handler under test (usually imported from `app/*`). It should be an object and/or exported module containing one or more [valid uppercase HTTP -method names][15] as keys, each with an [async handling function][16] that -accepts a [`NextRequest`][3] and a [context][17] (i.e. `{ params }`) as its two +method names][14] as keys, each with an [async handling function][15] that +accepts a [`NextRequest`][1] and a [context][16] (i.e. `{ params }`) as its two parameters. The object or module can also export [other configuration settings -recognized by Next.js][18]. +recognized by Next.js][17]. ```typescript await testApiHandler({ @@ -294,16 +298,16 @@ await testApiHandler({ }); ``` -See also: [`rejectOnHandlerError`][19] and the section [Working Around Next.js -`fetch` Patching][20]. +See also: [`rejectOnHandlerError`][18] and the section [Working Around Next.js +`fetch` Patching][19]. ### `pagesHandler` -> ⪢ API reference: [`pagesHandler`][21] +> ⪢ API reference: [`pagesHandler`][20] The actual route handler under test (usually imported from `pages/api/*`). It -should be an async function that accepts [`NextApiRequest`][7] and -[`NextApiResponse`][7] objects as its two parameters. +should be an async function that accepts [`NextApiRequest`][5] and +[`NextApiResponse`][5] objects as its two parameters. ```typescript await testApiHandler({ @@ -316,25 +320,25 @@ await testApiHandler({ }); ``` -See also: [`rejectOnHandlerError`][19]. +See also: [`rejectOnHandlerError`][18]. ### `test` -> ⪢ API reference: [`test`][22] +> ⪢ API reference: [`test`][21] An async or promise-returning function wherein test assertions can be run. This function receives one destructured parameter: `fetch`, which is a wrapper around -Node's [global fetch][23] function. Use this to send HTTP requests to the +Node's [global fetch][22] function. Use this to send HTTP requests to the handler under test. > \[!CAUTION]\ -> Note that `fetch`'s `resource` parameter, _i.e. [the first parameter in `fetch(...)`][24]_, +> Note that `fetch`'s `resource` parameter, _i.e. [the first parameter in `fetch(...)`][23]_, > is omitted. #### ⚙ Handling Redirections -Starting with version `4.0.4`, NTARH sets the [`fetch(...)` `options`][25] -parameter's [`redirect` property to `'manual'`][26] by default. This prevents +Starting with version `4.0.4`, NTARH sets the [`fetch(...)` `options`][24] +parameter's [`redirect` property to `'manual'`][25] by default. This prevents the WHATWG/undici `fetch` function from throwing a `fetch failed`/`redirect count exceeded` error. @@ -343,14 +347,14 @@ parameter, e.g. `fetch({ redirect: 'error' })`. #### ⚙ Compatibility with Mock Service Worker -Starting with version `4.0.0`, NTARH ships with [Mock Service Worker -(msw@2)][27] support by adding the [`x-msw-intention: bypass`][28] header -(formerly `x-msw-bypass` since version `3.1.0`) to all requests. +Starting with version `4.0.0`, NTARH ships with [Mock Service Worker (msw)][26] +support by adding the [`x-msw-intention: "bypass"`][27] and +`x-msw-bypass: "true"` headers to all requests. -If necessary, you can override this behavior by setting the header to some other -value (e.g. `"none"`) via `fetch`'s `customInit` parameter (not +If necessary, you can override this behavior by setting the appropriate headers +to some other value (e.g. `"none"`) via `fetch`'s `customInit` parameter (not `requestPatcher`). This comes in handy when testing functionality like -[arbitrary response redirection][29] (or via the [Pages Router][30]). +[arbitrary response redirection][28] (or via the [Pages Router][29]). For example: @@ -406,10 +410,10 @@ it('redirects a shortened URL to the real URL', async () => { As of version `2.3.0`, the response object returned by `fetch()` includes a non-standard _cookies_ field containing an array of objects representing -[`set-cookie` response header(s)][31] parsed by [the `cookie` package][32]. Use +[`set-cookie` response header(s)][30] parsed by [the `cookie` package][31]. Use the _cookies_ field to easily access a response's cookie data in your tests. -Here's an example taken straight from the [unit tests][33]: +Here's an example taken straight from the [unit tests][32]: ```typescript import { testApiHandler } from 'next-test-api-route-handler'; @@ -451,18 +455,18 @@ it('handles multiple set-cookie headers', async () => { ### `rejectOnHandlerError` -> ⪢ API reference: [`rejectOnHandlerError`][34] +> ⪢ API reference: [`rejectOnHandlerError`][33] As of version `2.3.0`, unhandled errors in the `pagesHandler`/`appHandler` function are kicked up to Next.js to handle. > \[!IMPORTANT]\ > **This means `testApiHandler` will NOT reject or throw if an unhandled error occurs -> in `pagesHandler`/`appHandler`, which includes failing Jest `expect()` assertions.** +> in `pagesHandler`/`appHandler`, which typically includes failing `expect()` assertions.** Instead, the response returned by `fetch()` in your `test` function will have a `HTTP 500` status [thanks to how Next.js deals with unhandled errors in -production][35]. Prior to `2.3.0`, NTARH's behavior on unhandled errors and +production][34]. Prior to `2.3.0`, NTARH's behavior on unhandled errors and elsewhere was inconsistent. Version `3.0.0` further improved error handling, ensuring no errors slip by uncaught. @@ -527,22 +531,22 @@ await testApiHandler({ } }); // ...but since we used rejectOnHandlerError, the whole promise rejects -// and Jest reports that the test failed, which is probably what you wanted. +// and it is reported that the test failed, which is probably what you wanted. ``` ### `requestPatcher` (`url`) > \[!TIP]\ > Manually setting the request url is usually unnecessary. Only set the url if [your -> handler expects it][36] or [you want to rely on query string parsing instead of -> `params`/`paramsPatcher`][37]. +> handler expects it][35] or [you want to rely on query string parsing instead of +> `params`/`paramsPatcher`][36]. #### 💎 Using `appHandler` -> ⪢ API reference: [`requestPatcher`][38], [`url`][39] +> ⪢ API reference: [`requestPatcher`][37], [`url`][38] -`requestPatcher` is a function that receives a [`NextRequest`][3] object and -returns a [`Request`][40] instance. Use this function to edit the request +`requestPatcher` is a function that receives a [`NextRequest`][1] object and +returns a [`Request`][39] instance. Use this function to edit the request _before_ it's injected into the handler. > \[!CAUTION]\ @@ -551,8 +555,8 @@ _before_ it's injected into the handler. > standard headers added by `fetch(...)`. If you're getting strange JSON-related > errors or hanging tests, ensure this is not the cause. -The returned [`Request`][40] instance will be wrapped with [`NextRequest`][3] if -it is not already an instance of [`NextRequest`][3], i.e.: +The returned [`Request`][39] instance will be wrapped with [`NextRequest`][1] if +it is not already an instance of [`NextRequest`][1], i.e.: ```typescript const returnedRequest = (await requestPatcher?.(request)) || request; @@ -570,7 +574,7 @@ await testApiHandler({ > \[!NOTE]\ > Unlike the Pages Router's `NextApiRequest` type, the App Router's `NextRequest` -> class [does not support relative URLs][41]. Therefore, whenever you pass a relative +> class [does not support relative URLs][40]. Therefore, whenever you pass a relative > url string via the `url` shorthand (e.g. `{ url: '/my-url?some=query' }`), NTARH > will wrap that url like so: `new URL(url, 'ntarh://')`. In this case, your requests > will have urls like `ntarh:///my-url?some=query`. @@ -588,9 +592,9 @@ which is executed after NTARH does URL normalization. #### 🔷 Using `pagesHandler` -> ⪢ API reference: [`requestPatcher`][42], [`url`][43] +> ⪢ API reference: [`requestPatcher`][41], [`url`][42] -`requestPatcher` is a function that receives an [`IncomingMessage`][44]. Use +`requestPatcher` is a function that receives an [`IncomingMessage`][43]. Use this function to modify the request _before_ it's injected into Next.js's resolver. @@ -603,30 +607,30 @@ await testApiHandler({ }); ``` -Note that, unlike with [the `URL` class][45], the `url` string can be relative. +Note that, unlike with [the `URL` class][44], the `url` string can be relative. ### `responsePatcher` #### 💎 Using `appHandler` -> ⪢ API reference: [`responsePatcher`][46] +> ⪢ API reference: [`responsePatcher`][45] -`responsePatcher` is a function that receives the [`Response`][47] object -returned from `appHandler` and returns a [`Response`][47] instance. Use this +`responsePatcher` is a function that receives the [`Response`][46] object +returned from `appHandler` and returns a [`Response`][46] instance. Use this function to edit the response _after_ your handler runs but _before_ it's processed by the server. #### 🔷 Using `pagesHandler` -> ⪢ API reference: [`responsePatcher`][48] +> ⪢ API reference: [`responsePatcher`][47] -`responsePatcher` is a function that receives a [`ServerResponse`][49] object. +`responsePatcher` is a function that receives a [`ServerResponse`][48] object. Use this function to edit the response _before_ it's injected into the handler. ### `paramsPatcher` (`params`) `paramsPatcher` is a function that receives an object representing "processed" -[dynamic segments][50] (aka: routes, slugs). +[dynamic segments][49] (aka: routes, slugs). For example, to test a handler normally accessible from `/api/user/:id` requires passing that handler a value for the "id" dynamic segment: @@ -662,46 +666,46 @@ await testApiHandler({ #### 💎 Using `appHandler` -> ⪢ API reference: [`paramsPatcher`][51], [`params`][52] +> ⪢ API reference: [`paramsPatcher`][50], [`params`][51] If both `paramsPatcher` and the `params` shorthand are used, `paramsPatcher` will receive `params` as its first argument. -> Route parameters should not be confused with [query string parameters][53], +> Route parameters should not be confused with [query string parameters][52], > which are automatically parsed out from the url and made available via the -> [`NextRequest`][3] argument passed to your handler. +> [`NextRequest`][1] argument passed to your handler. #### 🔷 Using `pagesHandler` -> ⪢ API reference: [`paramsPatcher`][54], [`params`][55] +> ⪢ API reference: [`paramsPatcher`][53], [`params`][54] If both `paramsPatcher` and the `params` shorthand are used, `paramsPatcher` will receive an object like `{ ...queryStringURLParams, ...params }` as its first argument. -> Route parameters should not be confused with [query string parameters][53], +> Route parameters should not be confused with [query string parameters][52], > which are automatically parsed out from the url and added to the `params` > object before `paramsPatcher` is evaluated. ## Examples What follows are several examples that demonstrate using NTARH with the [App -Router][56] and the [Pages Router][57]. +Router][55] and the [Pages Router][56]. -Check out [the tests][58] for even more examples. +Check out [the tests][57] for even more examples. ### Using the App Router -These examples use Next.js's [App Router][59] API. +These examples use Next.js's [App Router][58] API. #### Testing Apollo's Official Next.js Integration @ `app/api/graphql` This example is based on [the official Apollo Next.js App Router -integration][60]. You can run it yourself by copying and pasting the following +integration][59]. You can run it yourself by copying and pasting the following commands into your terminal. > The following should be run in a nix-like environment. On Windows, that's -> [WSL][61]. Requires `curl`, `node`, and `git`. +> [WSL][60]. Requires `curl`, `node`, and `git`. ```bash mkdir -p /tmp/ntarh-test/test @@ -715,8 +719,8 @@ npx jest ``` This script creates a new temporary directory, installs NTARH and configures -dependencies, downloads the [app route][62] and [jest test][63] files shown -below, and runs the test using [jest][64]. +dependencies, downloads the [app route][61] and [jest test][62] files shown +below, and runs the test using [jest][63]. The following is our new app route: @@ -796,8 +800,8 @@ describe('my-test (app router)', () => { #### Testing Clerk's Official Next.js Integration @ `app/api/authed` Suppose we created a new _authenticated_ API endpoint at `app/api/authed` by -[cloning the Clerk App Router demo repo][65] and following [Clerk's quick-start -guide for Next.js][66]: +[cloning the Clerk App Router demo repo][64] and following [Clerk's quick-start +guide for Next.js][65]: ```typescript /* File: app/api/authed/route.ts */ @@ -870,7 +874,7 @@ it('returns isAuthed: false and nothing else when unauthenticated', async () => If you're feeling more adventurous, you can transform this unit test into an _integration_ test (like the Apollo example above) by calling Clerk's -[`authMiddleware`][67] function in `appHandler` instead of mocking +[`authMiddleware`][66] function in `appHandler` instead of mocking `@clerk/nextjs`: ```typescript @@ -931,12 +935,12 @@ it('returns isAuthed: true and a userId when authenticated', async () => { /* ... */ ``` -You can also try calling [`authMiddleware`][67] in `requestPatcher`; however, +You can also try calling [`authMiddleware`][66] in `requestPatcher`; however, Clerk's middleware does its magic by importing the `headers` helper function from `'next/headers'`, and **only functions invoked within `appHandler` have access to the storage context that allows Next.js's helper functions to work**. -For insight into what you'd need to do to make [`authMiddleware`][67] callable -in `requestPatcher`, check out [Clerk's own tests][68]. +For insight into what you'd need to do to make [`authMiddleware`][66] callable +in `requestPatcher`, check out [Clerk's own tests][67]. #### Testing an Unreliable Handler on the Edge @ `app/api/unreliable` @@ -1023,15 +1027,15 @@ it('injects contrived errors at the required rate', async () => { ### Using the Pages Router -These examples use Next.js's [Pages Router][69] API. +These examples use Next.js's [Pages Router][68] API. #### Testing Next.js's Official Apollo Example @ `pages/api/graphql` -This example uses the [official Next.js Apollo demo][70]. You can easily run it +This example uses the [official Next.js Apollo demo][69]. You can easily run it yourself by copying and pasting the following commands into your terminal. > The following should be run in a nix-like environment. On Windows, that's -> [WSL][61]. Requires `curl`, `node`, and `git`. +> [WSL][60]. Requires `curl`, `node`, and `git`. ```bash git clone --depth=1 https://github.com/vercel/next.js /tmp/ntarh-test @@ -1048,13 +1052,13 @@ curl -o test/integration.test.js https://raw.githubusercontent.com/Xunnamius/nex npx jest ``` -This script clones [the Next.js repository][71], installs NTARH and configures -dependencies, downloads the [jest test][72] file shown below, and runs it using -[jest][64] to ensure our route integrates with Apollo correctly. +This script clones [the Next.js repository][70], installs NTARH and configures +dependencies, downloads the [jest test][71] file shown below, and runs it using +[jest][63] to ensure our route integrates with Apollo correctly. > \[!IMPORTANT]\ -> Note that passing the [route configuration object][73] (imported below as `config`) -> through to NTARH and setting `request.url` to the proper value [may be necessary][74] +> Note that passing the [route configuration object][72] (imported below as `config`) +> through to NTARH and setting `request.url` to the proper value [may be necessary][73] > when testing Apollo endpoints using the Pages Router. ```typescript @@ -1305,23 +1309,23 @@ Further documentation can be found under [`docs/`][x-repo-docs]. Since NTARH is meant for unit testing API routes rather than faithfully recreating Next.js functionality, NTARH's feature set comes with some caveats. Namely: no Next.js features will be available that are external to processing -API routes and executing their handlers. This includes [middleware][75] and -`NextResponse.next` (see [`requestPatcher`][76] if you need to mutate the -`Request` before it gets to the handler under test), [metadata][77], [static -assets][78], [OpenTelemetry][79] and [instrumentation][80], [caching][81], -[styling][82], [server actions and mutations][83], [helper functions][5] +API routes and executing their handlers. This includes [middleware][74] and +`NextResponse.next` (see [`requestPatcher`][75] if you need to mutate the +`Request` before it gets to the handler under test), [metadata][76], [static +assets][77], [OpenTelemetry][78] and [instrumentation][79], [caching][80], +[styling][81], [server actions and mutations][82], [helper functions][3] (except: `cookies`, `fetch` (global), `headers`, `NextRequest`, `NextResponse`, `notFound`, `permanentRedirect`, `redirect`, and `userAgent`), and anything -related to React or [components][84]. +related to React or [components][83]. NTARH is for testing your API route handlers only. -Further, any support NTARH appears to have for any "[edge runtime][85]" (or any -other runtime) beyond what is provided by [`AppRouteRouteModule`][86] is merely +Further, any support NTARH appears to have for any "[edge runtime][84]" (or any +other runtime) beyond what is provided by [`AppRouteRouteModule`][85] is merely cosmetic. **Your tests will always run in Node.js** (or your runner of choice) and never in a different runtime, realm, or VM. This means unit testing like with NTARH must be done in addition to, and not in lieu of, more holistic -testing practices (e.g. [end-to-end][87]). +testing practices (e.g. [end-to-end][86]). If you're having trouble with your App Router and/or Edge Runtime routes, consider [opening a new issue][x-repo-choose-new-issue]! @@ -1332,18 +1336,18 @@ consider [opening a new issue][x-repo-choose-new-issue]! > (via `npm run dev` or something similar), the middleware will still run on > Node.js. > -> Next.js's middleware limitation is discussed at length [here][88]. +> Next.js's middleware limitation is discussed at length [here][87]. #### Working around the App Router Patching the Global `fetch` Function Next.js's current App Router implementation mutates the global `fetch` function, -redefining it entirely. This can cause [problems][89] in testing environments +redefining it entirely. This can cause [problems][88] in testing environments where the global `fetch` is to be mocked by something else. Internally, NTARH sidesteps this issue entirely by caching the value of `globalThis.fetch` upon import. This also means NTARH completely sidesteps other tools that rely on interception through rewriting the global `fetch` function, -such as [Mock Service Worker (MSW)][90]. We still include the MSW bypass headers +such as [Mock Service Worker (MSW)][89]. We still include the MSW bypass headers with NTARH requests since we cannot guarantee that NTARH will not be imported _after_ MSW has finished patching global `fetch`. @@ -1373,21 +1377,21 @@ available globally and _immediately_. Unfortunately, Node.js does not place NTARH handles this by ensuring `AsyncLocalStorage` is added to `globalThis` before Next.js needs it. This is why [NTARH should always be the very first -import in any test file][13]. +import in any test file][12]. ### Legacy Runtime Support As of version `4.0.0`, NTARH supports both the App Router (for `next@>=14.0.4`) and the "legacy" Pages Router Next.js APIs. However, due to the code churn with `next@13`, NTARH's support for the App Router begins at `next@14.0.4`. See -[here][10] and [here][91] for more information. +[here][8] and [here][90] for more information. Additionally, as of version `2.1.0`, NTARH's Pages Router support is fully backwards compatible with Next.js going _allll_ the way back to `next@9.0.0` -[when API routes were first introduced][92]! +[when API routes were first introduced][91]! If you're working with the Pages Router and `next@<9.0.6` (so: [before -`next-server` was merged into `next`][93]), you might need to install +`next-server` was merged into `next`][92]), you might need to install `next-server` manually: ```shell @@ -1396,14 +1400,39 @@ npm install --save-dev next-server Similarly, if you are using `npm@<7` or `node@<15`, you must install Next.js _and its peer dependencies_ manually. This is because [`npm@<7` does not install -peer dependencies by default][94]. +peer dependencies by default][93]. ```shell npm install --save-dev next@latest react ``` > If you're also using an older version of Next.js, ensure you install the [peer -> dependencies (like `react`) that your specific Next.js version requires][95]! +> dependencies (like `react`) that your specific Next.js version requires][94]! + +### Jsdom Support + +Note that [jsdom does not support global fetch natively][95]. This should not be +an issue, however, since neither your API code nor your API test code should be +executed in a browser-like environment. + +For projects configured to use jsdom by default, you can use an annotation to +switch environments only in the files housing your API tests: + +```typescript +/** + * @jest-environment node + */ +// ⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆ + +import { testApiHandler } from 'next-test-api-route-handler'; + +test('use the node test environment for all tests in this file', () => { + //... +}); +``` + +If you're dead set on using jsdom over the node testing environment with NTARH, +see [here][96] and [here][97] for workarounds. ### Inspiration @@ -1423,8 +1452,8 @@ ballooning the execution time of the tests. That is: no spinning up the entire Next.js runtime just to run a single test in isolation. It doesn't seem like it'd be such a lift to surface a wrapped version of the -Pages Router's [`apiResolver`][96] function and a pared-down subclass of the App -Router's [`AppRouteRouteModule`][86], both accessible with something like +Pages Router's [`apiResolver`][98] function and a pared-down subclass of the App +Router's [`AppRouteRouteModule`][85], both accessible with something like `import { ... } from 'next/test'`. This is essentially what NTARH does. ### Published Package Details @@ -1614,138 +1643,139 @@ specification. Contributions of any kind welcome! https://github.com/xunnamius/next-test-api-route-handler/compare [x-repo-sponsor]: https://github.com/sponsors/Xunnamius [x-repo-support]: /.github/SUPPORT.md -[1]: - https://github.com/Xunnamius/next-test-api-route-handler/tree/v3.2.0#next-test-api-route-handler -[2]: - https://github.com/Xunnamius/next-test-api-route-handler/discussions/953#migration-guide -[3]: https://nextjs.org/docs/app/api-reference/functions/next-request -[4]: https://nextjs.org/docs/app/building-your-application/routing -[5]: https://nextjs.org/docs/app/api-reference/functions -[6]: https://nextjs.org/docs/api-routes/introduction -[7]: https://nextjs.org/docs/basic-features/typescript#api-routes -[8]: +[1]: https://nextjs.org/docs/app/api-reference/functions/next-request +[2]: https://nextjs.org/docs/app/building-your-application/routing +[3]: https://nextjs.org/docs/app/api-reference/functions +[4]: https://nextjs.org/docs/api-routes/introduction +[5]: https://nextjs.org/docs/basic-features/typescript#api-routes +[6]: https://github.com/Xunnamius/next-test-api-route-handler/actions/workflows/is-next-compat.yml -[9]: https://github.com/vercel/next.js/releases -[10]: +[7]: https://github.com/vercel/next.js/releases +[8]: https://github.com/Xunnamius/next-test-api-route-handler/issues/999#issuecomment-1956787672 -[11]: #legacy-runtime-support -[12]: #working-around-global-asynclocalstorage-availability -[13]: #usage -[14]: +[9]: #legacy-runtime-support +[10]: #jsdom-support +[11]: #working-around-global-asynclocalstorage-availability +[12]: #usage +[13]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#appHandler -[15]: +[14]: https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/web/http.ts#L5 -[16]: +[15]: https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/route-modules/app-route/module.ts#L75 -[17]: +[16]: https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/route-modules/app-route/module.ts#L84 -[18]: +[17]: https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/route-modules/app-route/module.ts#L100C4-L100C4 -[19]: #rejectonhandlererror -[20]: #working-around-the-app-router-patching-the-global-fetch-function -[21]: +[18]: #rejectonhandlererror +[19]: #working-around-the-app-router-patching-the-global-fetch-function +[20]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#pagesHandler -[22]: +[21]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInit.md#test -[23]: https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch -[24]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#resource -[25]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#options -[26]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#redirect -[27]: https://mswjs.io -[28]: +[22]: https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch +[23]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#resource +[24]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#options +[25]: https://developer.mozilla.org/en-US/docs/Web/API/fetch#redirect +[26]: https://mswjs.io +[27]: https://github.com/mswjs/msw/blob/a037e3a3f4f4d4cc712d2b3867b3410e4bcfaad6/src/core/bypass.ts#L33C29-L33C44 -[29]: https://nextjs.org/docs/app/api-reference/functions/redirect -[30]: +[28]: https://nextjs.org/docs/app/api-reference/functions/redirect +[29]: https://nextjs.org/docs/pages/building-your-application/routing/api-routes#redirects-to-a-specified-path-or-url -[31]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie -[32]: https://www.npmjs.com/package/cookie -[33]: ./test/unit-index.test.ts -[34]: +[30]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie +[31]: https://www.npmjs.com/package/cookie +[32]: ./test/unit-index.test.ts +[33]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInit.md#rejectOnHandlerError -[35]: +[34]: https://github.com/vercel/next.js/blob/f4e49377ac3ca2807f773bc1dcd5375c89bde9ef/packages/next/server/api-utils.ts#L134 -[36]: #testing-nextjss-official-apollo-example--pagesapigraphql -[37]: #testing-an-authenticated-flight-search-handler--pagesapiv3flightssearch -[38]: +[35]: #testing-nextjss-official-apollo-example--pagesapigraphql +[36]: #testing-an-authenticated-flight-search-handler--pagesapiv3flightssearch +[37]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#requestpatcher -[39]: +[38]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#url -[40]: https://developer.mozilla.org/en-US/docs/Web/API/Request -[41]: https://nextjs.org/docs/messages/middleware-relative-urls -[42]: +[39]: https://developer.mozilla.org/en-US/docs/Web/API/Request +[40]: https://nextjs.org/docs/messages/middleware-relative-urls +[41]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#requestpatcher -[43]: +[42]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#url -[44]: https://nodejs.org/api/http.html#http_class_http_incomingmessage -[45]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#url -[46]: +[43]: https://nodejs.org/api/http.html#http_class_http_incomingmessage +[44]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#url +[45]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#responsePatcher -[47]: https://developer.mozilla.org/en-US/docs/Web/API/Response -[48]: +[46]: https://developer.mozilla.org/en-US/docs/Web/API/Response +[47]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#responsePatcher -[49]: https://nodejs.org/api/http.html#http_class_http_serverresponse -[50]: +[48]: https://nodejs.org/api/http.html#http_class_http_serverresponse +[49]: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes -[51]: +[50]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#paramsPatcher -[52]: +[51]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitAppRouter.md#params -[53]: https://en.wikipedia.org/wiki/Query_string -[54]: +[52]: https://en.wikipedia.org/wiki/Query_string +[53]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#paramsPatcher -[55]: +[54]: https://github.com/Xunnamius/next-test-api-route-handler/blob/main/docs/interfaces/NtarhInitPagesRouter.md#params -[56]: #using-the-app-router -[57]: #using-the-pages-router -[58]: test/unit-index.test.ts -[59]: https://nextjs.org/docs/app -[60]: +[55]: #using-the-app-router +[56]: #using-the-pages-router +[57]: test/unit-index.test.ts +[58]: https://nextjs.org/docs/app +[59]: https://www.npmjs.com/package/@as-integrations/next/v/3.0.0#app-router-route-handlers -[61]: https://docs.microsoft.com/en-us/windows/wsl/install-win10 -[62]: ./apollo_test_raw_app_route -[63]: ./apollo_test_raw_app_test -[64]: https://www.npmjs.com/package/jest -[65]: https://github.com/clerk/clerk-nextjs-demo-app-router -[66]: https://clerk.com/docs/quickstarts/nextjs -[67]: https://clerk.com/docs/references/nextjs/auth-middleware -[68]: +[60]: https://docs.microsoft.com/en-us/windows/wsl/install-win10 +[61]: ./apollo_test_raw_app_route +[62]: ./apollo_test_raw_app_test +[63]: https://www.npmjs.com/package/jest +[64]: https://github.com/clerk/clerk-nextjs-demo-app-router +[65]: https://clerk.com/docs/quickstarts/nextjs +[66]: https://clerk.com/docs/references/nextjs/auth-middleware +[67]: https://github.com/clerk/javascript/blob/434a96ebefc550b726b417788b7bae9e41791408/packages/nextjs/src/server/authMiddleware.test.ts#L4 -[69]: https://nextjs.org/docs/pages -[70]: +[68]: https://nextjs.org/docs/pages +[69]: https://github.com/vercel/next.js/tree/deprecated-main/examples/api-routes-apollo-server-and-client -[71]: https://github.com/vercel/next.js -[72]: ./apollo_test_raw -[73]: https://nextjs.org/docs/api-routes/api-middlewares#custom-config -[74]: https://github.com/Xunnamius/next-test-api-route-handler/issues/56 -[75]: https://nextjs.org/docs/app/building-your-application/routing/middleware -[76]: #requestpatcher-url -[77]: https://nextjs.org/docs/app/building-your-application/optimizing#metadata -[78]: +[70]: https://github.com/vercel/next.js +[71]: ./apollo_test_raw +[72]: https://nextjs.org/docs/api-routes/api-middlewares#custom-config +[73]: https://github.com/Xunnamius/next-test-api-route-handler/issues/56 +[74]: https://nextjs.org/docs/app/building-your-application/routing/middleware +[75]: #requestpatcher-url +[76]: https://nextjs.org/docs/app/building-your-application/optimizing#metadata +[77]: https://nextjs.org/docs/app/building-your-application/optimizing#static-assets -[79]: +[78]: https://nextjs.org/docs/pages/building-your-application/optimizing/open-telemetry -[80]: +[79]: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation -[81]: https://nextjs.org/docs/app/building-your-application/caching -[82]: https://nextjs.org/docs/app/building-your-application/styling -[83]: +[80]: https://nextjs.org/docs/app/building-your-application/caching +[81]: https://nextjs.org/docs/app/building-your-application/styling +[82]: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations -[84]: https://nextjs.org/docs/app/api-reference/components -[85]: +[83]: https://nextjs.org/docs/app/api-reference/components +[84]: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#runtime -[86]: +[85]: https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/route-modules/app-route/module.ts#L118C24-L118C24 -[87]: +[86]: https://nextjs.org/docs/app/building-your-application/testing#types-of-tests -[88]: https://github.com/vercel/next.js/discussions/46722 -[89]: https://github.com/mswjs/msw/issues/1644 -[90]: https://github.com/mswjs/msw -[91]: https://github.com/Xunnamius/next-test-api-route-handler/discussions/953 -[92]: https://nextjs.org/blog/next-9 -[93]: https://github.com/vercel/next.js/pull/8613 -[94]: +[87]: https://github.com/vercel/next.js/discussions/46722 +[88]: https://github.com/mswjs/msw/issues/1644 +[89]: https://github.com/mswjs/msw +[90]: https://github.com/Xunnamius/next-test-api-route-handler/discussions/953 +[91]: https://nextjs.org/blog/next-9 +[92]: https://github.com/vercel/next.js/pull/8613 +[93]: https://github.blog/2021-02-02-npm-7-is-now-generally-available#peer-dependencies -[95]: +[94]: https://github.com/vercel/next.js/blob/v9.0.0/packages/next/package.json#L106-L109 -[96]: +[95]: https://github.com/jestjs/jest/issues/13834#issuecomment-1407375787 +[96]: https://github.com/jsdom/jsdom/issues/1724 +[97]: + https://stackoverflow.com/questions/74945569/cannot-access-built-in-node-js-fetch-function-from-jest-tests +[98]: https://github.com/vercel/next.js/blob/90f95399ddfd036624c69b09910f40fa36c00ac2/packages/next/src/server/api-utils/node/api-resolver.ts#L321