graphql-http 1.11.0 → 1.12.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.
@@ -3,7 +3,7 @@
3
3
  * audit/server
4
4
  *
5
5
  */
6
- import { assert, assertBodyAsExecutionResult, audit, extendedTypeof, } from './utils.mjs';
6
+ import { ressert, audit, extendedTypeof, AuditError } from './utils.mjs';
7
7
  /**
8
8
  * List of server audits required to check GraphQL over HTTP spec conformance.
9
9
  *
@@ -24,8 +24,10 @@ export function serverAudits(opts) {
24
24
  },
25
25
  body: JSON.stringify({ query: '{ __typename }' }),
26
26
  });
27
- assert('Status code', res.status).toBe(200);
28
- assert('Content-Type header', res.headers.get('content-type')).toContain('application/graphql-response+json');
27
+ ressert(res).status.toBe(200);
28
+ ressert(res)
29
+ .header('content-type')
30
+ .toContain('application/graphql-response+json');
29
31
  }),
30
32
  audit('MUST accept application/json and match the content-type', async () => {
31
33
  const res = await fetchFn(await getUrl(opts.url), {
@@ -36,8 +38,8 @@ export function serverAudits(opts) {
36
38
  },
37
39
  body: JSON.stringify({ query: '{ __typename }' }),
38
40
  });
39
- assert('Status code', res.status).toBe(200);
40
- assert('Content-Type header', res.headers.get('content-type')).toContain('application/json');
41
+ ressert(res).status.toBe(200);
42
+ ressert(res).header('content-type').toContain('application/json');
41
43
  }),
42
44
  audit('SHOULD accept */* and use application/json for the content-type', async () => {
43
45
  const res = await fetchFn(await getUrl(opts.url), {
@@ -48,15 +50,15 @@ export function serverAudits(opts) {
48
50
  },
49
51
  body: JSON.stringify({ query: '{ __typename }' }),
50
52
  });
51
- assert('Status code', res.status).toBe(200);
52
- assert('Content-Type header', res.headers.get('content-type')).toContain('application/json');
53
+ ressert(res).status.toBe(200);
54
+ ressert(res).header('content-type').toContain('application/json');
53
55
  }),
54
56
  audit('SHOULD assume application/json content-type when accept is missing', async () => {
55
57
  const url = new URL(await getUrl(opts.url));
56
58
  url.searchParams.set('query', '{ __typename }');
57
59
  const res = await fetchFn(url.toString());
58
- assert('Status code', res.status).toBe(200);
59
- assert('Content-Type header', res.headers.get('content-type')).toContain('application/json');
60
+ ressert(res).status.toBe(200);
61
+ ressert(res).header('content-type').toContain('application/json');
60
62
  }),
