-
Notifications
You must be signed in to change notification settings - Fork 0
/
with-json-body.ts
100 lines (82 loc) · 2.9 KB
/
with-json-body.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import isEqual from 'lodash.isequal'
import { HttpResponse, ResponseResolver } from 'msw'
// This is a typed version of the withJsonBody() example from the
// document with the fix https://github.com/mswjs/mswjs.io/pull/317
//
// We get a type error in the return statement. The reason is that
// `resolver(args)` in the last line may return a `Generator<...>` due to the
// current types. Inside an async function the overall return type becomes
// `Promise<Generator<...>>` which does not fit the current type definition
// of a resolver (which is `R | Promise<A> | Generator<R | Promise<R>>).
export function withJsonBodyAsInExamples(
expectedBody: unknown,
resolver: ResponseResolver,
): ResponseResolver {
return async (args) => {
const { request } = args
// Ignore requests that have a non-JSON body.
const contentType = request.headers.get('Content-Type') || ''
if (!contentType.includes('application/json')) {
return
}
// Clone the request and read it as JSON.
const actualBody = await request.clone().json()
// Compare two objects using "lodash".
if (!isEqual(actualBody, expectedBody)) {
return
}
return resolver(args)
}
}
// This is a fixed version of the example. The `as` statement in the end
// strips away the `Generator<..>` type in the return type. So that the rest
// fits the type definition.
export function withJsonBodyFixedWithAsStatement(
expectedBody: unknown,
resolver: ResponseResolver,
): ResponseResolver {
return async (args) => {
const { request } = args
// Ignore requests that have a non-JSON body.
const contentType = request.headers.get('Content-Type') || ''
if (!contentType.includes('application/json')) {
return
}
// Clone the request and read it as JSON.
const actualBody = await request.clone().json()
// Compare two objects using "lodash".
if (!isEqual(actualBody, expectedBody)) {
return
}
return resolver(args) as HttpResponse | undefined | void
}
}
// Another example to fix the type error by unpacking the generator object in
// case it is returned
export function withJsonBodyFixedWithUnpackingGenerator(
expectedBody: unknown,
resolver: ResponseResolver,
): ResponseResolver {
return async (args) => {
const { request } = args
// Ignore requests that have a non-JSON body.
const contentType = request.headers.get('Content-Type') || ''
if (!contentType.includes('application/json')) {
return
}
// Clone the request and read it as JSON.
const actualBody = await request.clone().json()
// Compare two objects using "lodash".
if (!isEqual(actualBody, expectedBody)) {
return
}
const result = resolver(args)
if (isGenerator(result)) {
const { done, value } = result.next()
if (!done) return value
} else {
return await result
}
}
}
declare function isGenerator(x: unknown): x is Generator