@@ -152,6 +152,114 @@ public function undefined_status_code_returns_failure(): void
152152 $ this ->assertStringContainsString ('Status code 404 not defined ' , $ result ->errors ()[0 ]);
153153 }
154154
155+ // ========================================
156+ // OAS 3.0 JSON-compatible content type tests
157+ // ========================================
158+
159+ #[Test]
160+ public function v30_problem_json_valid_response_passes (): void
161+ {
162+ $ result = $ this ->validator ->validate (
163+ 'petstore-3.0 ' ,
164+ 'GET ' ,
165+ '/v1/pets ' ,
166+ 400 ,
167+ [
168+ 'type ' => 'https://example.com/bad-request ' ,
169+ 'title ' => 'Bad Request ' ,
170+ 'status ' => 400 ,
171+ 'detail ' => 'Invalid query parameter ' ,
172+ ],
173+ );
174+
175+ $ this ->assertTrue ($ result ->isValid ());
176+ $ this ->assertSame ('/v1/pets ' , $ result ->matchedPath ());
177+ }
178+
179+ #[Test]
180+ public function v30_problem_json_invalid_response_fails (): void
181+ {
182+ $ result = $ this ->validator ->validate (
183+ 'petstore-3.0 ' ,
184+ 'GET ' ,
185+ '/v1/pets ' ,
186+ 400 ,
187+ [
188+ 'type ' => 'https://example.com/bad-request ' ,
189+ 'title ' => 'Bad Request ' ,
190+ 'status ' => 'not-an-integer ' ,
191+ ],
192+ );
193+
194+ $ this ->assertFalse ($ result ->isValid ());
195+ $ this ->assertNotEmpty ($ result ->errors ());
196+ }
197+
198+ #[Test]
199+ public function v30_problem_json_empty_body_fails (): void
200+ {
201+ $ result = $ this ->validator ->validate (
202+ 'petstore-3.0 ' ,
203+ 'GET ' ,
204+ '/v1/pets ' ,
205+ 400 ,
206+ null ,
207+ );
208+
209+ $ this ->assertFalse ($ result ->isValid ());
210+ $ this ->assertStringContainsString ('Response body is empty ' , $ result ->errors ()[0 ]);
211+ }
212+
213+ #[Test]
214+ public function v30_content_without_json_compatible_type_fails (): void
215+ {
216+ $ result = $ this ->validator ->validate (
217+ 'petstore-3.0 ' ,
218+ 'POST ' ,
219+ '/v1/pets ' ,
220+ 415 ,
221+ '<error>Unsupported</error> ' ,
222+ );
223+
224+ $ this ->assertFalse ($ result ->isValid ());
225+ $ this ->assertStringContainsString ('No JSON-compatible content type found ' , $ result ->errors ()[0 ]);
226+ $ this ->assertStringContainsString ('application/xml ' , $ result ->errors ()[0 ]);
227+ }
228+
229+ #[Test]
230+ public function v30_case_insensitive_content_type_matches (): void
231+ {
232+ $ result = $ this ->validator ->validate (
233+ 'petstore-3.0 ' ,
234+ 'GET ' ,
235+ '/v1/pets ' ,
236+ 422 ,
237+ [
238+ 'type ' => 'https://example.com/validation-error ' ,
239+ 'title ' => 'Validation Error ' ,
240+ 'status ' => 422 ,
241+ ],
242+ );
243+
244+ $ this ->assertTrue ($ result ->isValid ());
245+ $ this ->assertSame ('/v1/pets ' , $ result ->matchedPath ());
246+ }
247+
248+ #[Test]
249+ public function v30_json_content_type_without_schema_skips_validation (): void
250+ {
251+ $ result = $ this ->validator ->validate (
252+ 'petstore-3.0 ' ,
253+ 'GET ' ,
254+ '/v1/pets ' ,
255+ 500 ,
256+ ['error ' => 'something went wrong ' ],
257+ );
258+
259+ $ this ->assertTrue ($ result ->isValid ());
260+ $ this ->assertSame ('/v1/pets ' , $ result ->matchedPath ());
261+ }
262+
155263 // ========================================
156264 // OAS 3.1 tests
157265 // ========================================
@@ -195,6 +303,42 @@ public function v31_invalid_response_fails(): void
195303 $ this ->assertNotEmpty ($ result ->errors ());
196304 }
197305
306+ #[Test]
307+ public function v31_problem_json_valid_response_passes (): void
308+ {
309+ $ result = $ this ->validator ->validate (
310+ 'petstore-3.1 ' ,
311+ 'GET ' ,
312+ '/v1/pets ' ,
313+ 400 ,
314+ [
315+ 'type ' => 'https://example.com/bad-request ' ,
316+ 'title ' => 'Bad Request ' ,
317+ 'status ' => 400 ,
318+ 'detail ' => null ,
319+ ],
320+ );
321+
322+ $ this ->assertTrue ($ result ->isValid ());
323+ $ this ->assertSame ('/v1/pets ' , $ result ->matchedPath ());
324+ }
325+
326+ #[Test]
327+ public function v31_content_without_json_compatible_type_fails (): void
328+ {
329+ $ result = $ this ->validator ->validate (
330+ 'petstore-3.1 ' ,
331+ 'POST ' ,
332+ '/v1/pets ' ,
333+ 415 ,
334+ '<error>Unsupported</error> ' ,
335+ );
336+
337+ $ this ->assertFalse ($ result ->isValid ());
338+ $ this ->assertStringContainsString ('No JSON-compatible content type found ' , $ result ->errors ()[0 ]);
339+ $ this ->assertStringContainsString ('application/xml ' , $ result ->errors ()[0 ]);
340+ }
341+
198342 #[Test]
199343 public function v31_no_content_response_passes (): void
200344 {
0 commit comments