61
63
  audit('MUST use utf-8 encoding when responding', async () => {
62
64
  const res = await fetchFn(await getUrl(opts.url), {
@@ -66,28 +68,16 @@ export function serverAudits(opts) {
66
68
  },
67
69
  body: JSON.stringify({ query: '{ __typename }' }),
68
70
  });
69
- assert('Status code', res.status).toBe(200);
70
- // has charset set to utf-8
71
- try {
72
- assert('Content-Type header', res.headers.get('content-type')).toContain('charset=utf-8');
73
- return;
74
- }
75
- catch (_a) {
76
- // noop, continue
77
- }
78
- // has no charset specified
79
- assert('Content-Type header', res.headers.get('content-type')).notToContain('charset');
80
- // and the content is utf-8 encoded
71
+ ressert(res).status.toBe(200);
81
72
  try {
82
73
  const decoder = new TextDecoder('utf-8');
83
- const decoded = decoder.decode(await res.arrayBuffer());
84
- assert('UTF-8 decoded body', decoded).toBe('{"data":{"__typename":"Query"}}');
74
+ decoder.decode(await res.arrayBuffer());
85
75
  }
86
- catch (_b) {
87
- throw 'Body is not UTF-8 encoded';
76
+ catch (_a) {
77
+ throw new AuditError(res, 'Response body is not UTF-8 encoded');
88
78
  }
89
79
  }),
90
- audit('MUST accept utf-8 encoding', async () => {
80
+ audit('MUST accept utf-8 encoded request', async () => {
91
81
  const res = await fetchFn(await getUrl(opts.url), {
92
82
  method: 'POST',
93
83
  headers: {
@@ -95,10 +85,9 @@ export function serverAudits(opts) {
95
85
  },
96
86
  body: JSON.stringify({ query: '{ __typename }' }),
97
87
  });
98
- assert('Status code', res.status).toBe(200);
99
- assert('Content-Type header', res.headers.get('content-type')).toContain('utf-8');
88
+ ressert(res).status.toBe(200);
100
89
  }),
101
- audit('MUST assume utf-8 if encoding is unspecified', async () => {
90
+ audit('MUST assume utf-8 in request if encoding is unspecified', async () => {
102
91
  const res = await fetchFn(await getUrl(opts.url), {
103
92
  method: 'POST',
104
93
  headers: {
@@ -106,8 +95,7 @@ export function serverAudits(opts) {
106
95
  },
107
96
  body: JSON.stringify({ query: '{ __typename }' }),
108
97
  });
109
- assert('Status code', res.status).toBe(200);
110
- assert('Content-Type header', res.headers.get('content-type')).toContain('utf-8');
98
+ ressert(res).status.toBe(200);
111
99
  }),
112
100
  // Request
113
101
  audit('MUST accept POST requests', async () => {
@@ -116,13 +104,13 @@ export function serverAudits(opts) {
116
104
  headers: { 'content-type': 'application/json' },
117
105
  body: JSON.stringify({ query: '{ __typename }' }),
118
106
  });
119
- assert('Status code', res.status).toBe(200);
107
+ ressert(res).status.toBe(200);
120
108
  }),
121
109
  audit('MAY accept application/x-www-form-urlencoded formatted GET requests', async () => {
122
110
  const url = new URL(await getUrl(opts.url));
123
111
  url.searchParams.set('query', '{ __typename }');
124
112
  const res = await fetchFn(url.toString());
125
- assert('Status code', res.status).toBe(200);
113
+ ressert(res).status.toBe(200);
126
114
  }),
127
115
  // Request GET
128
116
  // TODO: this is a MUST if the server supports GET requests
@@ -134,14 +122,14 @@ export function serverAudits(opts) {
134
122
  accept: 'application/graphql-response+json',
135
123
  },
136
124
  });
137
- assert('Status code', res.status).toBeBetween(400, 499);
125
+ ressert(res).status.toBeBetween(400, 499);
138
126
  }),
139
127
  // Request POST
140
128
  audit('SHOULD respond with 4xx status code if content-type is not supplied on POST requests', async () => {
141
129
  const res = await fetchFn(await getUrl(opts.url), {
142
130
  method: 'POST',
143
131
  });
144
- assert('Status code', res.status).toBeBetween(400, 499);
132
+ ressert(res).status.toBeBetween(400, 499);
145
133
  }),
146
134
  audit('MUST accept application/json POST requests', async () => {
147
135
  const res = await fetchFn(await getUrl(opts.url), {
@@ -149,7 +137,7 @@ export function serverAudits(opts) {
149
137
  headers: { 'content-type': 'application/json' },
150
138
  body: JSON.stringify({ query: '{ __typename }' }),
151
139
  });
152
- assert('Status code', res.status).toBe(200);
140
+ ressert(res).status.toBe(200);
153
141
  }),
154
142
  audit('MUST require a request body on POST', async () => {
155
143
  var _a;
@@ -158,10 +146,10 @@ export function serverAudits(opts) {
158
146
  headers: { 'content-type': 'application/json' },
159
147
  });
160
148
  if ((_a = res.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('application/json')) {
161
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
149
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
162
150
  }
163
151
  else {
164
- assert('Status code', res.status).toBe(400);
152
+ ressert(res).status.toBe(400);
165
153
  }
166
154
  }),
167
155
  // Request Parameters
@@ -176,7 +164,7 @@ export function serverAudits(opts) {
176
164
  },
177
165
  body: JSON.stringify({ notquery: '{ __typename }' }),
178
166
  });
179
- assert('Status code', res.status).toBe(400);
167
+ ressert(res).status.toBe(400);
180
168
  }),
