HttpBrowserTest.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\BrowserKit\Tests;
  11. use Symfony\Component\BrowserKit\CookieJar;
  12. use Symfony\Component\BrowserKit\History;
  13. use Symfony\Component\BrowserKit\HttpBrowser;
  14. use Symfony\Component\BrowserKit\Response;
  15. use Symfony\Component\HttpClient\MockHttpClient;
  16. use Symfony\Component\HttpClient\Response\MockResponse;
  17. use Symfony\Contracts\HttpClient\HttpClientInterface;
  18. use Symfony\Contracts\HttpClient\ResponseInterface;
  19. class SpecialHttpResponse extends Response
  20. {
  21. }
  22. class TestHttpClient extends HttpBrowser
  23. {
  24. protected $nextResponse = null;
  25. protected $nextScript = null;
  26. public function __construct(array $server = [], History $history = null, CookieJar $cookieJar = null)
  27. {
  28. $client = new MockHttpClient(function (string $method, string $url, array $options) {
  29. if (null === $this->nextResponse) {
  30. return new MockResponse();
  31. }
  32. return new MockResponse($this->nextResponse->getContent(), [
  33. 'http_code' => $this->nextResponse->getStatusCode(),
  34. 'response_headers' => $this->nextResponse->getHeaders(),
  35. ]);
  36. });
  37. parent::__construct($client);
  38. $this->setServerParameters($server);
  39. $this->history = $history ?? new History();
  40. $this->cookieJar = $cookieJar ?? new CookieJar();
  41. }
  42. public function setNextResponse(Response $response)
  43. {
  44. $this->nextResponse = $response;
  45. }
  46. public function setNextScript($script)
  47. {
  48. $this->nextScript = $script;
  49. }
  50. protected function filterResponse($response)
  51. {
  52. if ($response instanceof SpecialHttpResponse) {
  53. return new Response($response->getContent(), $response->getStatusCode(), $response->getHeaders());
  54. }
  55. return $response;
  56. }
  57. protected function doRequest($request)
  58. {
  59. $response = parent::doRequest($request);
  60. if (null === $this->nextResponse) {
  61. return $response;
  62. }
  63. $class = \get_class($this->nextResponse);
  64. $response = new $class($response->getContent(), $response->getStatusCode(), $response->getHeaders());
  65. $this->nextResponse = null;
  66. return $response;
  67. }
  68. protected function getScript($request)
  69. {
  70. $r = new \ReflectionClass('Symfony\Component\BrowserKit\Response');
  71. $path = $r->getFileName();
  72. return <<<EOF
  73. <?php
  74. require_once('$path');
  75. echo serialize($this->nextScript);
  76. EOF;
  77. }
  78. }
  79. class HttpBrowserTest extends AbstractBrowserTest
  80. {
  81. public function getBrowser(array $server = [], History $history = null, CookieJar $cookieJar = null)
  82. {
  83. return new TestHttpClient($server, $history, $cookieJar);
  84. }
  85. public function testGetInternalResponse()
  86. {
  87. $client = $this->getBrowser();
  88. $client->setNextResponse(new SpecialHttpResponse('foo'));
  89. $client->request('GET', 'http://example.com/');
  90. $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
  91. $this->assertNotInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialHttpResponse', $client->getInternalResponse());
  92. $this->assertInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialHttpResponse', $client->getResponse());
  93. }
  94. /**
  95. * @dataProvider validContentTypes
  96. */
  97. public function testRequestHeaders(array $request, array $exepectedCall)
  98. {
  99. $client = $this->createMock(HttpClientInterface::class);
  100. $client
  101. ->expects($this->once())
  102. ->method('request')
  103. ->with(...$exepectedCall)
  104. ->willReturn($this->createMock(ResponseInterface::class));
  105. $browser = new HttpBrowser($client);
  106. $browser->request(...$request);
  107. }
  108. public function validContentTypes()
  109. {
  110. $defaultHeaders = ['user-agent' => 'Symfony BrowserKit', 'host' => 'example.com'];
  111. yield 'GET/HEAD' => [
  112. ['GET', 'http://example.com/', ['key' => 'value']],
  113. ['GET', 'http://example.com/', ['headers' => $defaultHeaders, 'body' => '', 'max_redirects' => 0]],
  114. ];
  115. yield 'empty form' => [
  116. ['POST', 'http://example.com/'],
  117. ['POST', 'http://example.com/', ['headers' => $defaultHeaders, 'body' => '', 'max_redirects' => 0]],
  118. ];
  119. yield 'form' => [
  120. ['POST', 'http://example.com/', ['key' => 'value', 'key2' => 'value']],
  121. ['POST', 'http://example.com/', ['headers' => $defaultHeaders + ['Content-Type' => 'application/x-www-form-urlencoded'], 'body' => 'key=value&key2=value', 'max_redirects' => 0]],
  122. ];
  123. yield 'content' => [
  124. ['POST', 'http://example.com/', [], [], [], 'content'],
  125. ['POST', 'http://example.com/', ['headers' => $defaultHeaders + ['Content-Type: text/plain; charset=utf-8', 'Content-Transfer-Encoding: 8bit'], 'body' => 'content', 'max_redirects' => 0]],
  126. ];
  127. }
  128. public function testMultiPartRequest()
  129. {
  130. $client = $this->createMock(HttpClientInterface::class);
  131. $client
  132. ->expects($this->once())
  133. ->method('request')
  134. ->with('POST', 'http://example.com/', $this->callback(function ($options) {
  135. $this->assertContains('Content-Type: multipart/form-data', implode('', $options['headers']));
  136. $this->assertInstanceOf('\Generator', $options['body']);
  137. $this->assertContains('my_file', implode('', iterator_to_array($options['body'])));
  138. return true;
  139. }))
  140. ->willReturn($this->createMock(ResponseInterface::class));
  141. $browser = new HttpBrowser($client);
  142. $path = tempnam(sys_get_temp_dir(), 'http');
  143. file_put_contents($path, 'my_file');
  144. $browser->request('POST', 'http://example.com/', [], ['file' => ['tmp_name' => $path, 'name' => 'foo']]);
  145. }
  146. }