graphql-http 1.17.0 → 1.18.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/README.md +1 -0
- package/lib/audits/common.d.mts +1 -1
- package/lib/audits/common.d.ts +1 -1
- package/lib/audits/index.d.mts +3 -3
- package/lib/audits/render.d.mts +1 -1
- package/lib/audits/render.js +15 -0
- package/lib/audits/render.mjs +15 -0
- package/lib/audits/server.d.mts +1 -1
- package/lib/audits/server.js +61 -161
- package/lib/audits/server.mjs +61 -161
- package/lib/audits/utils.d.mts +2 -2
- package/lib/audits/utils.js +6 -3
- package/lib/audits/utils.mjs +6 -3
- package/lib/client.d.mts +2 -2
- package/lib/handler.d.mts +22 -5
- package/lib/handler.d.ts +20 -3
- package/lib/handler.js +36 -14
- package/lib/handler.mjs +37 -15
- package/lib/index.d.mts +4 -4
- package/lib/use/express.d.mts +2 -2
- package/lib/use/fastify.d.mts +2 -2
- package/lib/use/fetch.d.mts +2 -2
- package/lib/use/http.d.mts +2 -2
- package/lib/use/http2.d.mts +2 -2
- package/lib/use/koa.d.mts +2 -2
- package/lib/use/node.d.mts +3 -3
- package/lib/utils.d.mts +2 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +15 -1
- package/lib/utils.mjs +13 -0
- package/package.json +16 -15
- package/umd/graphql-http-audits.js +82 -164
- package/umd/graphql-http-audits.min.js +1 -1
- package/umd/graphql-http-audits.min.js.gz +0 -0
package/README.md
CHANGED
|
@@ -788,6 +788,7 @@ Their compliance with the [GraphQL over HTTP spec](https://graphql.github.io/gra
|
|
|
788
788
|
| [graphql-helix](https://www.graphql-helix.com) | [✅ Compliant](/implementations/graphql-helix/README.md) |
|
|
789
789
|
| [graphql-yoga](https://www.the-guild.dev/graphql/yoga-server) | [✅ Compliant](/implementations/graphql-yoga/README.md) |
|
|
790
790
|
| [hotchocolate](https://chillicream.com/docs/hotchocolate) | [✅ Compliant](/implementations/hotchocolate/README.md) |
|
|
791
|
+
| [lighthouse](https://lighthouse-php.com) | [✅ Compliant](/implementations/lighthouse/README.md) |
|
|
791
792
|
| [pioneer](https://pioneer.dexclaimation.com) | [✅ Compliant](/implementations/pioneer/README.md) |
|
|
792
793
|
| [postgraphile](https://www.graphile.org/postgraphile) | [✅ Compliant](/implementations/postgraphile/README.md) |
|
|
793
794
|
<!-- prettier-ignore-end -->
|
package/lib/audits/common.d.mts
CHANGED
package/lib/audits/common.d.ts
CHANGED
package/lib/audits/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './common';
|
|
2
|
-
export * from './server';
|
|
3
|
-
export * from './render';
|
|
1
|
+
export * from './common.mjs';
|
|
2
|
+
export * from './server.mjs';
|
|
3
|
+
export * from './render.mjs';
|
package/lib/audits/render.d.mts
CHANGED
package/lib/audits/render.js
CHANGED
|
@@ -11,6 +11,7 @@ async function renderAuditResultsToHTML(results) {
|
|
|
11
11
|
const grouped = {
|
|
12
12
|
total: 0,
|
|
13
13
|
ok: [],
|
|
14
|
+
notice: [],
|
|
14
15
|
warn: [],
|
|
15
16
|
error: [],
|
|
16
17
|
};
|
|
@@ -33,6 +34,9 @@ async function renderAuditResultsToHTML(results) {
|
|
|
33
34
|
if (grouped.ok.length) {
|
|
34
35
|
report += `<li><span style="font-family: monospace">✅</span> <b>${grouped.ok.length}</b> pass</li>\n`;
|
|
35
36
|
}
|
|
37
|
+
if (grouped.notice.length) {
|
|
38
|
+
report += `<li><span style="font-family: monospace">💡</span> <b>${grouped.notice.length}</b> notices (suggestions)</li>\n`;
|
|
39
|
+
}
|
|
36
40
|
if (grouped.warn.length) {
|
|
37
41
|
// TODO: warning sign is rendered as "⚠️" in markdown instead of the emoji
|
|
38
42
|
report += `<li><span style="font-family: monospace">⚠️</span> <b>${grouped.warn.length}</b> warnings (optional)</li>\n`;
|
|
@@ -51,6 +55,17 @@ async function renderAuditResultsToHTML(results) {
|
|
|
51
55
|
report += '</ol>\n';
|
|
52
56
|
report += '\n';
|
|
53
57
|
}
|
|
58
|
+
if (grouped.notice.length) {
|
|
59
|
+
report += `<h2>Notices</h2>\n`;
|
|
60
|
+
report +=
|
|
61
|
+
'The server <i>MAY</i> support these, but are truly optional. These are suggestions following recommended conventions.\n';
|
|
62
|
+
report += '<ol>\n';
|
|
63
|
+
for (const [, result] of grouped.notice.entries()) {
|
|
64
|
+
report += await printAuditFail(result);
|
|
65
|
+
}
|
|
66
|
+
report += '</ol>\n';
|
|
67
|
+
report += '\n';
|
|
68
|
+
}
|
|
54
69
|
if (grouped.warn.length) {
|
|
55
70
|
report += `<h2>Warnings</h2>\n`;
|
|
56
71
|
report += 'The server <i>SHOULD</i> support these, but is not required.\n';
|
package/lib/audits/render.mjs
CHANGED
|
@@ -8,6 +8,7 @@ export async function renderAuditResultsToHTML(results) {
|
|
|
8
8
|
const grouped = {
|
|
9
9
|
total: 0,
|
|
10
10
|
ok: [],
|
|
11
|
+
notice: [],
|
|
11
12
|
warn: [],
|
|
12
13
|
error: [],
|
|
13
14
|
};
|
|
@@ -30,6 +31,9 @@ export async function renderAuditResultsToHTML(results) {
|
|
|
30
31
|
if (grouped.ok.length) {
|
|
31
32
|
report += `<li><span style="font-family: monospace">✅</span> <b>${grouped.ok.length}</b> pass</li>\n`;
|
|
32
33
|
}
|
|
34
|
+
if (grouped.notice.length) {
|
|
35
|
+
report += `<li><span style="font-family: monospace">💡</span> <b>${grouped.notice.length}</b> notices (suggestions)</li>\n`;
|
|
36
|
+
}
|
|
33
37
|
if (grouped.warn.length) {
|
|
34
38
|
// TODO: warning sign is rendered as "⚠️" in markdown instead of the emoji
|
|
35
39
|
report += `<li><span style="font-family: monospace">⚠️</span> <b>${grouped.warn.length}</b> warnings (optional)</li>\n`;
|
|
@@ -48,6 +52,17 @@ export async function renderAuditResultsToHTML(results) {
|
|
|
48
52
|
report += '</ol>\n';
|
|
49
53
|
report += '\n';
|
|
50
54
|
}
|
|
55
|
+
if (grouped.notice.length) {
|
|
56
|
+
report += `<h2>Notices</h2>\n`;
|
|
57
|
+
report +=
|
|
58
|
+
'The server <i>MAY</i> support these, but are truly optional. These are suggestions following recommended conventions.\n';
|
|
59
|
+
report += '<ol>\n';
|
|
60
|
+
for (const [, result] of grouped.notice.entries()) {
|
|
61
|
+
report += await printAuditFail(result);
|
|
62
|
+
}
|
|
63
|
+
report += '</ol>\n';
|
|
64
|
+
report += '\n';
|
|
65
|
+
}
|
|
51
66
|
if (grouped.warn.length) {
|
|
52
67
|
report += `<h2>Warnings</h2>\n`;
|
|
53
68
|
report += 'The server <i>SHOULD</i> support these, but is not required.\n';
|
package/lib/audits/server.d.mts
CHANGED
package/lib/audits/server.js
CHANGED
|
@@ -57,9 +57,13 @@ function serverAudits(opts) {
|
|
|
57
57
|
(0, utils_1.ressert)(res).header('content-type').toContain('application/json');
|
|
58
58
|
}),
|
|
59
59
|
(0, utils_1.audit)('80D8', 'SHOULD assume application/json content-type when accept is missing', async () => {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const res = await fetchFn(await getUrl(opts.url), {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: {
|
|
63
|
+
'content-type': 'application/json',
|
|
64
|
+
},
|
|
65
|
+
body: JSON.stringify({ query: '{ __typename }' }),
|
|
66
|
+
});
|
|
63
67
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
64
68
|
(0, utils_1.ressert)(res).header('content-type').toContain('application/json');
|
|
65
69
|
}),
|
|
@@ -86,7 +90,9 @@ function serverAudits(opts) {
|
|
|
86
90
|
headers: {
|
|
87
91
|
'content-type': 'application/json; charset=utf-8',
|
|
88
92
|
},
|
|
89
|
-
body: JSON.stringify({
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
query: '{ __type(name: "Run🏃Swim🏊") { name } }',
|
|
95
|
+
}),
|
|
90
96
|
});
|
|
91
97
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
92
98
|
}),
|
|
@@ -128,7 +134,7 @@ function serverAudits(opts) {
|
|
|
128
134
|
(0, utils_1.ressert)(res).status.toBeBetween(400, 499);
|
|
129
135
|
}),
|
|
130
136
|
// Request POST
|
|
131
|
-
(0, utils_1.audit)('9ABE', '
|
|
137
|
+
(0, utils_1.audit)('9ABE', 'MAY respond with 4xx status code if content-type is not supplied on POST requests', async () => {
|
|
132
138
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
133
139
|
method: 'POST',
|
|
134
140
|
});
|
|
@@ -142,23 +148,15 @@ function serverAudits(opts) {
|
|
|
142
148
|
});
|
|
143
149
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
144
150
|
}),
|
|
145
|
-
(0, utils_1.audit)('
|
|
146
|
-
var _a;
|
|
151
|
+
(0, utils_1.audit)('A5BF', 'MAY use 400 status code when request body is missing on POST', async () => {
|
|
147
152
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
148
153
|
method: 'POST',
|
|
149
154
|
headers: { 'content-type': 'application/json' },
|
|
150
155
|
});
|
|
151
|
-
|
|
152
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
(0, utils_1.ressert)(res).status.toBe(400);
|
|
156
|
-
}
|
|
156
|
+
(0, utils_1.ressert)(res).status.toBe(400);
|
|
157
157
|
}),
|
|
158
158
|
// Request Parameters
|
|
159
|
-
(0, utils_1.audit)(
|
|
160
|
-
// TODO: convert to MUST after watershed
|
|
161
|
-
'6610', 'SHOULD use 400 status code on missing {query} parameter when accepting application/graphql-response+json', async () => {
|
|
159
|
+
(0, utils_1.audit)('423L', 'MAY use 400 status code on missing {query} parameter', async () => {
|
|
162
160
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
163
161
|
method: 'POST',
|
|
164
162
|
headers: {
|
|
@@ -169,26 +167,11 @@ function serverAudits(opts) {
|
|
|
169
167
|
});
|
|
170
168
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
171
169
|
}),
|
|
172
|
-
(0, utils_1.audit)(
|
|
170
|
+
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`LKJ${index}`, `MAY use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {query} parameter`, async () => {
|
|
173
171
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
174
172
|
method: 'POST',
|
|
175
173
|
headers: {
|
|
176
174
|
'content-type': 'application/json',
|
|
177
|
-
accept: 'application/json',
|
|
178
|
-
},
|
|
179
|
-
body: JSON.stringify({ notquery: '{ __typename }' }),
|
|
180
|
-
});
|
|
181
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
182
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
183
|
-
}),
|
|
184
|
-
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`4F5${index}`,
|
|
185
|
-
// TODO: convert to MUST after watershed
|
|
186
|
-
`SHOULD use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {query} parameter when accepting application/graphql-response+json`, async () => {
|
|
187
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
188
|
-
method: 'POST',
|
|
189
|
-
headers: {
|
|
190
|
-
'content-type': 'application/json',
|
|
191
|
-
accept: 'application/graphql-response+json',
|
|
192
175
|
},
|
|
193
176
|
body: JSON.stringify({
|
|
194
177
|
query: invalid,
|
|
@@ -196,20 +179,6 @@ function serverAudits(opts) {
|
|
|
196
179
|
});
|
|
197
180
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
198
181
|
})),
|
|
199
|
-
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`9FE${index}`, `SHOULD use 200 status code with errors field on ${(0, utils_1.extendedTypeof)(invalid)} {query} parameter when accepting application/json`, async () => {
|
|
200
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
201
|
-
method: 'POST',
|
|
202
|
-
headers: {
|
|
203
|
-
'content-type': 'application/json',
|
|
204
|
-
accept: 'application/json',
|
|
205
|
-
},
|
|
206
|
-
body: JSON.stringify({
|
|
207
|
-
query: invalid,
|
|
208
|
-
}),
|
|
209
|
-
});
|
|
210
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
211
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
212
|
-
})),
|
|
213
182
|
(0, utils_1.audit)(
|
|
214
183
|
// TODO: convert to MUST after watershed
|
|
215
184
|
'34A2', 'SHOULD allow string {query} parameter when accepting application/graphql-response+json', async () => {
|
|
@@ -239,14 +208,11 @@ function serverAudits(opts) {
|
|
|
239
208
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
240
209
|
await (0, utils_1.ressert)(res).bodyAsExecutionResult.notToHaveProperty('errors');
|
|
241
210
|
}),
|
|
242
|
-
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`
|
|
243
|
-
// TODO: convert to MUST after watershed
|
|
244
|
-
`SHOULD use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {operationName} parameter when accepting application/graphql-response+json`, async () => {
|
|
211
|
+
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`6C0${index}`, `MAY use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {operationName} parameter`, async () => {
|
|
245
212
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
246
213
|
method: 'POST',
|
|
247
214
|
headers: {
|
|
248
215
|
'content-type': 'application/json',
|
|
249
|
-
accept: 'application/graphql-response+json',
|
|
250
216
|
},
|
|
251
217
|
body: JSON.stringify({
|
|
252
218
|
operationName: invalid,
|
|
@@ -255,21 +221,6 @@ function serverAudits(opts) {
|
|
|
255
221
|
});
|
|
256
222
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
257
223
|
})),
|
|
258
|
-
...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`FB9${index}`, `SHOULD use 200 status code with errors field on ${(0, utils_1.extendedTypeof)(invalid)} {operationName} parameter when accepting application/json`, async () => {
|
|
259
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
260
|
-
method: 'POST',
|
|
261
|
-
headers: {
|
|
262
|
-
'content-type': 'application/json',
|
|
263
|
-
accept: 'application/json',
|
|
264
|
-
},
|
|
265
|
-
body: JSON.stringify({
|
|
266
|
-
operationName: invalid,
|
|
267
|
-
query: '{ __typename }',
|
|
268
|
-
}),
|
|
269
|
-
});
|
|
270
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
271
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
272
|
-
})),
|
|
273
224
|
(0, utils_1.audit)(
|
|
274
225
|
// TODO: convert to MUST after watershed
|
|
275
226
|
'8161', 'SHOULD allow string {operationName} parameter when accepting application/graphql-response+json', async () => {
|
|
@@ -335,14 +286,11 @@ function serverAudits(opts) {
|
|
|
335
286
|
await (0, utils_1.ressert)(res).bodyAsExecutionResult.notToHaveProperty('errors');
|
|
336
287
|
}),
|
|
337
288
|
]),
|
|
338
|
-
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`
|
|
339
|
-
// TODO: convert to MUST after watershed
|
|
340
|
-
`SHOULD use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {variables} parameter when accepting application/graphql-response+json`, async () => {
|
|
289
|
+
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`476${index}`, `MAY use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {variables} parameter`, async () => {
|
|
341
290
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
342
291
|
method: 'POST',
|
|
343
292
|
headers: {
|
|
344
293
|
'content-type': 'application/json',
|
|
345
|
-
accept: 'application/graphql-response+json',
|
|
346
294
|
},
|
|
347
295
|
body: JSON.stringify({
|
|
348
296
|
query: '{ __typename }',
|
|
@@ -351,21 +299,6 @@ function serverAudits(opts) {
|
|
|
351
299
|
});
|
|
352
300
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
353
301
|
})),
|
|
354
|
-
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`F05${index}`, `SHOULD use 200 status code with errors field on ${(0, utils_1.extendedTypeof)(invalid)} {variables} parameter when accepting application/json`, async () => {
|
|
355
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
356
|
-
method: 'POST',
|
|
357
|
-
headers: {
|
|
358
|
-
'content-type': 'application/json',
|
|
359
|
-
accept: 'application/json',
|
|
360
|
-
},
|
|
361
|
-
body: JSON.stringify({
|
|
362
|
-
query: '{ __typename }',
|
|
363
|
-
variables: invalid,
|
|
364
|
-
}),
|
|
365
|
-
});
|
|
366
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
367
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
368
|
-
})),
|
|
369
302
|
(0, utils_1.audit)(
|
|
370
303
|
// TODO: convert to MUST after watershed
|
|
371
304
|
'2EA1', 'SHOULD allow map {variables} parameter when accepting application/graphql-response+json', async () => {
|
|
@@ -422,14 +355,13 @@ function serverAudits(opts) {
|
|
|
422
355
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
423
356
|
await (0, utils_1.ressert)(res).bodyAsExecutionResult.notToHaveProperty('errors');
|
|
424
357
|
}),
|
|
425
|
-
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`
|
|
358
|
+
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`58B${index}`,
|
|
426
359
|
// TODO: convert to MUST after watershed
|
|
427
|
-
`
|
|
360
|
+
`MAY use 400 status code on ${(0, utils_1.extendedTypeof)(invalid)} {extensions} parameter`, async () => {
|
|
428
361
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
429
362
|
method: 'POST',
|
|
430
363
|
headers: {
|
|
431
364
|
'content-type': 'application/json',
|
|
432
|
-
accept: 'application/graphql-response+json',
|
|
433
365
|
},
|
|
434
366
|
body: JSON.stringify({
|
|
435
367
|
query: '{ __typename }',
|
|
@@ -438,21 +370,6 @@ function serverAudits(opts) {
|
|
|
438
370
|
});
|
|
439
371
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
440
372
|
})),
|
|
441
|
-
...['string', 0, false, ['array']].map((invalid, index) => (0, utils_1.audit)(`368${index}`, `SHOULD use 200 status code with errors field on ${(0, utils_1.extendedTypeof)(invalid)} {extensions} parameter when accepting application/json`, async () => {
|
|
442
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
443
|
-
method: 'POST',
|
|
444
|
-
headers: {
|
|
445
|
-
'content-type': 'application/json',
|
|
446
|
-
accept: 'application/json',
|
|
447
|
-
},
|
|
448
|
-
body: JSON.stringify({
|
|
449
|
-
query: '{ __typename }',
|
|
450
|
-
extensions: invalid,
|
|
451
|
-
}),
|
|
452
|
-
});
|
|
453
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
454
|
-
await (0, utils_1.ressert)(res).bodyAsExecutionResult.toHaveProperty('errors');
|
|
455
|
-
})),
|
|
456
373
|
(0, utils_1.audit)(
|
|
457
374
|
// TODO: convert to MUST after watershed
|
|
458
375
|
'428F', 'SHOULD allow map {extensions} parameter when accepting application/graphql-response+json', async () => {
|
|
@@ -484,122 +401,91 @@ function serverAudits(opts) {
|
|
|
484
401
|
(0, utils_1.ressert)(res).status.toBe(200);
|
|
485
402
|
await (0, utils_1.ressert)(res).bodyAsExecutionResult.notToHaveProperty('errors');
|
|
486
403
|
}),
|
|
487
|
-
|
|
488
|
-
// Response application/json
|
|
489
|
-
(0, utils_1.audit)('D477', 'SHOULD use 200 status code on JSON parsing failure when accepting application/json', async () => {
|
|
404
|
+
(0, utils_1.audit)('B6DC', 'MAY use 4xx or 5xx status codes on JSON parsing failure', async () => {
|
|
490
405
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
491
406
|
method: 'POST',
|
|
492
407
|
headers: {
|
|
493
408
|
'content-type': 'application/json',
|
|
494
|
-
accept: 'application/json',
|
|
495
409
|
},
|
|
496
410
|
body: '{ "not a JSON',
|
|
497
411
|
});
|
|
498
|
-
(0, utils_1.ressert)(res).status.
|
|
499
|
-
}),
|
|
500
|
-
(0, utils_1.audit)('F5AF', 'SHOULD use 200 status code if parameters are invalid when accepting application/json', async () => {
|
|
501
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
502
|
-
method: 'POST',
|
|
503
|
-
headers: {
|
|
504
|
-
'content-type': 'application/json',
|
|
505
|
-
accept: 'application/json',
|
|
506
|
-
},
|
|
507
|
-
body: JSON.stringify({
|
|
508
|
-
qeury: /* typo */ '{ __typename }',
|
|
509
|
-
}),
|
|
510
|
-
});
|
|
511
|
-
(0, utils_1.ressert)(res).status.toBe(200);
|
|
412
|
+
(0, utils_1.ressert)(res).status.toBeBetween(400, 499);
|
|
512
413
|
}),
|
|
513
|
-
(0, utils_1.audit)('
|
|
414
|
+
(0, utils_1.audit)('BCF8', 'MAY use 400 status code on JSON parsing failure', async () => {
|
|
514
415
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
515
416
|
method: 'POST',
|
|
516
417
|
headers: {
|
|
517
418
|
'content-type': 'application/json',
|
|
518
|
-
accept: 'application/json',
|
|
519
419
|
},
|
|
520
|
-
body:
|
|
420
|
+
body: '{ "not a JSON',
|
|
521
421
|
});
|
|
522
|
-
(0, utils_1.ressert)(res).status.toBe(
|
|
422
|
+
(0, utils_1.ressert)(res).status.toBe(400);
|
|
523
423
|
}),
|
|
524
|
-
(0, utils_1.audit)('
|
|
424
|
+
(0, utils_1.audit)('8764', 'MAY use 4xx or 5xx status codes if parameters are invalid', async () => {
|
|
525
425
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
526
426
|
method: 'POST',
|
|
527
427
|
headers: {
|
|
528
428
|
'content-type': 'application/json',
|
|
529
|
-
accept: 'application/json',
|
|
530
429
|
},
|
|
531
430
|
body: JSON.stringify({
|
|
532
|
-
|
|
431
|
+
qeury /* typo */: '{ __typename }',
|
|
533
432
|
}),
|
|
534
433
|
});
|
|
535
|
-
(0, utils_1.ressert)(res).status.
|
|
434
|
+
(0, utils_1.ressert)(res).status.toBeBetween(400, 599);
|
|
536
435
|
}),
|
|
537
|
-
|
|
538
|
-
(0, utils_1.audit)(
|
|
539
|
-
// TODO: convert to MUST after watershed
|
|
540
|
-
'60AA', 'SHOULD use 4xx or 5xx status codes on JSON parsing failure when accepting application/graphql-response+json', async () => {
|
|
436
|
+
(0, utils_1.audit)('3E3A', 'MAY use 400 status code if parameters are invalid', async () => {
|
|
541
437
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
542
438
|
method: 'POST',
|
|
543
439
|
headers: {
|
|
544
440
|
'content-type': 'application/json',
|
|
545
|
-
accept: 'application/graphql-response+json',
|
|
546
441
|
},
|
|
547
|
-
body:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}),
|
|
551
|
-
(0, utils_1.audit)('2163', 'SHOULD use 400 status code on JSON parsing failure when accepting application/graphql-response+json', async () => {
|
|
552
|
-
const res = await fetchFn(await getUrl(opts.url), {
|
|
553
|
-
method: 'POST',
|
|
554
|
-
headers: {
|
|
555
|
-
'content-type': 'application/json',
|
|
556
|
-
accept: 'application/graphql-response+json',
|
|
557
|
-
},
|
|
558
|
-
body: '{ "not a JSON',
|
|
442
|
+
body: JSON.stringify({
|
|
443
|
+
qeury: /* typo */ '{ __typename }',
|
|
444
|
+
}),
|
|
559
445
|
});
|
|
560
446
|
(0, utils_1.ressert)(res).status.toBe(400);
|
|
561
447
|
}),
|
|
562
|
-
(
|
|
563
|
-
//
|
|
564
|
-
'
|
|
448
|
+
// TODO: audit('39AA', 'MUST accept a map for the {extensions} parameter'),
|
|
449
|
+
// Response application/json
|
|
450
|
+
(0, utils_1.audit)('572B', 'SHOULD use 200 status code on document parsing failure when accepting application/json', async () => {
|
|
565
451
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
566
452
|
method: 'POST',
|
|
567
453
|
headers: {
|
|
568
454
|
'content-type': 'application/json',
|
|
569
|
-
accept: 'application/
|
|
455
|
+
accept: 'application/json',
|
|
570
456
|
},
|
|
571
|
-
body: JSON.stringify({
|
|
572
|
-
qeury /* typo */: '{ __typename }',
|
|
573
|
-
}),
|
|
457
|
+
body: JSON.stringify({ query: '{' }),
|
|
574
458
|
});
|
|
575
|
-
(0, utils_1.ressert)(res).status.
|
|
459
|
+
(0, utils_1.ressert)(res).status.toBe(200);
|
|
576
460
|
}),
|
|
577
|
-
(0, utils_1.audit)('
|
|
461
|
+
(0, utils_1.audit)('FDE2', 'SHOULD use 200 status code on document validation failure when accepting application/json', async () => {
|
|
578
462
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
579
463
|
method: 'POST',
|
|
580
464
|
headers: {
|
|
581
465
|
'content-type': 'application/json',
|
|
582
|
-
accept: 'application/
|
|
466
|
+
accept: 'application/json',
|
|
583
467
|
},
|
|
584
468
|
body: JSON.stringify({
|
|
585
|
-
|
|
469
|
+
query: '{ 8f31403dfe404bccbb0e835f2629c6a7 }', // making sure the field doesnt exist
|
|
586
470
|
}),
|
|
587
471
|
});
|
|
588
|
-
(0, utils_1.ressert)(res).status.toBe(
|
|
472
|
+
(0, utils_1.ressert)(res).status.toBe(200);
|
|
589
473
|
}),
|
|
590
|
-
(0, utils_1.audit)('
|
|
474
|
+
(0, utils_1.audit)('7B9B', 'SHOULD use a status code of 200 on variable coercion failure when accepting application/json', async () => {
|
|
591
475
|
const res = await fetchFn(await getUrl(opts.url), {
|
|
592
476
|
method: 'POST',
|
|
593
477
|
headers: {
|
|
594
478
|
'content-type': 'application/json',
|
|
595
|
-
accept: 'application/
|
|
479
|
+
accept: 'application/json',
|
|
596
480
|
},
|
|
597
481
|
body: JSON.stringify({
|
|
598
|
-
|
|
482
|
+
query: 'query CoerceFailure($id: ID!){ __typename }',
|
|
483
|
+
variables: { id: null },
|
|
599
484
|
}),
|
|
600
485
|
});
|
|
601
|
-
|
|
486
|
+
(0, utils_1.ressert)(res).status.toBe(200);
|
|
602
487
|
}),
|
|
488
|
+
// Response application/graphql-response+json
|
|
603
489
|
(0, utils_1.audit)(
|
|
604
490
|
// TODO: convert to MUST after watershed
|
|
605
491
|
'865D', 'SHOULD use 4xx or 5xx status codes on document parsing failure when accepting application/graphql-response+json', async () => {
|
|
@@ -682,6 +568,20 @@ function serverAudits(opts) {
|
|
|
682
568
|
});
|
|
683
569
|
await (0, utils_1.ressert)(res).bodyAsExecutionResult.data.toBe(undefined);
|
|
684
570
|
}),
|
|
571
|
+
(0, utils_1.audit)('86EE', 'SHOULD use a status code of 400 on variable coercion failure when accepting application/graphql-response+json', async () => {
|
|
572
|
+
const res = await fetchFn(await getUrl(opts.url), {
|
|
573
|
+
method: 'POST',
|
|
574
|
+
headers: {
|
|
575
|
+
'content-type': 'application/json',
|
|
576
|
+
accept: 'application/graphql-response+json',
|
|
577
|
+
},
|
|
578
|
+
body: JSON.stringify({
|
|
579
|
+
query: 'query CoerceFailure($id: ID!){ __typename }',
|
|
580
|
+
variables: { id: null },
|
|
581
|
+
}),
|
|
582
|
+
});
|
|
583
|
+
(0, utils_1.ressert)(res).status.toBe(400);
|
|
584
|
+
}),
|
|
685
585
|
// TODO: how to fail and have the data entry?
|
|
686
586
|
// audit('EE52', 'MUST use 2xx status code if response contains the data entry and it is not null when accepting application/graphql-response+json'),
|
|
687
587
|
// TODO: how to make an unauthorized request?
|