181
169
  audit('SHOULD use 200 status code with errors field on missing {query} parameter when accepting application/json', async () => {
182
170
  const res = await fetchFn(await getUrl(opts.url), {
@@ -187,8 +175,8 @@ export function serverAudits(opts) {
187
175
  },
188
176
  body: JSON.stringify({ notquery: '{ __typename }' }),
189
177
  });
190
- assert('Status code', res.status).toBe(200);
191
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
178
+ ressert(res).status.toBe(200);
179
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
192
180
  }),
193
181
  ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(
194
182
  // TODO: convert to MUST after watershed
@@ -203,7 +191,7 @@ export function serverAudits(opts) {
203
191
  query: invalid,
204
192
  }),
205
193
  });
206
- assert('Status code', res.status).toBe(400);
194
+ ressert(res).status.toBe(400);
207
195
  })),
208
196
  ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {query} parameter when accepting application/json`, async () => {
209
197
  const res = await fetchFn(await getUrl(opts.url), {
@@ -216,8 +204,8 @@ export function serverAudits(opts) {
216
204
  query: invalid,
217
205
  }),
218
206
  });
219
- assert('Status code', res.status).toBe(200);
220
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
207
+ ressert(res).status.toBe(200);
208
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
221
209
  })),
222
210
  audit(
223
211
  // TODO: convert to MUST after watershed
@@ -232,7 +220,7 @@ export function serverAudits(opts) {
232
220
  query: '{ __typename }',
233
221
  }),
234
222
  });
235
- assert('Status code', res.status).toBe(200);
223
+ ressert(res).status.toBe(200);
236
224
  }),
237
225
  audit('MUST allow string {query} parameter when accepting application/json', async () => {
238
226
  const res = await fetchFn(await getUrl(opts.url), {
@@ -245,8 +233,8 @@ export function serverAudits(opts) {
245
233
  query: '{ __typename }',
246
234
  }),
247
235
  });
248
- assert('Status code', res.status).toBe(200);
249
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
236
+ ressert(res).status.toBe(200);
237
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
250
238
  }),
251
239
  ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(
252
240
  // TODO: convert to MUST after watershed
@@ -262,7 +250,7 @@ export function serverAudits(opts) {
262
250
  query: '{ __typename }',
263
251
  }),
264
252
  });
265
- assert('Status code', res.status).toBe(400);
253
+ ressert(res).status.toBe(400);
266
254
  })),
267
255
  ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {operationName} parameter when accepting application/json`, async () => {
268
256
  const res = await fetchFn(await getUrl(opts.url), {
@@ -276,8 +264,8 @@ export function serverAudits(opts) {
276
264
  query: '{ __typename }',
277
265
  }),
278
266
  });
279
- assert('Status code', res.status).toBe(200);
280
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
267
+ ressert(res).status.toBe(200);
268
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
281
269
  })),
282
270
  audit(
283
271
  // TODO: convert to MUST after watershed
@@ -293,7 +281,7 @@ export function serverAudits(opts) {
293
281
  query: 'query Query { __typename }',
294
282
  }),
295
283
  });
296
- assert('Status code', res.status).toBe(200);
284
+ ressert(res).status.toBe(200);
297
285
  }),
298
286
  audit('MUST allow string {operationName} parameter when accepting application/json', async () => {
299
287
  const res = await fetchFn(await getUrl(opts.url), {
@@ -307,8 +295,8 @@ export function serverAudits(opts) {
307
295
  query: 'query Query { __typename }',
308
296
  }),
309
297
  });
310
- assert('Status code', res.status).toBe(200);
311
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
298
+ ressert(res).status.toBe(200);
299
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
312
300
  }),
313
301
  ...['variables', 'operationName', 'extensions'].flatMap((parameter) => [
314
302
  audit(
@@ -325,8 +313,8 @@ export function serverAudits(opts) {
325
313
  [parameter]: null,
326
314
  }),
327
315
  });
328
- assert('Status code', res.status).toBe(200);
329
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
316
+ ressert(res).status.toBe(200);
317
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
330
318
  }),
331
319
  audit(`MUST allow null {${parameter}} parameter when accepting application/json`, async () => {
332
320
  const res = await fetchFn(await getUrl(opts.url), {
@@ -340,8 +328,8 @@ export function serverAudits(opts) {
340
328
  [parameter]: null,
341
329
  }),
342
330
  });
343
- assert('Status code', res.status).toBe(200);
344
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
331
+ ressert(res).status.toBe(200);
332
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
345
333
  }),
