1
1
import { ReactElement } from 'react'
2
+ import { serialize as superjsonSerialize } from 'superjson'
2
3
import { rest , type ResponseResolver , type RestContext } from 'msw'
3
4
import { setupServer , type SetupServer } from 'msw/node'
4
5
import { BrowserRouter as Router } from 'react-router-dom'
@@ -9,27 +10,39 @@ import { Query } from '../../queries'
9
10
import config from '../../config'
10
11
import { HttpMethod } from '../../types'
11
12
13
+ export type Route = { method : HttpMethod ; path : string }
14
+
15
+ export type MockQuery = < Input , Output , MockOutput extends Output > (
16
+ query : Query < Input , Output > ,
17
+ resJson : MockOutput
18
+ ) => void
19
+
20
+ export type MockApi = ( route : Route , resJson : unknown ) => void
21
+
12
22
// Inspired by the Tanstack React Query helper:
13
23
// https://github.com/TanStack/query/blob/4ae99561ca3383d6de3f4aad656a49ba4a17b57a/packages/react-query/src/__tests__/utils.tsx#L7-L26
14
24
export function renderInContext ( ui : ReactElement ) : RenderResult {
15
25
const client = new QueryClient ( )
16
26
const { rerender, ...result } = render (
17
- < QueryClientProvider client = { client } > < Router > { ui } </ Router > </ QueryClientProvider >
27
+ < QueryClientProvider client = { client } >
28
+ < Router > { ui } </ Router >
29
+ </ QueryClientProvider >
18
30
)
19
31
return {
20
32
...result ,
21
33
rerender : ( rerenderUi : ReactElement ) =>
22
34
rerender (
23
- < QueryClientProvider client = { client } > < Router > { rerenderUi } </ Router > </ QueryClientProvider >
24
- )
35
+ < QueryClientProvider client = { client } >
36
+ < Router > { rerenderUi } </ Router >
37
+ </ QueryClientProvider >
38
+ ) ,
25
39
}
26
40
}
27
41
28
- type QueryRoute = Query < any , any > [ 'route' ]
29
-
30
42
export function mockServer ( ) : {
31
- server : SetupServer ,
32
- mockQuery : ( { route } : { route : QueryRoute } , resJson : any ) => void
43
+ server : SetupServer
44
+ mockQuery : MockQuery
45
+ mockApi : MockApi
33
46
} {
34
47
const server : SetupServer = setupServer ( )
35
48
@@ -40,28 +53,41 @@ export function mockServer(): {
40
53
} )
41
54
afterAll ( ( ) => server . close ( ) )
42
55
43
- function mockQuery ( { route } : { route : QueryRoute } , resJson : any ) : void {
44
- if ( ! Object . values ( HttpMethod ) . includes ( route . method ) ) {
45
- throw new Error ( `Unsupported query method for mocking: ${ route . method } . Supported method strings are: ${ Object . values ( HttpMethod ) . join ( ', ' ) } .` )
46
- }
56
+ const mockQuery : MockQuery = ( query , mockData ) => {
57
+ const route = ( query as unknown as { route : Route } ) . route
58
+ mockRoute ( server , route , ( _req , res , ctx ) =>
59
+ res ( ctx . json ( superjsonSerialize ( mockData ) ) )
60
+ )
61
+ }
62
+
63
+ const mockApi : MockApi = ( route , mockData ) => {
64
+ mockRoute ( server , route , ( _req , res , ctx ) => res ( ctx . json ( mockData ) ) )
65
+ }
66
+
67
+ return { server, mockQuery, mockApi }
68
+ }
47
69
48
- const url = `${ config . apiUrl } ${ route . path } `
49
- const responseHandler : ResponseResolver < any , RestContext , any > = ( _req , res , ctx ) => {
50
- return res ( ctx . json ( resJson ) )
51
- }
70
+ function mockRoute (
71
+ server : SetupServer ,
72
+ route : Route ,
73
+ responseHandler : ResponseResolver < any , RestContext , any >
74
+ ) {
75
+ if ( ! Object . values ( HttpMethod ) . includes ( route . method ) ) {
76
+ throw new Error (
77
+ `Unsupported query method for mocking: ${
78
+ route . method
79
+ } . Supported method strings are: ${ Object . values ( HttpMethod ) . join ( ', ' ) } .`
80
+ )
81
+ }
52
82
53
- // NOTE: Technically, we only need to care about POST for Queries
54
- // and GET for the /auth/me route. However, an additional use case
55
- // for this function could be to mock APIs, so more methods are supported.
56
- const handlers : Record < HttpMethod , Parameters < typeof server . use > [ 0 ] > = {
57
- [ HttpMethod . Get ] : rest . get ( url , responseHandler ) ,
58
- [ HttpMethod . Post ] : rest . post ( url , responseHandler ) ,
59
- [ HttpMethod . Put ] : rest . put ( url , responseHandler ) ,
60
- [ HttpMethod . Delete ] : rest . delete ( url , responseHandler ) ,
61
- }
83
+ const url = `${ config . apiUrl } ${ route . path } `
62
84
63
- server . use ( handlers [ route . method ] )
85
+ const handlers : Record < HttpMethod , Parameters < typeof server . use > [ 0 ] > = {
86
+ [ HttpMethod . Get ] : rest . get ( url , responseHandler ) ,
87
+ [ HttpMethod . Post ] : rest . post ( url , responseHandler ) ,
88
+ [ HttpMethod . Put ] : rest . put ( url , responseHandler ) ,
89
+ [ HttpMethod . Delete ] : rest . delete ( url , responseHandler ) ,
64
90
}
65
91
66
- return { server, mockQuery }
92
+ server . use ( handlers [ route . method ] )
67
93
}
0 commit comments