99use WpOrg \Requests \Capability ;
1010use WpOrg \Requests \Exception ;
1111use WpOrg \Requests \Exception \InvalidArgument ;
12+ use WpOrg \Requests \Hooks ;
1213use WpOrg \Requests \Iri ;
1314use WpOrg \Requests \Requests ;
1415use WpOrg \Requests \Response \Headers ;
1516use WpOrg \Requests \Tests \Fixtures \ArrayAccessibleObject ;
1617use WpOrg \Requests \Tests \Fixtures \RawTransportMock ;
1718use WpOrg \Requests \Tests \Fixtures \StringableObject ;
1819use WpOrg \Requests \Tests \Fixtures \TestTransportMock ;
20+ use WpOrg \Requests \Tests \Fixtures \TransportFailedMock ;
21+ use WpOrg \Requests \Tests \Fixtures \TransportInvalidArgumentMock ;
1922use WpOrg \Requests \Tests \Fixtures \TransportMock ;
2023
2124final class RequestsTest extends TestCase {
@@ -172,6 +175,42 @@ public function testDefaultTransport() {
172175 $ this ->assertSame (200 , $ request ->status_code );
173176 }
174177
178+ public function testTransportFailedTriggersRequestsFailedCallback () {
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 TransportFailedMock ();
185+
186+ $ options = [
187+ 'hooks ' => $ hooks ,
188+ 'transport ' => $ transport ,
189+ ];
190+
191+ $ this ->expectException (Exception::class);
192+ $ this ->expectExceptionMessage ('Transport failed! ' );
193+ Requests::get ('http://example.com/ ' , [], $ options );
194+ }
195+
196+ public function testTransportInvalidArgumentTriggersRequestsFailedCallback () {
197+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
198+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
199+ $ hooks = new Hooks ();
200+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
201+
202+ $ transport = new TransportInvalidArgumentMock ();
203+
204+ $ options = [
205+ 'hooks ' => $ hooks ,
206+ 'transport ' => $ transport ,
207+ ];
208+
209+ $ this ->expectException (InvalidArgument::class);
210+ $ this ->expectExceptionMessage ('Argument #1 ($url) must be of type string|Stringable ' );
211+ Requests::get ('http://example.com/ ' , [], $ options );
212+ }
213+
175214 /**
176215 * Standard response header parsing
177216 */
@@ -272,6 +311,31 @@ public function testInvalidProtocolVersion() {
272311 Requests::get ('http://example.com/ ' , [], $ options );
273312 }
274313
314+ /**
315+ * Check that invalid protocols are not accepted
316+ *
317+ * We do not support HTTP/0.9. If this is really an issue for you, file a
318+ * new issue, and update your server/proxy to support a proper protocol.
319+ */
320+ public function testInvalidProtocolVersionTriggersRequestsFailedCallback () {
321+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
322+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
323+ $ hooks = new Hooks ();
324+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
325+
326+ $ transport = new RawTransportMock ();
327+ $ transport ->data = "HTTP/0.9 200 OK \r\n\r\n<p>Test " ;
328+
329+ $ options = [
330+ 'hooks ' => $ hooks ,
331+ 'transport ' => $ transport ,
332+ ];
333+
334+ $ this ->expectException (Exception::class);
335+ $ this ->expectExceptionMessage ('Response could not be parsed ' );
336+ Requests::get ('http://example.com/ ' , [], $ options );
337+ }
338+
275339 /**
276340 * HTTP/0.9 also appears to use a single CRLF instead of two.
277341 */
@@ -288,6 +352,28 @@ public function testSingleCRLFSeparator() {
288352 Requests::get ('http://example.com/ ' , [], $ options );
289353 }
290354
355+ /**
356+ * HTTP/0.9 also appears to use a single CRLF instead of two.
357+ */
358+ public function testSingleCRLFSeparatorTriggersRequestsFailedCallback () {
359+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
360+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
361+ $ hooks = new Hooks ();
362+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
363+
364+ $ transport = new RawTransportMock ();
365+ $ transport ->data = "HTTP/0.9 200 OK \r\n<p>Test " ;
366+
367+ $ options = [
368+ 'hooks ' => $ hooks ,
369+ 'transport ' => $ transport ,
370+ ];
371+
372+ $ this ->expectException (Exception::class);
373+ $ this ->expectExceptionMessage ('Missing header/body separator ' );
374+ Requests::get ('http://example.com/ ' , [], $ options );
375+ }
376+
291377 public function testInvalidStatus () {
292378 $ transport = new RawTransportMock ();
293379 $ transport ->data = "HTTP/1.1 OK \r\nTest: value \nAnother-Test: value \r\n\r\nTest " ;
@@ -301,6 +387,25 @@ public function testInvalidStatus() {
301387 Requests::get ('http://example.com/ ' , [], $ options );
302388 }
303389
390+ public function testInvalidStatusTriggersRequestsFailedCallback () {
391+ $ mock = $ this ->getMockBuilder (stdClass::class)->setMethods (['failed ' ])->getMock ();
392+ $ mock ->expects ($ this ->atLeastOnce ())->method ('failed ' );
393+ $ hooks = new Hooks ();
394+ $ hooks ->register ('requests.failed ' , [$ mock , 'failed ' ]);
395+
396+ $ transport = new RawTransportMock ();
397+ $ transport ->data = "HTTP/1.1 OK \r\nTest: value \nAnother-Test: value \r\n\r\nTest " ;
398+
399+ $ options = [
400+ 'hooks ' => $ hooks ,
401+ 'transport ' => $ transport ,
402+ ];
403+
404+ $ this ->expectException (Exception::class);
405+ $ this ->expectExceptionMessage ('Response could not be parsed ' );
406+ Requests::get ('http://example.com/ ' , [], $ options );
407+ }
408+
304409 public function test30xWithoutLocation () {
305410 $ transport = new TransportMock ();
306411 $ transport ->code = 302 ;
0 commit comments