346
334
  ]),
347
335
  ...['string', 0, false, ['array']].map((invalid) => audit(
@@ -358,7 +346,7 @@ export function serverAudits(opts) {
358
346
  variables: invalid,
359
347
  }),
360
348
  });
361
- assert('Status code', res.status).toBe(400);
349
+ ressert(res).status.toBe(400);
362
350
  })),
363
351
  ...['string', 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {variables} parameter when accepting application/json`, async () => {
364
352
  const res = await fetchFn(await getUrl(opts.url), {
@@ -372,8 +360,8 @@ export function serverAudits(opts) {
372
360
  variables: invalid,
373
361
  }),
374
362
  });
375
- assert('Status code', res.status).toBe(200);
376
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
363
+ ressert(res).status.toBe(200);
364
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
377
365
  })),
378
366
  audit(
379
367
  // TODO: convert to MUST after watershed
@@ -389,7 +377,7 @@ export function serverAudits(opts) {
389
377
  variables: { name: 'sometype' },
390
378
  }),
391
379
  });
392
- assert('Status code', res.status).toBe(200);
380
+ ressert(res).status.toBe(200);
393
381
  }),
394
382
  audit('MUST allow map {variables} parameter when accepting application/json', async () => {
395
383
  const res = await fetchFn(await getUrl(opts.url), {
@@ -403,8 +391,8 @@ export function serverAudits(opts) {
403
391
  variables: { name: 'sometype' },
404
392
  }),
405
393
  });
406
- assert('Status code', res.status).toBe(200);
407
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
394
+ ressert(res).status.toBe(200);
395
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
408
396
  }),
409
397
  audit('MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/graphql-response+json', async () => {
410
398
  const url = new URL(await getUrl(opts.url));
@@ -416,7 +404,7 @@ export function serverAudits(opts) {
416
404
  accept: 'application/graphql-response+json',
417
405
  },
418
406
  });
419
- assert('Status code', res.status).toBe(200);
407
+ ressert(res).status.toBe(200);
420
408
  }),
421
409
  audit('MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/json', async () => {
422
410
  const url = new URL(await getUrl(opts.url));
@@ -428,8 +416,8 @@ export function serverAudits(opts) {
428
416
  accept: 'application/json',
429
417
  },
430
418
  });
431
- assert('Status code', res.status).toBe(200);
432
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
419
+ ressert(res).status.toBe(200);
420
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
433
421
  }),
434
422
  ...['string', 0, false, ['array']].map((invalid) => audit(
435
423
  // TODO: convert to MUST after watershed
@@ -445,7 +433,7 @@ export function serverAudits(opts) {
445
433
  extensions: invalid,
446
434
  }),
447
435
  });
448
- assert('Status code', res.status).toBe(400);
436
+ ressert(res).status.toBe(400);
449
437
  })),
450
438
  ...['string', 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {extensions} parameter when accepting application/json`, async () => {
451
439
  const res = await fetchFn(await getUrl(opts.url), {
@@ -459,8 +447,8 @@ export function serverAudits(opts) {
459
447
  extensions: invalid,
460
448
  }),
461
449
  });
462
- assert('Status code', res.status).toBe(200);
463
- assert('Execution result', await assertBodyAsExecutionResult(res)).toHaveProperty('errors');
450
+ ressert(res).status.toBe(200);
451
+ await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
464
452
  })),
465
453
  audit(
466
454
  // TODO: convert to MUST after watershed
@@ -476,7 +464,7 @@ export function serverAudits(opts) {
476
464
  extensions: { some: 'value' },
477
465
  }),
478
466
  });
479
- assert('Status code', res.status).toBe(200);
467
+ ressert(res).status.toBe(200);
480
468
  }),
481
469
  audit('MUST allow map {extensions} parameter when accepting application/json', async () => {
482
470
  const res = await fetchFn(await getUrl(opts.url), {
@@ -490,8 +478,8 @@ export function serverAudits(opts) {
490
478
  extensions: { some: 'value' },
491
479
  }),
492
480
  });
493
- assert('Status code', res.status).toBe(200);
494
- assert('Execution result', await assertBodyAsExecutionResult(res)).notToHaveProperty('errors');
481
+ ressert(res).status.toBe(200);
482
+ await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
495
483
  }),
