@@ -38,7 +38,8 @@ export function serverAudits(opts: ServerAuditOptions): Audit[] {
38
38
return [
39
39
// Media Types
40
40
audit (
41
- 'MUST accept application/graphql-response+json and match the content-type' ,
41
+ // TODO: convert to MUST after watershed
42
+ 'SHOULD accept application/graphql-response+json and match the content-type' ,
42
43
async ( ) => {
43
44
const url = new URL ( opts . url ) ;
44
45
url . searchParams . set ( 'query' , '{ __typename }' ) ;
@@ -74,7 +75,8 @@ export function serverAudits(opts: ServerAuditOptions): Audit[] {
74
75
} ,
75
76
) ,
76
77
audit (
77
- 'MUST accept */* and use application/graphql-response+json for the content-type' ,
78
+ // TODO: convert to MUST after watershed
79
+ 'SHOULD accept */* and use application/graphql-response+json for the content-type' ,
78
80
async ( ) => {
79
81
const url = new URL ( opts . url ) ;
80
82
url . searchParams . set ( 'query' , '{ __typename }' ) ;
@@ -92,7 +94,8 @@ export function serverAudits(opts: ServerAuditOptions): Audit[] {
92
94
} ,
93
95
) ,
94
96
audit (
95
- 'MUST assume application/graphql-response+json content-type when accept is missing' ,
97
+ // TODO: convert to MUST after watershed
98
+ 'SHOULD assume application/graphql-response+json content-type when accept is missing' ,
96
99
async ( ) => {
97
100
const url = new URL ( opts . url ) ;
98
101
url . searchParams . set ( 'query' , '{ __typename }' ) ;
@@ -105,15 +108,40 @@ export function serverAudits(opts: ServerAuditOptions): Audit[] {
105
108
) . toContain ( 'application/graphql-response+json' ) ;
106
109
} ,
107
110
) ,
108
- audit ( 'MUST use utf-8 charset in response ' , async ( ) => {
111
+ audit ( 'MUST use utf-8 encoding when responding ' , async ( ) => {
109
112
const url = new URL ( opts . url ) ;
110
113
url . searchParams . set ( 'query' , '{ __typename }' ) ;
111
114
112
115
const res = await fetchFn ( url . toString ( ) ) ;
113
116
assert ( 'Status code' , res . status ) . toBe ( 200 ) ;
114
- assert ( 'Content-Type header' , res . headers . get ( 'content-type' ) ) . toContain (
115
- 'charset=utf-8' ,
116
- ) ;
117
+
118
+ // has charset set to utf-8
119
+ try {
120
+ assert (
121
+ 'Content-Type header' ,
122
+ res . headers . get ( 'content-type' ) ,
123
+ ) . toContain ( 'charset=utf-8' ) ;
124
+ return ;
125
+ } catch {
126
+ // noop, continue
127
+ }
128
+
129
+ // has no charset specified
130
+ assert (
131
+ 'Content-Type header' ,
132
+ res . headers . get ( 'content-type' ) ,
133
+ ) . notToContain ( 'charset' ) ;
134
+
135
+ // and the content is utf-8 encoded
136
+ try {
137
+ const decoder = new TextDecoder ( 'utf-8' ) ;
138
+ const decoded = decoder . decode ( await res . arrayBuffer ( ) ) ;
139
+ assert ( 'UTF-8 decoded body' , decoded ) . toBe (
140
+ '{"data":{"__typename":"Query"}}' ,
141
+ ) ;
142
+ } catch {
143
+ throw 'Body is not UTF-8 encoded' ;
144
+ }
117
145
} ) ,
118
146
audit ( 'MUST accept only utf-8 charset' , async ( ) => {
119
147
const url = new URL ( opts . url ) ;
@@ -124,10 +152,26 @@ export function serverAudits(opts: ServerAuditOptions): Audit[] {
124
152
accept : 'application/graphql-response+json; charset=iso-8859-1' ,
125
153
} ,
126
154
} ) ;
127
- assert ( 'Status code' , res . status ) . toBe ( 406 ) ;
128
- assert ( 'Accept header' , res . headers . get ( 'accept' ) ) . toContain (
129
- 'charset=utf-8' ,
130
- ) ;
155
+
156
+ // application/json is 200 + errors
157
+ const contentType = res . headers . get ( 'content-type' ) || '' ;
158
+ if ( contentType . includes ( 'application/json' ) ) {
159
+ assert ( `Content-Type ${ contentType } status code` , res . status ) . toBe ( 200 ) ;
160
+
161
+ const body = await res . json ( ) ;
162
+ assert ( 'Body data errors' , body . errors ) . toBeDefined ( ) ;
163
+ return ;
164
+ }
165
+
166
+ // other content-types must be 4xx
167
+ assert (
168
+ `Content-Type ${ contentType } status code` ,
169
+ res . status ,
170
+ ) . toBeGreaterThanOrEqual ( 400 ) ;
171
+ assert (
172
+ `Content-Type ${ contentType } status code` ,
173
+ res . status ,
174
+ ) . toBeLessThanOrEqual ( 499 ) ;
131
175
} ) ,
132
176
// Request
133
177
audit ( 'MUST accept POST requests' , async ( ) => {
0 commit comments