@@ -647,8 +647,8 @@ These examples use Next.js's [App Router][51] API.
647
647
#### Testing Apollo's Official Next.js Integration @ ` app/api/graphql `
648
648
649
649
This example is based on [ the official Apollo Next.js App Router
650
- integration] [ 52 ] . You can easily run it yourself by copying and pasting the
651
- following commands into your terminal.
650
+ integration] [ 52 ] . You can run it yourself by copying and pasting the following
651
+ commands into your terminal.
652
652
653
653
> The following should be run in a nix-like environment. On Windows, that's
654
654
> [ WSL] [ 53 ] . Requires ` curl ` , ` node ` , and ` git ` .
@@ -660,13 +660,15 @@ npm install --force next @apollo/server @as-integrations/next graphql-tag next-t
660
660
echo ' module.exports={"presets":["next/babel"]};' > babel.config.js
661
661
mkdir -p app/api/graphql
662
662
curl -o app/api/graphql/route.js https://raw.githubusercontent.com/Xunnamius/next-test-api-route-handler/main/apollo_test_raw_app_route
663
- curl -o test/my .test.js https://raw.githubusercontent.com/Xunnamius/next-test-api-route-handler/main/apollo_test_raw_app_test
663
+ curl -o test/integration .test.js https://raw.githubusercontent.com/Xunnamius/next-test-api-route-handler/main/apollo_test_raw_app_test
664
664
npx jest
665
665
```
666
666
667
- The above script creates a new temporary directory, installs NTARH and
668
- configures dependencies, downloads the [ app route] [ 54 ] and [ jest test] [ 55 ] files
669
- shown below, and runs the test using [ jest] [ 56 ] .
667
+ This script creates a new temporary directory, installs NTARH and configures
668
+ dependencies, downloads the [ app route] [ 54 ] and [ jest test] [ 55 ] files shown
669
+ below, and runs the test using [ jest] [ 56 ] .
670
+
671
+ The following is our new app route:
670
672
671
673
``` typescript
672
674
/* File: app/api/graphql/route.js */
@@ -697,8 +699,11 @@ const handler = startServerAndCreateNextHandler(server);
697
699
export { handler as GET , handler as POST };
698
700
```
699
701
702
+ And with the following jest test, we ensure our route integrates with Apollo
703
+ correctly:
704
+
700
705
``` typescript
701
- /* File: tests/my .test.js */
706
+ /* File: tests/integration .test.js */
702
707
703
708
import { testApiHandler } from ' next-test-api-route-handler' ;
704
709
// Import the handler under test from the app/api directory
@@ -740,27 +745,84 @@ describe('my-test (app router)', () => {
740
745
741
746
#### Testing Clerk's Official Next.js Integration @ ` app/api/authed `
742
747
743
- Suppose we have an _ authenticated_ API endpoint built using [ Clerk's quick-start
744
- guide for Next.js] [ 57 ] , or perhaps [ from their official demo repo] [ 58 ] .
748
+ Suppose we created a new _ authenticated_ API endpoint at ` app/api/authed ` using
749
+ [ Clerk's quick-start guide for Next.js] [ 57 ] :
750
+
751
+ ``` typescript
752
+ /* File: app/api/authed/route.ts */
753
+
754
+ import { auth } from ' @clerk/nextjs' ;
755
+
756
+ export async function GET() {
757
+ const { userId } = auth ();
758
+ return Response .json ({ isAuthed: !! userId , userId });
759
+ }
760
+ ```
745
761
746
- How might we test that this endpoint behaves as we expect?
762
+ How might we test that this endpoint functions as we expect?
747
763
748
764
``` typescript
749
765
/* File: test/unit.test.ts */
750
766
767
+ import * as Clerk from ' @clerk/nextjs' ;
751
768
import { testApiHandler } from ' next-test-api-route-handler' ;
752
- import * as appHandler from ' ../app/api/authed/route' ;
753
769
754
- it (' ' , async () => {
770
+ import * as appHandler from ' ./app/api/authed/route' ;
771
+
772
+ let mockedClerkAuthReturnValue:
773
+ | Partial <ReturnType <(typeof Clerk )[' auth' ]>>
774
+ | undefined = undefined ;
775
+
776
+ jest .mock (' @clerk/nextjs' , () => {
777
+ return {
778
+ auth() {
779
+ return mockedClerkAuthReturnValue ;
780
+ }
781
+ };
782
+ });
783
+
784
+ afterEach (() => {
785
+ mockedClerkAuthReturnValue = undefined ;
786
+ });
787
+
788
+ it (' returns isAuthed: true and a userId when authenticated' , async () => {
755
789
expect .hasAssertions ();
756
790
791
+ mockedClerkAuthReturnValue = { userId: ' winning' };
792
+
757
793
await testApiHandler ({
758
794
appHandler ,
759
- test : async ({ fetch }) => // TODO
795
+ test : async ({ fetch }) => {
796
+ await expect ((await fetch ()).json ()).resolves .toStrictEqual ({
797
+ isAuthed: true ,
798
+ userId: ' winning'
799
+ });
800
+ }
801
+ });
802
+ });
803
+
804
+ it (' returns isAuthed: false and nothing else when unauthenticated' , async () => {
805
+ expect .hasAssertions ();
806
+
807
+ mockedClerkAuthReturnValue = { userId: null };
808
+
809
+ await testApiHandler ({
810
+ appHandler ,
811
+ test : async ({ fetch }) => {
812
+ await expect ((await fetch ()).json ()).resolves .toStrictEqual ({
813
+ isAuthed: false ,
814
+ userId: null
815
+ });
816
+ }
760
817
});
761
818
});
762
819
```
763
820
821
+ If you're feeling more adventurous, you can turn this unit test into an
822
+ _ integration_ test by calling [ ` authMiddleware ` ] [ 58 ] in ` requestPatcher ` instead
823
+ of mocking ` @clerk/nextjs ` . For insight into what you'd need to mock to make
824
+ this work, check out [ Clerk's own tests] [ 59 ] .
825
+
764
826
#### Testing an Unreliable Handler on the Edge @ ` app/api/unreliable `
765
827
766
828
Suppose we have an API endpoint we use to test our application's error handling.
@@ -846,11 +908,11 @@ it('injects contrived errors at the required rate', async () => {
846
908
847
909
### Using the Pages Router
848
910
849
- These examples use Next.js's [ Pages Router] [ 59 ] API.
911
+ These examples use Next.js's [ Pages Router] [ 60 ] API.
850
912
851
913
#### Testing Next.js's Official Apollo Example @ ` pages/api/graphql `
852
914
853
- This example uses the [ official Next.js Apollo demo] [ 60 ] . You can easily run it
915
+ This example uses the [ official Next.js Apollo demo] [ 61 ] . You can easily run it
854
916
yourself by copying and pasting the following commands into your terminal.
855
917
856
918
> The following should be run in a nix-like environment. On Windows, that's
@@ -867,21 +929,21 @@ npm install --force next-test-api-route-handler jest babel-jest @babel/core @bab
867
929
# npm install --force [email protected] next-server
868
930
echo ' module.exports={"presets":["next/babel"]};' > babel.config.js
869
931
mkdir test
870
- curl -o test/my .test.js https://raw.githubusercontent.com/Xunnamius/next-test-api-route-handler/main/apollo_test_raw
932
+ curl -o test/integration .test.js https://raw.githubusercontent.com/Xunnamius/next-test-api-route-handler/main/apollo_test_raw
871
933
npx jest
872
934
```
873
935
874
- The above script clones [ the Next.js repository] [ 61 ] , installs NTARH and
875
- configures dependencies, downloads the [ jest test] [ 62 ] file shown below, and
876
- runs it using [ jest] [ 56 ] .
936
+ This script clones [ the Next.js repository] [ 62 ] , installs NTARH and configures
937
+ dependencies, downloads the [ jest test] [ 63 ] file shown below, and runs it using
938
+ [ jest] [ 56 ] to ensure our route integrates with Apollo correctly .
877
939
878
940
> \[ !IMPORTANT] \
879
- > Note that passing the [ route configuration object] [ 63 ] (imported below as ` config ` )
880
- > through to NTARH and setting ` request.url ` to the proper value is ** [ crucial ] [ 64 ] **
881
- > when testing Apollo endpoints using the Pages Router!
941
+ > Note that passing the [ route configuration object] [ 64 ] (imported below as ` config ` )
942
+ > through to NTARH and setting ` request.url ` to the proper value [ may be necessary ] [ 65 ]
943
+ > when testing Apollo endpoints using the Pages Router.
882
944
883
945
``` typescript
884
- /* File: examples/api-routes-apollo-server-and-client/tests/my .test.js */
946
+ /* File: examples/api-routes-apollo-server-and-client/tests/integration .test.js */
885
947
886
948
import { testApiHandler } from ' next-test-api-route-handler' ;
887
949
// Import the handler under test from the pages/api directory
@@ -1128,52 +1190,60 @@ Further documentation can be found under [`docs/`][x-repo-docs].
1128
1190
Since NTARH is meant for unit testing API routes rather than faithfully
1129
1191
recreating Next.js functionality, NTARH's feature set comes with some caveats.
1130
1192
Namely: no Next.js features will be available that are external to processing
1131
- API routes and executing their handlers. This includes [ middleware] [ 65 ] (see
1132
- [ ` requestPatcher ` ] [ 66 ] if you need to mutate the ` Request ` before it gets to the
1133
- handler under test), [ metadata] [ 67 ] , [ static assets] [ 68 ] , [ OpenTelemetry] [ 69 ]
1134
- and [ instrumentation] [ 70 ] , [ caching] [ 71 ] , [ styling] [ 72 ] , [ server actions and
1135
- mutations] [ 73 ] , [ helper functions] [ 5 ] (except: ` cookies ` , ` fetch ` (global),
1193
+ API routes and executing their handlers. This includes [ middleware] [ 66 ] (see
1194
+ [ ` requestPatcher ` ] [ 67 ] if you need to mutate the ` Request ` before it gets to the
1195
+ handler under test), [ metadata] [ 68 ] , [ static assets] [ 69 ] , [ OpenTelemetry] [ 70 ]
1196
+ and [ instrumentation] [ 71 ] , [ caching] [ 72 ] , [ styling] [ 73 ] , [ server actions and
1197
+ mutations] [ 74 ] , [ helper functions] [ 5 ] (except: ` cookies ` , ` fetch ` (global),
1136
1198
` headers ` , ` NextRequest ` /` NextResponse ` , ` notFound ` , ` permanentRedirect ` ,
1137
- ` redirect ` , and ` userAgent ` ), and anything related to React or [ components] [ 74 ] .
1199
+ ` redirect ` , and ` userAgent ` ), and anything related to React or [ components] [ 75 ] .
1138
1200
1139
1201
NTARH is for testing your API route handlers only.
1140
1202
1141
- Further, any support NTARH appears to have for any "[ edge runtime] [ 75 ] " (or any
1142
- other runtime) beyond what is provided by [ ` AppRouteRouteModule ` ] [ 76 ] is merely
1203
+ Further, any support NTARH appears to have for any "[ edge runtime] [ 76 ] " (or any
1204
+ other runtime) beyond what is provided by [ ` AppRouteRouteModule ` ] [ 77 ] is merely
1143
1205
cosmetic. ** Your tests will always run in Node.js** (or your runner of choice)
1144
1206
and never in a different runtime, realm, or VM. This means unit testing like
1145
1207
with NTARH must be done in addition to, and not in lieu of, more holistic
1146
- testing practices (e.g. [ end-to-end] [ 77 ] ).
1208
+ testing practices (e.g. [ end-to-end] [ 78 ] ).
1147
1209
1148
1210
If you're having trouble with your App Router and/or Edge Runtime routes,
1149
1211
consider [ opening a new issue] [ x-repo-choose-new-issue ] !
1150
1212
1213
+ > Also note that Next.js's middleware ** only supports the Edge runtime** , even
1214
+ > if the Next.js application is being run entirely by Node.js. This is an
1215
+ > artificial constraint imposed by Next.js; when running the middleware locally
1216
+ > (via ` npm run dev ` or something similar), the middleware will still run on
1217
+ > Node.js.
1218
+ >
1219
+ > Next.js's middleware limitation is discussed at length [ here] [ 79 ] .
1220
+
1151
1221
### Legacy Runtime Support
1152
1222
1153
1223
As of version ` 4.0.0 ` , NTARH supports both the App Router (for ` next@>=14.0.4 ` )
1154
1224
and the "legacy" Pages Router Next.js APIs.
1155
1225
1156
1226
Additionally, as of version ` 2.1.0 ` , NTARH is fully backwards compatible with
1157
1227
Next.js going
_ allll
_ the way back to
` [email protected] ` [ when API routes were first
1158
- introduced] [ 78 ] !
1228
+ introduced] [ 80 ] !
1159
1229
1160
1230
If you're working with ` next@<9.0.6 ` (so: [ before ` next-server ` was merged into
1161
- ` next ` ] [ 79 ] ), you might need to install ` next-server ` manually:
1231
+ ` next ` ] [ 81 ] ), you might need to install ` next-server ` manually:
1162
1232
1163
1233
``` shell
1164
1234
npm install --save-dev next-server
1165
1235
```
1166
1236
1167
1237
Similarly, if you are using ` npm@<7 ` or ` node@<15 ` , you must install Next.js
1168
1238
_ and its peer dependencies_ manually. This is because [ ` npm@<7 ` does not install
1169
- peer dependencies by default] [ 80 ] .
1239
+ peer dependencies by default] [ 82 ] .
1170
1240
1171
1241
``` shell
1172
1242
npm install --save-dev next@latest react
1173
1243
```
1174
1244
1175
1245
> If you're also using an older version of Next.js, ensure you install the [ peer
1176
- > dependencies (like ` react ` ) that your specific Next.js version requires] [ 81 ] !
1246
+ > dependencies (like ` react ` ) that your specific Next.js version requires] [ 83 ] !
1177
1247
1178
1248
### Inspiration
1179
1249
@@ -1193,8 +1263,8 @@ ballooning the execution time of the tests. That is: no spinning up the entire
1193
1263
Next.js runtime just to run a single test in isolation.
1194
1264
1195
1265
It doesn't seem like it'd be such a lift to surface a wrapped version of the
1196
- Pages Router's [ ` apiResolver ` ] [ 82 ] function and a pared-down subclass of the App
1197
- Router's [ ` AppRouteRouteModule ` ] [ 76 ] , both accessible with something like
1266
+ Pages Router's [ ` apiResolver ` ] [ 84 ] function and a pared-down subclass of the App
1267
+ Router's [ ` AppRouteRouteModule ` ] [ 77 ] , both accessible with something like
1198
1268
` import { ... } from 'next/test' ` . This is essentially what NTARH does.
1199
1269
1200
1270
### Published Package Details
@@ -1458,39 +1528,42 @@ specification. Contributions of any kind welcome!
1458
1528
[ 55 ] : ./apollo_test_raw_app_test
1459
1529
[ 56 ] : https://www.npmjs.com/package/jest
1460
1530
[ 57 ] : https://clerk.com/docs/quickstarts/nextjs
1461
- [ 58 ] : https://github.com/clerk/clerk-nextjs-demo-app-router
1462
- [ 59 ] : https://nextjs.org/docs/pages
1463
- [ 60] :
1531
+ [ 58 ] : https://clerk.com/docs/references/nextjs/auth-middleware
1532
+ [ 59] :
1533
+ https://github.com/clerk/javascript/blob/434a96ebefc550b726b417788b7bae9e41791408/packages/nextjs/src/server/authMiddleware.test.ts#L4
1534
+ [ 60 ] : https://nextjs.org/docs/pages
1535
+ [ 61] :
1464
1536
https://github.com/vercel/next.js/tree/deprecated-main/examples/api-routes-apollo-server-and-client
1465
- [ 61 ] : https://github.com/vercel/next.js
1466
- [ 62 ] : ./apollo_test_raw
1467
- [ 63 ] : https://nextjs.org/docs/api-routes/api-middlewares#custom-config
1468
- [ 64 ] : https://github.com/Xunnamius/next-test-api-route-handler/issues/56
1469
- [ 65 ] : https://nextjs.org/docs/app/building-your-application/routing/middleware
1470
- [ 66 ] : #requestpatcher-url
1471
- [ 67 ] : https://nextjs.org/docs/app/building-your-application/optimizing#metadata
1472
- [ 68] :
1473
- https://nextjs.org/docs/app/building-your-application/optimizing#static-assets
1537
+ [ 62 ] : https://github.com/vercel/next.js
1538
+ [ 63 ] : ./apollo_test_raw
1539
+ [ 64 ] : https://nextjs.org/docs/api-routes/api-middlewares#custom-config
1540
+ [ 65 ] : https://github.com/Xunnamius/next-test-api-route-handler/issues/56
1541
+ [ 66 ] : https://nextjs.org/docs/app/building-your-application/routing/middleware
1542
+ [ 67 ] : #requestpatcher-url
1543
+ [ 68 ] : https://nextjs.org/docs/app/building-your-application/optimizing#metadata
1474
1544
[ 69] :
1475
- https://nextjs.org/docs/pages /building-your-application/optimizing/open-telemetry
1545
+ https://nextjs.org/docs/app /building-your-application/optimizing#static-assets
1476
1546
[ 70] :
1547
+ https://nextjs.org/docs/pages/building-your-application/optimizing/open-telemetry
1548
+ [ 71] :
1477
1549
https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
1478
- [ 71 ] : https://nextjs.org/docs/app/building-your-application/caching
1479
- [ 72 ] : https://nextjs.org/docs/app/building-your-application/styling
1480
- [ 73 ] :
1550
+ [ 72 ] : https://nextjs.org/docs/app/building-your-application/caching
1551
+ [ 73 ] : https://nextjs.org/docs/app/building-your-application/styling
1552
+ [ 74 ] :
1481
1553
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
1482
- [ 74 ] : https://nextjs.org/docs/app/api-reference/components
1483
- [ 75] :
1484
- https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#runtime
1554
+ [ 75 ] : https://nextjs.org/docs/app/api-reference/components
1485
1555
[ 76] :
1486
- https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/ route-modules/app-route/module.ts#L118C24-L118C24
1556
+ https://nextjs.org/docs/app/api-reference/file-conventions/ route-segment-config#runtime
1487
1557
[ 77] :
1558
+ https://github.com/vercel/next.js/blob/0aa0179246d4e59f74cd1d62e3beb8e9b670fc4e/packages/next/src/server/future/route-modules/app-route/module.ts#L118C24-L118C24
1559
+ [ 78] :
1488
1560
https://nextjs.org/docs/app/building-your-application/testing#types-of-tests
1489
- [ 78 ] : https://nextjs.org/blog/next-9
1490
- [ 79 ] : https://github.com/vercel/next.js/pull/8613
1491
- [ 80] :
1561
+ [ 79 ] : https://github.com/vercel/next.js/discussions/46722
1562
+ [ 80 ] : https://nextjs.org/blog/next-9
1563
+ [ 81 ] : https://github.com/vercel/next.js/pull/8613
1564
+ [ 82] :
1492
1565
https://github.blog/2021-02-02-npm-7-is-now-generally-available#peer-dependencies
1493
- [ 81 ] :
1566
+ [ 83 ] :
1494
1567
https://github.com/vercel/next.js/blob/v9.0.0/packages/next/package.json#L106-L109
1495
- [ 82 ] :
1568
+ [ 84 ] :
1496
1569
https://github.com/vercel/next.js/blob/90f95399ddfd036624c69b09910f40fa36c00ac2/packages/next/src/server/api-utils/node/api-resolver.ts#L321
0 commit comments