496
484
  // TODO: audit('MUST accept a map for the {extensions} parameter'),
497
485
  // Response application/json
@@ -504,7 +492,7 @@ export function serverAudits(opts) {
504
492
  },
505
493
  body: '{ "not a JSON',
506
494
  });
507
- assert('Status code', res.status).toBe(200);
495
+ ressert(res).status.toBe(200);
508
496
  }),
509
497
  audit('SHOULD use 200 status code if parameters are invalid when accepting application/json', async () => {
510
498
  const res = await fetchFn(await getUrl(opts.url), {
@@ -517,7 +505,7 @@ export function serverAudits(opts) {
517
505
  qeury: /* typo */ '{ __typename }',
518
506
  }),
519
507
  });
520
- assert('Status code', res.status).toBe(200);
508
+ ressert(res).status.toBe(200);
521
509
  }),
522
510
  audit('SHOULD use 200 status code on document parsing failure when accepting application/json', async () => {
523
511
  const res = await fetchFn(await getUrl(opts.url), {
@@ -528,7 +516,7 @@ export function serverAudits(opts) {
528
516
  },
529
517
  body: JSON.stringify({ query: '{' }),
530
518
  });
531
- assert('Status code', res.status).toBe(200);
519
+ ressert(res).status.toBe(200);
532
520
  }),
533
521
  audit('SHOULD use 200 status code on document validation failure when accepting application/json', async () => {
534
522
  const res = await fetchFn(await getUrl(opts.url), {
@@ -541,7 +529,7 @@ export function serverAudits(opts) {
541
529
  query: '{ 8f31403dfe404bccbb0e835f2629c6a7 }', // making sure the field doesnt exist
542
530
  }),
543
531
  });
544
- assert('Status code', res.status).toBe(200);
532
+ ressert(res).status.toBe(200);
545
533
  }),
546
534
  // Response application/graphql-response+json
547
535
  audit(
@@ -555,7 +543,7 @@ export function serverAudits(opts) {
555
543
  },
556
544
  body: '{ "not a JSON',
557
545
  });
558
- assert('Status code', res.status).toBeBetween(400, 499);
546
+ ressert(res).status.toBeBetween(400, 499);
559
547
  }),
560
548
  audit('SHOULD use 400 status code on JSON parsing failure when accepting application/graphql-response+json', async () => {
561
549
  const res = await fetchFn(await getUrl(opts.url), {
@@ -566,7 +554,7 @@ export function serverAudits(opts) {
566
554
  },
567
555
  body: '{ "not a JSON',
568
556
  });
569
- assert('Status code', res.status).toBe(400);
557
+ ressert(res).status.toBe(400);
570
558
  }),
571
559
  audit('SHOULD not contain the data entry on JSON parsing failure when accepting application/graphql-response+json', async () => {
572
560
  const res = await fetchFn(await getUrl(opts.url), {
@@ -577,7 +565,7 @@ export function serverAudits(opts) {
577
565
  },
578
566
  body: '{ "not a JSON',
579
567
  });
580
- assert('Data entry', (await assertBodyAsExecutionResult(res)).data).toBe(undefined);
568
+ await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
581
569
  }),
582
570
  audit(
583
571
  // TODO: convert to MUST after watershed
@@ -592,7 +580,7 @@ export function serverAudits(opts) {
592
580
  qeury /* typo */: '{ __typename }',
593
581
  }),
594
582
  });
595
- assert('Status code', res.status).toBeBetween(400, 599);
583
+ ressert(res).status.toBeBetween(400, 599);
596
584
  }),
597
585
  audit('SHOULD use 400 status code if parameters are invalid when accepting application/graphql-response+json', async () => {
598
586
  const res = await fetchFn(await getUrl(opts.url), {
@@ -605,7 +593,7 @@ export function serverAudits(opts) {
605
593
  qeury: /* typo */ '{ __typename }',
606
594
  }),
607
595
  });
608
- assert('Status code', res.status).toBe(400);
596
+ ressert(res).status.toBe(400);
609
597
  }),
