44
55use WpOrg \Requests \Exception ;
66use WpOrg \Requests \Exception \InvalidArgument ;
7+ use WpOrg \Requests \Hooks ;
78use WpOrg \Requests \Iri ;
89use WpOrg \Requests \Requests ;
910use WpOrg \Requests \Response \Headers ;
1011use WpOrg \Requests \Tests \Fixtures \RawTransportMock ;
12+ use WpOrg \Requests \Tests \Fixtures \StringableObject ;
13+ use WpOrg \Requests \Tests \Fixtures \TestTransportMock ;
14+ use WpOrg \Requests \Tests \Fixtures \TransportFailedMock ;
15+ use WpOrg \Requests \Tests \Fixtures \TransportInvalidArgumentMock ;
1116use WpOrg \Requests \Tests \Fixtures \TransportMock ;
1217use WpOrg \Requests \Tests \TestCase ;
1318use WpOrg \Requests \Tests \TypeProviderHelper ;
@@ -152,6 +157,42 @@ public function testDefaultTransport() {
152157 $ this ->assertSame (200 , $ request ->status_code );
153158 }
154159
160+ public function testTransportFailedTriggersRequestsFailedCallback () {
161+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
162+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
163+ $ hooks = new Hooks ();
164+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
165+
166+ $ transport = new TransportFailedMock ();
167+
168+ $ options = [
169+ 'hooks ' => $ hooks ,
170+ 'transport ' => $ transport ,
171+ ];
172+
173+ $ this ->expectException (Exception::class);
174+ $ this ->expectExceptionMessage ('Transport failed! ' );
175+ Requests::get ('http://example.com/ ' , [], $ options );
176+ }
177+
178+ public function testTransportInvalidArgumentTriggersRequestsFailedCallback () {
179+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
180+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
181+ $ hooks = new Hooks ();
182+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
183+
184+ $ transport = new TransportInvalidArgumentMock ();
185+
186+ $ options = [
187+ 'hooks ' => $ hooks ,
188+ 'transport ' => $ transport ,
189+ ];
190+
191+ $ this ->expectException (InvalidArgument::class);
192+ $ this ->expectExceptionMessage ('Argument #1 ($url) must be of type string|Stringable ' );
193+ Requests::get ('http://example.com/ ' , [], $ options );
194+ }
195+
155196 /**
156197 * Standard response header parsing
157198 */
@@ -252,6 +293,31 @@ public function testInvalidProtocolVersion() {
252293 Requests::get ('http://example.com/ ' , [], $ options );
253294 }
254295
296+ /**
297+ * Check that invalid protocols are not accepted
298+ *
299+ * We do not support HTTP/0.9. If this is really an issue for you, file a
300+ * new issue, and update your server/proxy to support a proper protocol.
301+ */
302+ public function testInvalidProtocolVersionTriggersRequestsFailedCallback () {
303+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
304+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
305+ $ hooks = new Hooks ();
306+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
307+
308+ $ transport = new RawTransportMock ();
309+ $ transport ->data = "HTTP/0.9 200 OK \r\n\r\n<p>Test " ;
310+
311+ $ options = [
312+ 'hooks ' => $ hooks ,
313+ 'transport ' => $ transport ,
314+ ];
315+
316+ $ this ->expectException (Exception::class);
317+ $ this ->expectExceptionMessage ('Response could not be parsed ' );
318+ Requests::get ('http://example.com/ ' , [], $ options );
319+ }
320+
255321 /**
256322 * HTTP/0.9 also appears to use a single CRLF instead of two.
257323 */
@@ -268,6 +334,28 @@ public function testSingleCRLFSeparator() {
268334 Requests::get ('http://example.com/ ' , [], $ options );
269335 }
270336
337+ /**
338+ * HTTP/0.9 also appears to use a single CRLF instead of two.
339+ */
340+ public function testSingleCRLFSeparatorTriggersRequestsFailedCallback () {
341+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
342+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
343+ $ hooks = new Hooks ();
344+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
345+
346+ $ transport = new RawTransportMock ();
347+ $ transport ->data = "HTTP/0.9 200 OK \r\n<p>Test " ;
348+
349+ $ options = [
350+ 'hooks ' => $ hooks ,
351+ 'transport ' => $ transport ,
352+ ];
353+
354+ $ this ->expectException (Exception::class);
355+ $ this ->expectExceptionMessage ('Missing header/body separator ' );
356+ Requests::get ('http://example.com/ ' , [], $ options );
357+ }
358+
271359 public function testInvalidStatus () {
272360 $ transport = new RawTransportMock ();
273361 $ transport ->data = "HTTP/1.1 OK \r\nTest: value \nAnother-Test: value \r\n\r\nTest " ;
@@ -281,6 +369,25 @@ public function testInvalidStatus() {
281369 Requests::get ('http://example.com/ ' , [], $ options );
282370 }
283371
372+ public function testInvalidStatusTriggersRequestsFailedCallback () {
373+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
374+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
375+ $ hooks = new Hooks ();
376+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
377+
378+ $ transport = new RawTransportMock ();
379+ $ transport ->data = "HTTP/1.1 OK \r\nTest: value \nAnother-Test: value \r\n\r\nTest " ;
380+
381+ $ options = [
382+ 'hooks ' => $ hooks ,
383+ 'transport ' => $ transport ,
384+ ];
385+
386+ $ this ->expectException (Exception::class);
387+ $ this ->expectExceptionMessage ('Response could not be parsed ' );
388+ Requests::get ('http://example.com/ ' , [], $ options );
389+ }
390+
284391 public function test30xWithoutLocation () {
285392 $ transport = new TransportMock ();
286393 $ transport ->code = 302 ;
0 commit comments