msw 2.10.4 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core/{HttpResponse-C7FhBLaS.d.mts → HttpResponse-DiuKTgC7.d.mts} +21 -7
- package/lib/core/{HttpResponse-DWu36LsY.d.ts → HttpResponse-DlQEvD4q.d.ts} +21 -7
- package/lib/core/HttpResponse.d.mts +1 -1
- package/lib/core/HttpResponse.d.ts +1 -1
- package/lib/core/SetupApi.d.mts +1 -1
- package/lib/core/SetupApi.d.ts +1 -1
- package/lib/core/getResponse.d.mts +1 -1
- package/lib/core/getResponse.d.ts +1 -1
- package/lib/core/graphql.d.mts +2 -2
- package/lib/core/graphql.d.ts +2 -2
- package/lib/core/graphql.js +2 -8
- package/lib/core/graphql.js.map +1 -1
- package/lib/core/graphql.mjs +2 -8
- package/lib/core/graphql.mjs.map +1 -1
- package/lib/core/handlers/GraphQLHandler.d.mts +1 -1
- package/lib/core/handlers/GraphQLHandler.d.ts +1 -1
- package/lib/core/handlers/GraphQLHandler.js +36 -9
- package/lib/core/handlers/GraphQLHandler.js.map +1 -1
- package/lib/core/handlers/GraphQLHandler.mjs +36 -9
- package/lib/core/handlers/GraphQLHandler.mjs.map +1 -1
- package/lib/core/handlers/HttpHandler.d.mts +15 -5
- package/lib/core/handlers/HttpHandler.d.ts +15 -5
- package/lib/core/handlers/HttpHandler.js +21 -10
- package/lib/core/handlers/HttpHandler.js.map +1 -1
- package/lib/core/handlers/HttpHandler.mjs +21 -10
- package/lib/core/handlers/HttpHandler.mjs.map +1 -1
- package/lib/core/handlers/RequestHandler.d.mts +1 -1
- package/lib/core/handlers/RequestHandler.d.ts +1 -1
- package/lib/core/handlers/RequestHandler.js +1 -1
- package/lib/core/handlers/RequestHandler.js.map +1 -1
- package/lib/core/handlers/RequestHandler.mjs +1 -1
- package/lib/core/handlers/RequestHandler.mjs.map +1 -1
- package/lib/core/http.d.mts +4 -4
- package/lib/core/http.d.ts +4 -4
- package/lib/core/http.js +2 -2
- package/lib/core/http.js.map +1 -1
- package/lib/core/http.mjs +2 -2
- package/lib/core/http.mjs.map +1 -1
- package/lib/core/index.d.mts +2 -2
- package/lib/core/index.d.ts +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs.map +1 -1
- package/lib/core/passthrough.d.mts +1 -1
- package/lib/core/passthrough.d.ts +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
- package/lib/core/utils/executeHandlers.d.mts +1 -1
- package/lib/core/utils/executeHandlers.d.ts +1 -1
- package/lib/core/utils/handleRequest.d.mts +1 -1
- package/lib/core/utils/handleRequest.d.ts +1 -1
- package/lib/core/utils/internal/isHandlerKind.d.mts +1 -1
- package/lib/core/utils/internal/isHandlerKind.d.ts +1 -1
- package/lib/core/utils/internal/parseGraphQLRequest.d.mts +1 -1
- package/lib/core/utils/internal/parseGraphQLRequest.d.ts +1 -1
- package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
- package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
- package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
- package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.mts +1 -1
- package/lib/core/ws/handleWebSocketEvent.d.ts +1 -1
- package/lib/iife/index.js +62 -30
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/package.json +2 -2
- package/src/core/graphql.ts +8 -12
- package/src/core/handlers/GraphQLHandler.test.ts +86 -51
- package/src/core/handlers/GraphQLHandler.ts +81 -17
- package/src/core/handlers/HttpHandler.test.ts +60 -30
- package/src/core/handlers/HttpHandler.ts +61 -12
- package/src/core/handlers/RequestHandler.ts +2 -2
- package/src/core/http.ts +5 -5
- package/src/core/index.ts +4 -0
- package/src/core/utils/handleRequest.test.ts +84 -0
package/lib/mockServiceWorker.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Please do NOT modify this file.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const PACKAGE_VERSION = '2.
|
|
10
|
+
const PACKAGE_VERSION = '2.11.0'
|
|
11
11
|
const INTEGRITY_CHECKSUM = 'f5825c521429caf22a4dd13b66e243af'
|
|
12
12
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
13
13
|
const activeClientIds = new Set()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Seamless REST/GraphQL API mocking library for browser and Node.js.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./lib/core/index.js",
|
|
@@ -280,7 +280,7 @@
|
|
|
280
280
|
"vitest-environment-miniflare": "^2.14.4",
|
|
281
281
|
"webpack": "^5.95.0",
|
|
282
282
|
"webpack-http-server": "^0.5.0",
|
|
283
|
-
"msw": "2.
|
|
283
|
+
"msw": "2.11.0"
|
|
284
284
|
},
|
|
285
285
|
"peerDependencies": {
|
|
286
286
|
"typescript": ">= 4.8.x"
|
package/src/core/graphql.ts
CHANGED
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
GraphQLHandler,
|
|
8
8
|
GraphQLVariables,
|
|
9
|
-
|
|
9
|
+
GraphQLOperationType,
|
|
10
10
|
GraphQLHandlerNameSelector,
|
|
11
11
|
GraphQLResolverExtras,
|
|
12
12
|
GraphQLResponseBody,
|
|
13
13
|
GraphQLQuery,
|
|
14
|
+
GraphQLCustomPredicate,
|
|
14
15
|
} from './handlers/GraphQLHandler'
|
|
15
16
|
import type { Path } from './utils/matching/matchRequestUrl'
|
|
16
17
|
|
|
@@ -27,10 +28,11 @@ export type GraphQLRequestHandler = <
|
|
|
27
28
|
Query extends GraphQLQuery = GraphQLQuery,
|
|
28
29
|
Variables extends GraphQLVariables = GraphQLVariables,
|
|
29
30
|
>(
|
|
30
|
-
|
|
31
|
+
predicate:
|
|
31
32
|
| GraphQLHandlerNameSelector
|
|
32
33
|
| DocumentNode
|
|
33
|
-
| TypedDocumentNode<Query, Variables
|
|
34
|
+
| TypedDocumentNode<Query, Variables>
|
|
35
|
+
| GraphQLCustomPredicate,
|
|
34
36
|
resolver: GraphQLResponseResolver<
|
|
35
37
|
[Query] extends [never] ? GraphQLQuery : Query,
|
|
36
38
|
Variables
|
|
@@ -48,17 +50,11 @@ export type GraphQLResponseResolver<
|
|
|
48
50
|
>
|
|
49
51
|
|
|
50
52
|
function createScopedGraphQLHandler(
|
|
51
|
-
operationType:
|
|
53
|
+
operationType: GraphQLOperationType,
|
|
52
54
|
url: Path,
|
|
53
55
|
): GraphQLRequestHandler {
|
|
54
|
-
return (
|
|
55
|
-
return new GraphQLHandler(
|
|
56
|
-
operationType,
|
|
57
|
-
operationName,
|
|
58
|
-
url,
|
|
59
|
-
resolver,
|
|
60
|
-
options,
|
|
61
|
-
)
|
|
56
|
+
return (predicate, resolver, options = {}) => {
|
|
57
|
+
return new GraphQLHandler(operationType, predicate, url, resolver, options)
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
60
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* @vitest-environment jsdom
|
|
3
|
-
*/
|
|
1
|
+
// @vitest-environment jsdom
|
|
4
2
|
import { createRequestId, encodeBuffer } from '@mswjs/interceptors'
|
|
5
3
|
import { OperationTypeNode, parse } from 'graphql'
|
|
6
4
|
import {
|
|
@@ -62,7 +60,7 @@ const LOGIN = `
|
|
|
62
60
|
`
|
|
63
61
|
|
|
64
62
|
describe('info', () => {
|
|
65
|
-
|
|
63
|
+
it('exposes request handler information for query', () => {
|
|
66
64
|
const handler = new GraphQLHandler(
|
|
67
65
|
OperationTypeNode.QUERY,
|
|
68
66
|
'GetUser',
|
|
@@ -75,7 +73,7 @@ describe('info', () => {
|
|
|
75
73
|
expect(handler.info.operationName).toEqual('GetUser')
|
|
76
74
|
})
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
it('exposes request handler information for mutation', () => {
|
|
79
77
|
const handler = new GraphQLHandler(
|
|
80
78
|
OperationTypeNode.MUTATION,
|
|
81
79
|
'Login',
|
|
@@ -88,7 +86,7 @@ describe('info', () => {
|
|
|
88
86
|
expect(handler.info.operationName).toEqual('Login')
|
|
89
87
|
})
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
it('parses a query operation name from a given DocumentNode', () => {
|
|
92
90
|
const node = parse(`
|
|
93
91
|
query GetUser {
|
|
94
92
|
user {
|
|
@@ -109,7 +107,7 @@ describe('info', () => {
|
|
|
109
107
|
expect(handler.info).toHaveProperty('operationName', 'GetUser')
|
|
110
108
|
})
|
|
111
109
|
|
|
112
|
-
|
|
110
|
+
it('parses a mutation operation name from a given DocumentNode', () => {
|
|
113
111
|
const node = parse(`
|
|
114
112
|
mutation Login {
|
|
115
113
|
user {
|
|
@@ -129,7 +127,7 @@ describe('info', () => {
|
|
|
129
127
|
expect(handler.info).toHaveProperty('operationName', 'Login')
|
|
130
128
|
})
|
|
131
129
|
|
|
132
|
-
|
|
130
|
+
it('throws an exception given a DocumentNode with a mismatched operation type', () => {
|
|
133
131
|
const node = parse(`
|
|
134
132
|
mutation CreateUser {
|
|
135
133
|
user {
|
|
@@ -148,7 +146,7 @@ describe('info', () => {
|
|
|
148
146
|
|
|
149
147
|
describe('parse', () => {
|
|
150
148
|
describe('query', () => {
|
|
151
|
-
|
|
149
|
+
it('parses a query without variables (GET)', async () => {
|
|
152
150
|
const handler = new GraphQLHandler(
|
|
153
151
|
OperationTypeNode.QUERY,
|
|
154
152
|
'GetUser',
|
|
@@ -174,7 +172,7 @@ describe('parse', () => {
|
|
|
174
172
|
})
|
|
175
173
|
})
|
|
176
174
|
|
|
177
|
-
|
|
175
|
+
it('parses a query with variables (GET)', async () => {
|
|
178
176
|
const handler = new GraphQLHandler(
|
|
179
177
|
OperationTypeNode.QUERY,
|
|
180
178
|
'GetUser',
|
|
@@ -205,7 +203,7 @@ describe('parse', () => {
|
|
|
205
203
|
})
|
|
206
204
|
})
|
|
207
205
|
|
|
208
|
-
|
|
206
|
+
it('parses a query without variables (POST)', async () => {
|
|
209
207
|
const handler = new GraphQLHandler(
|
|
210
208
|
OperationTypeNode.QUERY,
|
|
211
209
|
'GetUser',
|
|
@@ -231,7 +229,7 @@ describe('parse', () => {
|
|
|
231
229
|
})
|
|
232
230
|
})
|
|
233
231
|
|
|
234
|
-
|
|
232
|
+
it('parses a query with variables (POST)', async () => {
|
|
235
233
|
const handler = new GraphQLHandler(
|
|
236
234
|
OperationTypeNode.QUERY,
|
|
237
235
|
'GetUser',
|
|
@@ -264,7 +262,7 @@ describe('parse', () => {
|
|
|
264
262
|
})
|
|
265
263
|
|
|
266
264
|
describe('mutation', () => {
|
|
267
|
-
|
|
265
|
+
it('parses a mutation without variables (GET)', async () => {
|
|
268
266
|
const handler = new GraphQLHandler(
|
|
269
267
|
OperationTypeNode.MUTATION,
|
|
270
268
|
'GetUser',
|
|
@@ -290,7 +288,7 @@ describe('parse', () => {
|
|
|
290
288
|
})
|
|
291
289
|
})
|
|
292
290
|
|
|
293
|
-
|
|
291
|
+
it('parses a mutation with variables (GET)', async () => {
|
|
294
292
|
const handler = new GraphQLHandler(
|
|
295
293
|
OperationTypeNode.MUTATION,
|
|
296
294
|
'GetUser',
|
|
@@ -321,7 +319,7 @@ describe('parse', () => {
|
|
|
321
319
|
})
|
|
322
320
|
})
|
|
323
321
|
|
|
324
|
-
|
|
322
|
+
it('parses a mutation without variables (POST)', async () => {
|
|
325
323
|
const handler = new GraphQLHandler(
|
|
326
324
|
OperationTypeNode.MUTATION,
|
|
327
325
|
'GetUser',
|
|
@@ -347,7 +345,7 @@ describe('parse', () => {
|
|
|
347
345
|
})
|
|
348
346
|
})
|
|
349
347
|
|
|
350
|
-
|
|
348
|
+
it('parses a mutation with variables (POST)', async () => {
|
|
351
349
|
const handler = new GraphQLHandler(
|
|
352
350
|
OperationTypeNode.MUTATION,
|
|
353
351
|
'GetUser',
|
|
@@ -380,7 +378,7 @@ describe('parse', () => {
|
|
|
380
378
|
})
|
|
381
379
|
|
|
382
380
|
describe('with endpoint configuration', () => {
|
|
383
|
-
|
|
381
|
+
it('parses the request and parses grapqhl properties from it when the graphql.link endpoint matches', async () => {
|
|
384
382
|
const handler = new GraphQLHandler(
|
|
385
383
|
OperationTypeNode.QUERY,
|
|
386
384
|
'GetUser',
|
|
@@ -441,7 +439,7 @@ describe('parse', () => {
|
|
|
441
439
|
})
|
|
442
440
|
})
|
|
443
441
|
|
|
444
|
-
|
|
442
|
+
it('parses a request but does not parse graphql properties from it graphql.link hostname does not match', async () => {
|
|
445
443
|
const handler = new GraphQLHandler(
|
|
446
444
|
OperationTypeNode.QUERY,
|
|
447
445
|
'GetUser',
|
|
@@ -490,7 +488,7 @@ describe('parse', () => {
|
|
|
490
488
|
})
|
|
491
489
|
})
|
|
492
490
|
|
|
493
|
-
|
|
491
|
+
it('parses a request but does not parse graphql properties from it graphql.link pathname does not match', async () => {
|
|
494
492
|
const handler = new GraphQLHandler(
|
|
495
493
|
OperationTypeNode.QUERY,
|
|
496
494
|
'GetUser',
|
|
@@ -542,7 +540,7 @@ describe('parse', () => {
|
|
|
542
540
|
})
|
|
543
541
|
|
|
544
542
|
describe('predicate', () => {
|
|
545
|
-
|
|
543
|
+
it('respects operation type', async () => {
|
|
546
544
|
const handler = new GraphQLHandler(
|
|
547
545
|
OperationTypeNode.QUERY,
|
|
548
546
|
'GetUser',
|
|
@@ -557,20 +555,20 @@ describe('predicate', () => {
|
|
|
557
555
|
})
|
|
558
556
|
|
|
559
557
|
expect(
|
|
560
|
-
handler.predicate({
|
|
558
|
+
await handler.predicate({
|
|
561
559
|
request,
|
|
562
560
|
parsedResult: await handler.parse({ request }),
|
|
563
561
|
}),
|
|
564
562
|
).toBe(true)
|
|
565
563
|
expect(
|
|
566
|
-
handler.predicate({
|
|
564
|
+
await handler.predicate({
|
|
567
565
|
request: alienRequest,
|
|
568
566
|
parsedResult: await handler.parse({ request: alienRequest }),
|
|
569
567
|
}),
|
|
570
568
|
).toBe(false)
|
|
571
569
|
})
|
|
572
570
|
|
|
573
|
-
|
|
571
|
+
it('respects operation name', async () => {
|
|
574
572
|
const handler = new GraphQLHandler(
|
|
575
573
|
OperationTypeNode.QUERY,
|
|
576
574
|
'GetUser',
|
|
@@ -590,21 +588,21 @@ describe('predicate', () => {
|
|
|
590
588
|
`,
|
|
591
589
|
})
|
|
592
590
|
|
|
593
|
-
expect(
|
|
591
|
+
await expect(
|
|
594
592
|
handler.predicate({
|
|
595
593
|
request,
|
|
596
594
|
parsedResult: await handler.parse({ request }),
|
|
597
595
|
}),
|
|
598
|
-
).toBe(true)
|
|
599
|
-
expect(
|
|
596
|
+
).resolves.toBe(true)
|
|
597
|
+
await expect(
|
|
600
598
|
handler.predicate({
|
|
601
599
|
request: alienRequest,
|
|
602
600
|
parsedResult: await handler.parse({ request: alienRequest }),
|
|
603
601
|
}),
|
|
604
|
-
).toBe(false)
|
|
602
|
+
).resolves.toBe(false)
|
|
605
603
|
})
|
|
606
604
|
|
|
607
|
-
|
|
605
|
+
it('allows anonymous GraphQL opertaions when using "all" expected operation type', async () => {
|
|
608
606
|
const handler = new GraphQLHandler('all', new RegExp('.*'), '*', resolver)
|
|
609
607
|
const request = createPostGraphQLRequest({
|
|
610
608
|
query: `
|
|
@@ -617,15 +615,15 @@ describe('predicate', () => {
|
|
|
617
615
|
`,
|
|
618
616
|
})
|
|
619
617
|
|
|
620
|
-
expect(
|
|
618
|
+
await expect(
|
|
621
619
|
handler.predicate({
|
|
622
620
|
request,
|
|
623
621
|
parsedResult: await handler.parse({ request }),
|
|
624
622
|
}),
|
|
625
|
-
).toBe(true)
|
|
623
|
+
).resolves.toBe(true)
|
|
626
624
|
})
|
|
627
625
|
|
|
628
|
-
|
|
626
|
+
it('respects custom endpoint', async () => {
|
|
629
627
|
const handler = new GraphQLHandler(
|
|
630
628
|
OperationTypeNode.QUERY,
|
|
631
629
|
'GetUser',
|
|
@@ -642,23 +640,60 @@ describe('predicate', () => {
|
|
|
642
640
|
query: GET_USER,
|
|
643
641
|
})
|
|
644
642
|
|
|
645
|
-
expect(
|
|
643
|
+
await expect(
|
|
646
644
|
handler.predicate({
|
|
647
645
|
request,
|
|
648
646
|
parsedResult: await handler.parse({ request }),
|
|
649
647
|
}),
|
|
650
|
-
).toBe(true)
|
|
651
|
-
expect(
|
|
648
|
+
).resolves.toBe(true)
|
|
649
|
+
await expect(
|
|
652
650
|
handler.predicate({
|
|
653
651
|
request: alienRequest,
|
|
654
652
|
parsedResult: await handler.parse({ request: alienRequest }),
|
|
655
653
|
}),
|
|
656
|
-
).toBe(false)
|
|
654
|
+
).resolves.toBe(false)
|
|
655
|
+
})
|
|
656
|
+
|
|
657
|
+
it('supports custom predicate function', async () => {
|
|
658
|
+
const handler = new GraphQLHandler(
|
|
659
|
+
OperationTypeNode.QUERY,
|
|
660
|
+
({ query }) => {
|
|
661
|
+
return query.includes('password')
|
|
662
|
+
},
|
|
663
|
+
/.+/,
|
|
664
|
+
resolver,
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
{
|
|
668
|
+
const request = createPostGraphQLRequest({
|
|
669
|
+
query: `query GetUser { user { password } }`,
|
|
670
|
+
})
|
|
671
|
+
|
|
672
|
+
await expect(
|
|
673
|
+
handler.predicate({
|
|
674
|
+
request,
|
|
675
|
+
parsedResult: await handler.parse({ request }),
|
|
676
|
+
}),
|
|
677
|
+
).resolves.toBe(true)
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
{
|
|
681
|
+
const request = createPostGraphQLRequest({
|
|
682
|
+
query: `query GetUser { user { nonMatching } }`,
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
await expect(
|
|
686
|
+
handler.predicate({
|
|
687
|
+
request,
|
|
688
|
+
parsedResult: await handler.parse({ request }),
|
|
689
|
+
}),
|
|
690
|
+
).resolves.toBe(false)
|
|
691
|
+
}
|
|
657
692
|
})
|
|
658
693
|
})
|
|
659
694
|
|
|
660
695
|
describe('test', () => {
|
|
661
|
-
|
|
696
|
+
it('respects operation type', async () => {
|
|
662
697
|
const handler = new GraphQLHandler(
|
|
663
698
|
OperationTypeNode.QUERY,
|
|
664
699
|
'GetUser',
|
|
@@ -676,7 +711,7 @@ describe('test', () => {
|
|
|
676
711
|
expect(await handler.test({ request: alienRequest })).toBe(false)
|
|
677
712
|
})
|
|
678
713
|
|
|
679
|
-
|
|
714
|
+
it('respects operation name', async () => {
|
|
680
715
|
const handler = new GraphQLHandler(
|
|
681
716
|
OperationTypeNode.QUERY,
|
|
682
717
|
'GetUser',
|
|
@@ -696,11 +731,11 @@ describe('test', () => {
|
|
|
696
731
|
`,
|
|
697
732
|
})
|
|
698
733
|
|
|
699
|
-
expect(
|
|
700
|
-
expect(
|
|
734
|
+
await expect(handler.test({ request })).resolves.toBe(true)
|
|
735
|
+
await expect(handler.test({ request: alienRequest })).resolves.toBe(false)
|
|
701
736
|
})
|
|
702
737
|
|
|
703
|
-
|
|
738
|
+
it('respects custom endpoint', async () => {
|
|
704
739
|
const handler = new GraphQLHandler(
|
|
705
740
|
OperationTypeNode.QUERY,
|
|
706
741
|
'GetUser',
|
|
@@ -717,13 +752,13 @@ describe('test', () => {
|
|
|
717
752
|
query: GET_USER,
|
|
718
753
|
})
|
|
719
754
|
|
|
720
|
-
expect(
|
|
721
|
-
expect(
|
|
755
|
+
await expect(handler.test({ request })).resolves.toBe(true)
|
|
756
|
+
await expect(handler.test({ request: alienRequest })).resolves.toBe(false)
|
|
722
757
|
})
|
|
723
758
|
})
|
|
724
759
|
|
|
725
760
|
describe('run', () => {
|
|
726
|
-
|
|
761
|
+
it('returns a mocked response given a matching query', async () => {
|
|
727
762
|
const handler = new GraphQLHandler(
|
|
728
763
|
OperationTypeNode.QUERY,
|
|
729
764
|
'GetUser',
|
|
@@ -757,18 +792,18 @@ describe('run', () => {
|
|
|
757
792
|
})
|
|
758
793
|
expect(result!.request.method).toBe('POST')
|
|
759
794
|
expect(result!.request.url).toBe('https://example.com/')
|
|
760
|
-
expect(
|
|
795
|
+
await expect(result!.request.json()).resolves.toEqual({
|
|
761
796
|
query: GET_USER,
|
|
762
797
|
variables: { userId: 'abc-123' },
|
|
763
798
|
})
|
|
764
799
|
expect(result!.response?.status).toBe(200)
|
|
765
800
|
expect(result!.response?.statusText).toBe('OK')
|
|
766
|
-
expect(
|
|
801
|
+
await expect(result!.response?.json()).resolves.toEqual({
|
|
767
802
|
data: { user: { id: 'abc-123' } },
|
|
768
803
|
})
|
|
769
804
|
})
|
|
770
805
|
|
|
771
|
-
|
|
806
|
+
it('returns null given a non-matching query', async () => {
|
|
772
807
|
const handler = new GraphQLHandler(
|
|
773
808
|
OperationTypeNode.QUERY,
|
|
774
809
|
'GetUser',
|
|
@@ -818,12 +853,12 @@ describe('request', () => {
|
|
|
818
853
|
)
|
|
819
854
|
const request = createPostGraphQLRequest({
|
|
820
855
|
query: `
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
}
|
|
856
|
+
query GetAllUsers {
|
|
857
|
+
user {
|
|
858
|
+
id
|
|
825
859
|
}
|
|
826
|
-
|
|
860
|
+
}
|
|
861
|
+
`,
|
|
827
862
|
})
|
|
828
863
|
|
|
829
864
|
const requestId = createRequestId()
|
|
@@ -21,15 +21,15 @@ import { toPublicUrl } from '../utils/request/toPublicUrl'
|
|
|
21
21
|
import { devUtils } from '../utils/internal/devUtils'
|
|
22
22
|
import { getAllRequestCookies } from '../utils/request/getRequestCookies'
|
|
23
23
|
|
|
24
|
-
export type
|
|
24
|
+
export type GraphQLOperationType = OperationTypeNode | 'all'
|
|
25
25
|
export type GraphQLHandlerNameSelector = DocumentNode | RegExp | string
|
|
26
26
|
|
|
27
27
|
export type GraphQLQuery = Record<string, any> | null
|
|
28
28
|
export type GraphQLVariables = Record<string, any>
|
|
29
29
|
|
|
30
30
|
export interface GraphQLHandlerInfo extends RequestHandlerDefaultInfo {
|
|
31
|
-
operationType:
|
|
32
|
-
operationName: GraphQLHandlerNameSelector
|
|
31
|
+
operationType: GraphQLOperationType
|
|
32
|
+
operationName: GraphQLHandlerNameSelector | GraphQLCustomPredicate
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export type GraphQLRequestParsedResult = {
|
|
@@ -77,6 +77,21 @@ export type GraphQLResponseBody<BodyType extends DefaultBodyType> =
|
|
|
77
77
|
| null
|
|
78
78
|
| undefined
|
|
79
79
|
|
|
80
|
+
export type GraphQLCustomPredicate = (args: {
|
|
81
|
+
request: Request
|
|
82
|
+
query: string
|
|
83
|
+
operationType: GraphQLOperationType
|
|
84
|
+
operationName: string
|
|
85
|
+
variables: GraphQLVariables
|
|
86
|
+
cookies: Record<string, string>
|
|
87
|
+
}) => GraphQLCustomPredicateResult | Promise<GraphQLCustomPredicateResult>
|
|
88
|
+
|
|
89
|
+
export type GraphQLCustomPredicateResult = boolean | { matches: boolean }
|
|
90
|
+
|
|
91
|
+
export type GraphQLPredicate =
|
|
92
|
+
| GraphQLHandlerNameSelector
|
|
93
|
+
| GraphQLCustomPredicate
|
|
94
|
+
|
|
80
95
|
export function isDocumentNode(
|
|
81
96
|
value: DocumentNode | any,
|
|
82
97
|
): value is DocumentNode {
|
|
@@ -100,16 +115,16 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
100
115
|
>()
|
|
101
116
|
|
|
102
117
|
constructor(
|
|
103
|
-
operationType:
|
|
104
|
-
|
|
118
|
+
operationType: GraphQLOperationType,
|
|
119
|
+
predicate: GraphQLPredicate,
|
|
105
120
|
endpoint: Path,
|
|
106
121
|
resolver: ResponseResolver<GraphQLResolverExtras<any>, any, any>,
|
|
107
122
|
options?: RequestHandlerOptions,
|
|
108
123
|
) {
|
|
109
|
-
let resolvedOperationName =
|
|
124
|
+
let resolvedOperationName = predicate
|
|
110
125
|
|
|
111
|
-
if (isDocumentNode(
|
|
112
|
-
const parsedNode = parseDocumentNode(
|
|
126
|
+
if (isDocumentNode(resolvedOperationName)) {
|
|
127
|
+
const parsedNode = parseDocumentNode(resolvedOperationName)
|
|
113
128
|
|
|
114
129
|
if (parsedNode.operationType !== operationType) {
|
|
115
130
|
throw new Error(
|
|
@@ -126,10 +141,15 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
126
141
|
resolvedOperationName = parsedNode.operationName
|
|
127
142
|
}
|
|
128
143
|
|
|
144
|
+
const displayOperationName =
|
|
145
|
+
typeof resolvedOperationName === 'function'
|
|
146
|
+
? '[custom predicate]'
|
|
147
|
+
: resolvedOperationName
|
|
148
|
+
|
|
129
149
|
const header =
|
|
130
150
|
operationType === 'all'
|
|
131
151
|
? `${operationType} (origin: ${endpoint.toString()})`
|
|
132
|
-
: `${operationType} ${
|
|
152
|
+
: `${operationType}${displayOperationName ? ` ${displayOperationName}` : ''} (origin: ${endpoint.toString()})`
|
|
133
153
|
|
|
134
154
|
super({
|
|
135
155
|
info: {
|
|
@@ -175,7 +195,10 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
175
195
|
const cookies = getAllRequestCookies(args.request)
|
|
176
196
|
|
|
177
197
|
if (!match.matches) {
|
|
178
|
-
return {
|
|
198
|
+
return {
|
|
199
|
+
match,
|
|
200
|
+
cookies,
|
|
201
|
+
}
|
|
179
202
|
}
|
|
180
203
|
|
|
181
204
|
const parsedResult = await this.parseGraphQLRequestOrGetFromCache(
|
|
@@ -183,7 +206,10 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
183
206
|
)
|
|
184
207
|
|
|
185
208
|
if (typeof parsedResult === 'undefined') {
|
|
186
|
-
return {
|
|
209
|
+
return {
|
|
210
|
+
match,
|
|
211
|
+
cookies,
|
|
212
|
+
}
|
|
187
213
|
}
|
|
188
214
|
|
|
189
215
|
return {
|
|
@@ -196,10 +222,10 @@ export class GraphQLHandler extends RequestHandler<
|
|
|
196
222
|
}
|
|
197
223
|
}
|
|
198
224
|
|
|
199
|
-
predicate(args: {
|
|
225
|
+
async predicate(args: {
|
|
200
226
|
request: Request
|
|
201
227
|
parsedResult: GraphQLRequestParsedResult
|
|
202
|
-
}) {
|
|
228
|
+
}): Promise<boolean> {
|
|
203
229
|
if (args.parsedResult.operationType === undefined) {
|
|
204
230
|
return false
|
|
205
231
|
}
|
|
@@ -218,10 +244,16 @@ Consider naming this operation or using "graphql.operation()" request handler to
|
|
|
218
244
|
this.info.operationType === 'all' ||
|
|
219
245
|
args.parsedResult.operationType === this.info.operationType
|
|
220
246
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Check if the operation name matches the outgoing GraphQL request.
|
|
249
|
+
* @note Unlike the HTTP handler, the custom predicate functions are invoked
|
|
250
|
+
* during predicate, not parsing, because GraphQL request parsing happens first,
|
|
251
|
+
* and non-GraphQL requests are filtered out automatically.
|
|
252
|
+
*/
|
|
253
|
+
const hasMatchingOperationName = await this.matchOperationName({
|
|
254
|
+
request: args.request,
|
|
255
|
+
parsedResult: args.parsedResult,
|
|
256
|
+
})
|
|
225
257
|
|
|
226
258
|
return (
|
|
227
259
|
args.parsedResult.match.matches &&
|
|
@@ -230,12 +262,44 @@ Consider naming this operation or using "graphql.operation()" request handler to
|
|
|
230
262
|
)
|
|
231
263
|
}
|
|
232
264
|
|
|
265
|
+
private async matchOperationName(args: {
|
|
266
|
+
request: Request
|
|
267
|
+
parsedResult: GraphQLRequestParsedResult
|
|
268
|
+
}): Promise<boolean> {
|
|
269
|
+
if (typeof this.info.operationName === 'function') {
|
|
270
|
+
const customPredicateResult = await this.info.operationName({
|
|
271
|
+
request: args.request,
|
|
272
|
+
...this.extendResolverArgs({
|
|
273
|
+
request: args.request,
|
|
274
|
+
parsedResult: args.parsedResult,
|
|
275
|
+
}),
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @note Keep the { matches } signature in case we decide to support path parameters
|
|
280
|
+
* in GraphQL handlers. If that happens, the custom predicate would have to be moved
|
|
281
|
+
* to the parsing phase, the same as we have for the HttpHandler, and the user will
|
|
282
|
+
* have a possibility to return parsed path parameters from the custom predicate.
|
|
283
|
+
*/
|
|
284
|
+
return typeof customPredicateResult === 'boolean'
|
|
285
|
+
? customPredicateResult
|
|
286
|
+
: customPredicateResult.matches
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (this.info.operationName instanceof RegExp) {
|
|
290
|
+
return this.info.operationName.test(args.parsedResult.operationName || '')
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return args.parsedResult.operationName === this.info.operationName
|
|
294
|
+
}
|
|
295
|
+
|
|
233
296
|
protected extendResolverArgs(args: {
|
|
234
297
|
request: Request
|
|
235
298
|
parsedResult: GraphQLRequestParsedResult
|
|
236
299
|
}) {
|
|
237
300
|
return {
|
|
238
301
|
query: args.parsedResult.query || '',
|
|
302
|
+
operationType: args.parsedResult.operationType!,
|
|
239
303
|
operationName: args.parsedResult.operationName || '',
|
|
240
304
|
variables: args.parsedResult.variables || {},
|
|
241
305
|
cookies: args.parsedResult.cookies,
|