610
598
  audit('SHOULD not contain the data entry if parameters are invalid when accepting application/graphql-response+json', async () => {
611
599
  const res = await fetchFn(await getUrl(opts.url), {
@@ -618,7 +606,7 @@ export function serverAudits(opts) {
618
606
  qeury: /* typo */ '{ __typename }',
619
607
  }),
620
608
  });
621
- assert('Data entry', (await assertBodyAsExecutionResult(res)).data).toBe(undefined);
609
+ await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
622
610
  }),
623
611
  audit(
624
612
  // TODO: convert to MUST after watershed
@@ -633,7 +621,7 @@ export function serverAudits(opts) {
633
621
  query: '{',
634
622
  }),
635
623
  });
636
- assert('Status code', res.status).toBeBetween(400, 599);
624
+ ressert(res).status.toBeBetween(400, 599);
637
625
  }),
638
626
  audit('SHOULD use 400 status code on document parsing failure when accepting application/graphql-response+json', async () => {
639
627
  const res = await fetchFn(await getUrl(opts.url), {
@@ -646,7 +634,7 @@ export function serverAudits(opts) {
646
634
  query: '{',
647
635
  }),
648
636
  });
649
- assert('Status code', res.status).toBe(400);
637
+ ressert(res).status.toBe(400);
650
638
  }),
651
639
  audit('SHOULD not contain the data entry on document parsing failure when accepting application/graphql-response+json', async () => {
652
640
  const res = await fetchFn(await getUrl(opts.url), {
@@ -659,7 +647,7 @@ export function serverAudits(opts) {
659
647
  query: '{',
660
648
  }),
661
649
  });
662
- assert('Data entry', (await assertBodyAsExecutionResult(res)).data).toBe(undefined);
650
+ await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
663
651
  }),
664
652
  audit(
665
653
  // TODO: convert to MUST after watershed
@@ -674,7 +662,7 @@ export function serverAudits(opts) {
674
662
  query: '{ 8f31403dfe404bccbb0e835f2629c6a7 }', // making sure the field doesnt exist
675
663
  }),
676
664
  });
677
- assert('Status code', res.status).toBeBetween(400, 599);
665
+ ressert(res).status.toBeBetween(400, 599);
678
666
  }),
679
667
  audit('SHOULD use 400 status code on document validation failure when accepting application/graphql-response+json', async () => {
680
668
  const res = await fetchFn(await getUrl(opts.url), {
@@ -687,7 +675,7 @@ export function serverAudits(opts) {
687
675
  query: '{ 8f31403dfe404bccbb0e835f2629c6a7 }', // making sure the field doesnt exist
688
676
  }),
689
677
  });
690
- assert('Status code', res.status).toBe(400);
678
+ ressert(res).status.toBe(400);
691
679
  }),
692
680
  audit('SHOULD not contain the data entry on document validation failure when accepting application/graphql-response+json', async () => {
693
681
  const res = await fetchFn(await getUrl(opts.url), {
@@ -700,7 +688,7 @@ export function serverAudits(opts) {
700
688
  query: '{ 8f31403dfe404bccbb0e835f2629c6a7 }', // making sure the field doesnt exist
701
689
  }),
702
690
  });
703
- assert('Data entry', (await assertBodyAsExecutionResult(res)).data).toBe(undefined);
691
+ await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
704
692
  }),
705
693
  // TODO: how to fail and have the data entry?
706
694
  // audit('MUST use 2xx status code if response contains the data entry and it is not null when accepting application/graphql-response+json'),
@@ -13,25 +13,44 @@ export * from '../utils';
13
13
  */
14
14
  export declare function audit(name: AuditName, fn: () => Promise<void>): Audit;
15
15
  /**
16
- * Will throw a string if the assertion fails.
17
- *
18
- * All fatal problems will throw an instance of Error.
16
+ * Error thrown when an assertion test fails.
19
17
  *
20
18
  * @private
21
19
  */
22
- export declare function assert<T = unknown>(name: string, actual: T): {
23
- toBe: (expected: T) => void;
24
- toBeBetween: (min: T extends number ? T : never, max: T extends number ? T : never) => void;
25
- toContain: (expected: T extends (infer U)[] ? U : T extends string ? T : never) => void;
26
- notToContain: (expected: T extends (infer U_1)[] ? U_1 : T extends string ? T : never) => void;
27
- toHaveProperty: (prop: T extends Record<any, any> ? PropertyKey : never) => void;
28
- notToHaveProperty: (prop: T extends Record<any, any> ? PropertyKey : never) => void;
29
- };
20
+ export declare class AuditError {
21
+ /**
22
+ * Response from the server.
23
+ */
24
+ response: Response;
25
+ /**
26
+ * Reason for the failing audit.
27
+ */
28
+ reason: string;
29
+ constructor(response: Response, reason: string);
30
+ }
30
31
  /**
31
- * Parses the string as JSON and safely reports parsing issues for audits.
32
+ * Will throw an AuditError if the assertion on Response fails.
33
+ *
34
+ * All fatal problems will throw an instance of an Error.
32
35
  *
33
- * Assumes the parsed JSON will be an `ExecutionResult`.
36
+ * The name "ressert" is a wordplay combining "response" and "assert".
34
37
  *
35
38
  * @private
36
- * */
37
- export declare function assertBodyAsExecutionResult(res: Response): Promise<ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>>>;
39
+ */
40
+ export declare function ressert(res: Response): {
41
+ status: {
42
+ toBe(code: number): void;
43
+ toBeBetween: (min: number, max: number) => void;
44
+ };
45
+ header(key: 'content-type'): {
46
+ toContain(part: string): void;
47
+ notToContain(part: string): void;
48
+ };
49
+ bodyAsExecutionResult: {
50
+ data: {
51
+ toBe(val: ExecutionResult['data']): Promise<void>;
52
+ };
53
+ toHaveProperty(key: keyof ExecutionResult): Promise<void>;
54
+ notToHaveProperty(key: keyof ExecutionResult): Promise<void>;
55
+ };
56
+ };
@@ -13,25 +13,44 @@ export * from '../utils';
13
13
  */
14
14
  export declare function audit(name: AuditName, fn: () => Promise<void>): Audit;
15
15
  /**
16
- * Will throw a string if the assertion fails.
17
- *
18
- * All fatal problems will throw an instance of Error.
16
+ * Error thrown when an assertion test fails.
19
17
  *
20
18
  * @private
21
19
  */
22
- export declare function assert<T = unknown>(name: string, actual: T): {
23
- toBe: (expected: T) => void;
24
- toBeBetween: (min: T extends number ? T : never, max: T extends number ? T : never) => void;
25
- toContain: (expected: T extends (infer U)[] ? U : T extends string ? T : never) => void;
26
- notToContain: (expected: T extends (infer U_1)[] ? U_1 : T extends string ? T : never) => void;
27
- toHaveProperty: (prop: T extends Record<any, any> ? PropertyKey : never) => void;
28
- notToHaveProperty: (prop: T extends Record<any, any> ? PropertyKey : never) => void;
29
- };
20
+ export declare class AuditError {
21
+ /**
22
+ * Response from the server.
23
+ */
24
+ response: Response;
25
+ /**
26
+ * Reason for the failing audit.
27
+ */
28
+ reason: string;
29
+ constructor(response: Response, reason: string);
30
+ }
30
31
  /**
31
- * Parses the string as JSON and safely reports parsing issues for audits.
32
+ * Will throw an AuditError if the assertion on Response fails.
33
+ *
34
+ * All fatal problems will throw an instance of an Error.
32
35
  *
33
- * Assumes the parsed JSON will be an `ExecutionResult`.
36
+ * The name "ressert" is a wordplay combining "response" and "assert".
34
37
  *
35
38
  * @private
36
- * */
37
- export declare function assertBodyAsExecutionResult(res: Response): Promise<ExecutionResult<import("graphql/jsutils/ObjMap").ObjMap<unknown>, import("graphql/jsutils/ObjMap").ObjMap<unknown>>>;
39
+ */
40
+ export declare function ressert(res: Response): {
41
+ status: {
42
+ toBe(code: number): void;
43
+ toBeBetween: (min: number, max: number) => void;
44
+ };
45
+ header(key: 'content-type'): {
46
+ toContain(part: string): void;
47
+ notToContain(part: string): void;
48
+ };
49
+ bodyAsExecutionResult: {
50
+ data: {
51
+ toBe(val: ExecutionResult['data']): Promise<void>;
52
+ };
53
+ toHaveProperty(key: keyof ExecutionResult): Promise<void>;
54
+ notToHaveProperty(key: keyof ExecutionResult): Promise<void>;
55
+ };
56
+ };