ClientTest.php 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  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 PHPUnit\Framework\TestCase;
  12. use Symfony\Component\BrowserKit\Client;
  13. use Symfony\Component\BrowserKit\History;
  14. use Symfony\Component\BrowserKit\CookieJar;
  15. use Symfony\Component\BrowserKit\Response;
  16. class SpecialResponse extends Response
  17. {
  18. }
  19. class TestClient extends Client
  20. {
  21. protected $nextResponse = null;
  22. protected $nextScript = null;
  23. public function setNextResponse(Response $response)
  24. {
  25. $this->nextResponse = $response;
  26. }
  27. public function setNextScript($script)
  28. {
  29. $this->nextScript = $script;
  30. }
  31. protected function doRequest($request)
  32. {
  33. if (null === $this->nextResponse) {
  34. return new Response();
  35. }
  36. $response = $this->nextResponse;
  37. $this->nextResponse = null;
  38. return $response;
  39. }
  40. protected function filterResponse($response)
  41. {
  42. if ($response instanceof SpecialResponse) {
  43. return new Response($response->getContent(), $response->getStatus(), $response->getHeaders());
  44. }
  45. return $response;
  46. }
  47. protected function getScript($request)
  48. {
  49. $r = new \ReflectionClass('Symfony\Component\BrowserKit\Response');
  50. $path = $r->getFileName();
  51. return <<<EOF
  52. <?php
  53. require_once('$path');
  54. echo serialize($this->nextScript);
  55. EOF;
  56. }
  57. }
  58. class ClientTest extends TestCase
  59. {
  60. public function testGetHistory()
  61. {
  62. $client = new TestClient(array(), $history = new History());
  63. $this->assertSame($history, $client->getHistory(), '->getHistory() returns the History');
  64. }
  65. public function testGetCookieJar()
  66. {
  67. $client = new TestClient(array(), null, $cookieJar = new CookieJar());
  68. $this->assertSame($cookieJar, $client->getCookieJar(), '->getCookieJar() returns the CookieJar');
  69. }
  70. public function testGetRequest()
  71. {
  72. $client = new TestClient();
  73. $client->request('GET', 'http://example.com/');
  74. $this->assertEquals('http://example.com/', $client->getRequest()->getUri(), '->getCrawler() returns the Request of the last request');
  75. }
  76. /**
  77. * @group legacy
  78. * @expectedDeprecation Calling the "Symfony\Component\BrowserKit\Client::getRequest()" method before the "request()" one is deprecated since Symfony 4.1 and will throw an exception in 5.0.
  79. */
  80. public function testGetRequestNull()
  81. {
  82. $client = new TestClient();
  83. $this->assertNull($client->getRequest());
  84. }
  85. public function testXmlHttpRequest()
  86. {
  87. $client = new TestClient();
  88. $client->xmlHttpRequest('GET', 'http://example.com/', array(), array(), array(), null, true);
  89. $this->assertEquals($client->getRequest()->getServer()['HTTP_X_REQUESTED_WITH'], 'XMLHttpRequest');
  90. $this->assertFalse($client->getServerParameter('HTTP_X_REQUESTED_WITH', false));
  91. }
  92. public function testGetRequestWithIpAsHttpHost()
  93. {
  94. $client = new TestClient();
  95. $client->request('GET', 'https://example.com/foo', array(), array(), array('HTTP_HOST' => '127.0.0.1'));
  96. $this->assertEquals('https://example.com/foo', $client->getRequest()->getUri());
  97. $headers = $client->getRequest()->getServer();
  98. $this->assertEquals('127.0.0.1', $headers['HTTP_HOST']);
  99. }
  100. public function testGetResponse()
  101. {
  102. $client = new TestClient();
  103. $client->setNextResponse(new Response('foo'));
  104. $client->request('GET', 'http://example.com/');
  105. $this->assertEquals('foo', $client->getResponse()->getContent(), '->getCrawler() returns the Response of the last request');
  106. $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getResponse(), '->getCrawler() returns the Response of the last request');
  107. }
  108. /**
  109. * @group legacy
  110. * @expectedDeprecation Calling the "Symfony\Component\BrowserKit\Client::getResponse()" method before the "request()" one is deprecated since Symfony 4.1 and will throw an exception in 5.0.
  111. */
  112. public function testGetResponseNull()
  113. {
  114. $client = new TestClient();
  115. $this->assertNull($client->getResponse());
  116. }
  117. public function testGetInternalResponse()
  118. {
  119. $client = new TestClient();
  120. $client->setNextResponse(new SpecialResponse('foo'));
  121. $client->request('GET', 'http://example.com/');
  122. $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
  123. $this->assertNotInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getInternalResponse());
  124. $this->assertInstanceOf('Symfony\Component\BrowserKit\Tests\SpecialResponse', $client->getResponse());
  125. }
  126. /**
  127. * @group legacy
  128. * @expectedDeprecation Calling the "Symfony\Component\BrowserKit\Client::getInternalResponse()" method before the "request()" one is deprecated since Symfony 4.1 and will throw an exception in 5.0.
  129. */
  130. public function testGetInternalResponseNull()
  131. {
  132. $client = new TestClient();
  133. $this->assertNull($client->getInternalResponse());
  134. }
  135. public function testGetContent()
  136. {
  137. $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
  138. $client = new TestClient();
  139. $client->request('POST', 'http://example.com/jsonrpc', array(), array(), array(), $json);
  140. $this->assertEquals($json, $client->getRequest()->getContent());
  141. }
  142. public function testGetCrawler()
  143. {
  144. $client = new TestClient();
  145. $client->setNextResponse(new Response('foo'));
  146. $crawler = $client->request('GET', 'http://example.com/');
  147. $this->assertSame($crawler, $client->getCrawler(), '->getCrawler() returns the Crawler of the last request');
  148. }
  149. /**
  150. * @group legacy
  151. * @expectedDeprecation Calling the "Symfony\Component\BrowserKit\Client::getCrawler()" method before the "request()" one is deprecated since Symfony 4.1 and will throw an exception in 5.0.
  152. */
  153. public function testGetCrawlerNull()
  154. {
  155. $client = new TestClient();
  156. $this->assertNull($client->getCrawler());
  157. }
  158. public function testRequestHttpHeaders()
  159. {
  160. $client = new TestClient();
  161. $client->request('GET', '/');
  162. $headers = $client->getRequest()->getServer();
  163. $this->assertEquals('localhost', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
  164. $client = new TestClient();
  165. $client->request('GET', 'http://www.example.com');
  166. $headers = $client->getRequest()->getServer();
  167. $this->assertEquals('www.example.com', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header');
  168. $client->request('GET', 'https://www.example.com');
  169. $headers = $client->getRequest()->getServer();
  170. $this->assertTrue($headers['HTTPS'], '->request() sets the HTTPS header');
  171. $client = new TestClient();
  172. $client->request('GET', 'http://www.example.com:8080');
  173. $headers = $client->getRequest()->getServer();
  174. $this->assertEquals('www.example.com:8080', $headers['HTTP_HOST'], '->request() sets the HTTP_HOST header with port');
  175. }
  176. public function testRequestURIConversion()
  177. {
  178. $client = new TestClient();
  179. $client->request('GET', '/foo');
  180. $this->assertEquals('http://localhost/foo', $client->getRequest()->getUri(), '->request() converts the URI to an absolute one');
  181. $client = new TestClient();
  182. $client->request('GET', 'http://www.example.com');
  183. $this->assertEquals('http://www.example.com', $client->getRequest()->getUri(), '->request() does not change absolute URIs');
  184. $client = new TestClient();
  185. $client->request('GET', 'http://www.example.com/');
  186. $client->request('GET', '/foo');
  187. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  188. $client = new TestClient();
  189. $client->request('GET', 'http://www.example.com/foo');
  190. $client->request('GET', '#');
  191. $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
  192. $client->request('GET', '#');
  193. $this->assertEquals('http://www.example.com/foo#', $client->getRequest()->getUri(), '->request() uses the previous request for #');
  194. $client->request('GET', '#foo');
  195. $this->assertEquals('http://www.example.com/foo#foo', $client->getRequest()->getUri(), '->request() uses the previous request for #');
  196. $client = new TestClient();
  197. $client->request('GET', 'http://www.example.com/foo/');
  198. $client->request('GET', 'bar');
  199. $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  200. $client = new TestClient();
  201. $client->request('GET', 'http://www.example.com/foo/foobar');
  202. $client->request('GET', 'bar');
  203. $this->assertEquals('http://www.example.com/foo/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  204. $client = new TestClient();
  205. $client->request('GET', 'http://www.example.com/foo/');
  206. $client->request('GET', 'http');
  207. $this->assertEquals('http://www.example.com/foo/http', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  208. $client = new TestClient();
  209. $client->request('GET', 'http://www.example.com/foo');
  210. $client->request('GET', 'http/bar');
  211. $this->assertEquals('http://www.example.com/http/bar', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  212. $client = new TestClient();
  213. $client->request('GET', 'http://www.example.com/');
  214. $client->request('GET', 'http');
  215. $this->assertEquals('http://www.example.com/http', $client->getRequest()->getUri(), '->request() uses the previous request for relative URLs');
  216. $client = new TestClient();
  217. $client->request('GET', 'http://www.example.com/foo');
  218. $client->request('GET', '?');
  219. $this->assertEquals('http://www.example.com/foo?', $client->getRequest()->getUri(), '->request() uses the previous request for ?');
  220. $client->request('GET', '?');
  221. $this->assertEquals('http://www.example.com/foo?', $client->getRequest()->getUri(), '->request() uses the previous request for ?');
  222. $client->request('GET', '?foo=bar');
  223. $this->assertEquals('http://www.example.com/foo?foo=bar', $client->getRequest()->getUri(), '->request() uses the previous request for ?');
  224. }
  225. public function testRequestReferer()
  226. {
  227. $client = new TestClient();
  228. $client->request('GET', 'http://www.example.com/foo/foobar');
  229. $client->request('GET', 'bar');
  230. $server = $client->getRequest()->getServer();
  231. $this->assertEquals('http://www.example.com/foo/foobar', $server['HTTP_REFERER'], '->request() sets the referer');
  232. }
  233. public function testRequestHistory()
  234. {
  235. $client = new TestClient();
  236. $client->request('GET', 'http://www.example.com/foo/foobar');
  237. $client->request('GET', 'bar');
  238. $this->assertEquals('http://www.example.com/foo/bar', $client->getHistory()->current()->getUri(), '->request() updates the History');
  239. $this->assertEquals('http://www.example.com/foo/foobar', $client->getHistory()->back()->getUri(), '->request() updates the History');
  240. }
  241. public function testRequestCookies()
  242. {
  243. $client = new TestClient();
  244. $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar')));
  245. $client->request('GET', 'http://www.example.com/foo/foobar');
  246. $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');
  247. $client->request('GET', 'bar');
  248. $this->assertEquals(array('foo' => 'bar'), $client->getCookieJar()->allValues('http://www.example.com/foo/foobar'), '->request() updates the CookieJar');
  249. }
  250. public function testRequestSecureCookies()
  251. {
  252. $client = new TestClient();
  253. $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>', 200, array('Set-Cookie' => 'foo=bar; path=/; secure')));
  254. $client->request('GET', 'https://www.example.com/foo/foobar');
  255. $this->assertTrue($client->getCookieJar()->get('foo', '/', 'www.example.com')->isSecure());
  256. }
  257. public function testClick()
  258. {
  259. $client = new TestClient();
  260. $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>'));
  261. $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
  262. $client->click($crawler->filter('a')->link());
  263. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links');
  264. }
  265. public function testClickLink()
  266. {
  267. $client = new TestClient();
  268. $client->setNextResponse(new Response('<html><a href="/foo">foo</a></html>'));
  269. $client->request('GET', 'http://www.example.com/foo/foobar');
  270. $client->clickLink('foo');
  271. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() clicks on links');
  272. }
  273. public function testClickLinkNotFound()
  274. {
  275. $client = new TestClient();
  276. $client->setNextResponse(new Response('<html><a href="/foo">foobar</a></html>'));
  277. $client->request('GET', 'http://www.example.com/foo/foobar');
  278. try {
  279. $client->clickLink('foo');
  280. $this->fail('->clickLink() throws a \InvalidArgumentException if the link could not be found');
  281. } catch (\Exception $e) {
  282. $this->assertInstanceOf('InvalidArgumentException', $e, '->clickLink() throws a \InvalidArgumentException if the link could not be found');
  283. }
  284. }
  285. public function testClickForm()
  286. {
  287. $client = new TestClient();
  288. $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
  289. $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
  290. $client->click($crawler->filter('input')->form());
  291. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->click() Form submit forms');
  292. }
  293. public function testSubmit()
  294. {
  295. $client = new TestClient();
  296. $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
  297. $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
  298. $client->submit($crawler->filter('input')->form());
  299. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
  300. }
  301. public function testSubmitForm()
  302. {
  303. $client = new TestClient();
  304. $client->setNextResponse(new Response('<html><form name="signup" action="/foo"><input type="text" name="username" /><input type="password" name="password" /><input type="submit" value="Register" /></form></html>'));
  305. $client->request('GET', 'http://www.example.com/foo/foobar');
  306. $client->submitForm('Register', array(
  307. 'username' => 'username',
  308. 'password' => 'password',
  309. ), 'POST');
  310. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
  311. }
  312. public function testSubmitFormNotFound()
  313. {
  314. $client = new TestClient();
  315. $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
  316. $client->request('GET', 'http://www.example.com/foo/foobar');
  317. try {
  318. $client->submitForm('Register', array(
  319. 'username' => 'username',
  320. 'password' => 'password',
  321. ), 'POST');
  322. $this->fail('->submitForm() throws a \InvalidArgumentException if the form could not be found');
  323. } catch (\Exception $e) {
  324. $this->assertInstanceOf('InvalidArgumentException', $e, '->submitForm() throws a \InvalidArgumentException if the form could not be found');
  325. }
  326. }
  327. public function testSubmitPreserveAuth()
  328. {
  329. $client = new TestClient(array('PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar'));
  330. $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
  331. $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
  332. $server = $client->getRequest()->getServer();
  333. $this->assertArrayHasKey('PHP_AUTH_USER', $server);
  334. $this->assertEquals('foo', $server['PHP_AUTH_USER']);
  335. $this->assertArrayHasKey('PHP_AUTH_PW', $server);
  336. $this->assertEquals('bar', $server['PHP_AUTH_PW']);
  337. $client->submit($crawler->filter('input')->form());
  338. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->submit() submit forms');
  339. $server = $client->getRequest()->getServer();
  340. $this->assertArrayHasKey('PHP_AUTH_USER', $server);
  341. $this->assertEquals('foo', $server['PHP_AUTH_USER']);
  342. $this->assertArrayHasKey('PHP_AUTH_PW', $server);
  343. $this->assertEquals('bar', $server['PHP_AUTH_PW']);
  344. }
  345. public function testSubmitPassthrewHeaders()
  346. {
  347. $client = new TestClient();
  348. $client->setNextResponse(new Response('<html><form action="/foo"><input type="submit" /></form></html>'));
  349. $crawler = $client->request('GET', 'http://www.example.com/foo/foobar');
  350. $headers = array('Accept-Language' => 'de');
  351. $client->submit($crawler->filter('input')->form(), array(), $headers);
  352. $server = $client->getRequest()->getServer();
  353. $this->assertArrayHasKey('Accept-Language', $server);
  354. $this->assertEquals('de', $server['Accept-Language']);
  355. }
  356. public function testFollowRedirect()
  357. {
  358. $client = new TestClient();
  359. $client->followRedirects(false);
  360. $client->request('GET', 'http://www.example.com/foo/foobar');
  361. try {
  362. $client->followRedirect();
  363. $this->fail('->followRedirect() throws a \LogicException if the request was not redirected');
  364. } catch (\Exception $e) {
  365. $this->assertInstanceOf('LogicException', $e, '->followRedirect() throws a \LogicException if the request was not redirected');
  366. }
  367. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
  368. $client->request('GET', 'http://www.example.com/foo/foobar');
  369. $client->followRedirect();
  370. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
  371. $client = new TestClient();
  372. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
  373. $client->request('GET', 'http://www.example.com/foo/foobar');
  374. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() automatically follows redirects if followRedirects is true');
  375. $client = new TestClient();
  376. $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
  377. $client->request('GET', 'http://www.example.com/foo/foobar');
  378. $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->followRedirect() does not follow redirect if HTTP Code is not 30x');
  379. $client = new TestClient();
  380. $client->setNextResponse(new Response('', 201, array('Location' => 'http://www.example.com/redirected')));
  381. $client->followRedirects(false);
  382. $client->request('GET', 'http://www.example.com/foo/foobar');
  383. try {
  384. $client->followRedirect();
  385. $this->fail('->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
  386. } catch (\Exception $e) {
  387. $this->assertInstanceOf('LogicException', $e, '->followRedirect() throws a \LogicException if the request did not respond with 30x HTTP Code');
  388. }
  389. }
  390. public function testFollowRelativeRedirect()
  391. {
  392. $client = new TestClient();
  393. $client->setNextResponse(new Response('', 302, array('Location' => '/redirected')));
  394. $client->request('GET', 'http://www.example.com/foo/foobar');
  395. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
  396. $client = new TestClient();
  397. $client->setNextResponse(new Response('', 302, array('Location' => '/redirected:1234')));
  398. $client->request('GET', 'http://www.example.com/foo/foobar');
  399. $this->assertEquals('http://www.example.com/redirected:1234', $client->getRequest()->getUri(), '->followRedirect() follows relative urls');
  400. }
  401. public function testFollowRedirectWithMaxRedirects()
  402. {
  403. $client = new TestClient();
  404. $client->setMaxRedirects(1);
  405. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
  406. $client->request('GET', 'http://www.example.com/foo/foobar');
  407. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
  408. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected2')));
  409. try {
  410. $client->followRedirect();
  411. $this->fail('->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
  412. } catch (\Exception $e) {
  413. $this->assertInstanceOf('LogicException', $e, '->followRedirect() throws a \LogicException if the request was redirected and limit of redirections was reached');
  414. }
  415. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
  416. $client->request('GET', 'http://www.example.com/foo/foobar');
  417. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect if any');
  418. $client->setNextResponse(new Response('', 302, array('Location' => '/redirected')));
  419. $client->request('GET', 'http://www.example.com/foo/foobar');
  420. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows relative URLs');
  421. $client = new TestClient();
  422. $client->setNextResponse(new Response('', 302, array('Location' => '//www.example.org/')));
  423. $client->request('GET', 'https://www.example.com/');
  424. $this->assertEquals('https://www.example.org/', $client->getRequest()->getUri(), '->followRedirect() follows protocol-relative URLs');
  425. $client = new TestClient();
  426. $client->setNextResponse(new Response('', 302, array('Location' => 'http://www.example.com/redirected')));
  427. $client->request('POST', 'http://www.example.com/foo/foobar', array('name' => 'bar'));
  428. $this->assertEquals('GET', $client->getRequest()->getMethod(), '->followRedirect() uses a GET for 302');
  429. $this->assertEquals(array(), $client->getRequest()->getParameters(), '->followRedirect() does not submit parameters when changing the method');
  430. }
  431. public function testFollowRedirectWithCookies()
  432. {
  433. $client = new TestClient();
  434. $client->followRedirects(false);
  435. $client->setNextResponse(new Response('', 302, array(
  436. 'Location' => 'http://www.example.com/redirected',
  437. 'Set-Cookie' => 'foo=bar',
  438. )));
  439. $client->request('GET', 'http://www.example.com/');
  440. $this->assertEquals(array(), $client->getRequest()->getCookies());
  441. $client->followRedirect();
  442. $this->assertEquals(array('foo' => 'bar'), $client->getRequest()->getCookies());
  443. }
  444. public function testFollowRedirectWithHeaders()
  445. {
  446. $headers = array(
  447. 'HTTP_HOST' => 'www.example.com',
  448. 'HTTP_USER_AGENT' => 'Symfony BrowserKit',
  449. 'CONTENT_TYPE' => 'application/vnd.custom+xml',
  450. 'HTTPS' => false,
  451. );
  452. $client = new TestClient();
  453. $client->followRedirects(false);
  454. $client->setNextResponse(new Response('', 302, array(
  455. 'Location' => 'http://www.example.com/redirected',
  456. )));
  457. $client->request('GET', 'http://www.example.com/', array(), array(), array(
  458. 'CONTENT_TYPE' => 'application/vnd.custom+xml',
  459. ));
  460. $this->assertEquals($headers, $client->getRequest()->getServer());
  461. $client->followRedirect();
  462. $headers['HTTP_REFERER'] = 'http://www.example.com/';
  463. $this->assertEquals($headers, $client->getRequest()->getServer());
  464. }
  465. public function testFollowRedirectWithPort()
  466. {
  467. $headers = array(
  468. 'HTTP_HOST' => 'www.example.com:8080',
  469. 'HTTP_USER_AGENT' => 'Symfony BrowserKit',
  470. 'HTTPS' => false,
  471. 'HTTP_REFERER' => 'http://www.example.com:8080/',
  472. );
  473. $client = new TestClient();
  474. $client->setNextResponse(new Response('', 302, array(
  475. 'Location' => 'http://www.example.com:8080/redirected',
  476. )));
  477. $client->request('GET', 'http://www.example.com:8080/');
  478. $this->assertEquals($headers, $client->getRequest()->getServer());
  479. }
  480. public function testIsFollowingRedirects()
  481. {
  482. $client = new TestClient();
  483. $this->assertTrue($client->isFollowingRedirects(), '->getFollowRedirects() returns default value');
  484. $client->followRedirects(false);
  485. $this->assertFalse($client->isFollowingRedirects(), '->getFollowRedirects() returns assigned value');
  486. }
  487. public function testGetMaxRedirects()
  488. {
  489. $client = new TestClient();
  490. $this->assertEquals(-1, $client->getMaxRedirects(), '->getMaxRedirects() returns default value');
  491. $client->setMaxRedirects(3);
  492. $this->assertEquals(3, $client->getMaxRedirects(), '->getMaxRedirects() returns assigned value');
  493. }
  494. public function testFollowRedirectWithPostMethod()
  495. {
  496. $parameters = array('foo' => 'bar');
  497. $files = array('myfile.foo' => 'baz');
  498. $server = array('X_TEST_FOO' => 'bazbar');
  499. $content = 'foobarbaz';
  500. $client = new TestClient();
  501. $client->setNextResponse(new Response('', 307, array('Location' => 'http://www.example.com/redirected')));
  502. $client->request('POST', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
  503. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect with POST method');
  504. $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->followRedirect() keeps parameters with POST method');
  505. $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->followRedirect() keeps files with POST method');
  506. $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->followRedirect() keeps $_SERVER with POST method');
  507. $this->assertEquals($content, $client->getRequest()->getContent(), '->followRedirect() keeps content with POST method');
  508. $this->assertEquals('POST', $client->getRequest()->getMethod(), '->followRedirect() keeps request method');
  509. }
  510. public function testFollowRedirectDropPostMethod()
  511. {
  512. $parameters = array('foo' => 'bar');
  513. $files = array('myfile.foo' => 'baz');
  514. $server = array('X_TEST_FOO' => 'bazbar');
  515. $content = 'foobarbaz';
  516. $client = new TestClient();
  517. foreach (array(301, 302, 303) as $code) {
  518. $client->setNextResponse(new Response('', $code, array('Location' => 'http://www.example.com/redirected')));
  519. $client->request('POST', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
  520. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->followRedirect() follows a redirect with POST method on response code: '.$code.'.');
  521. $this->assertEmpty($client->getRequest()->getParameters(), '->followRedirect() drops parameters with POST method on response code: '.$code.'.');
  522. $this->assertEmpty($client->getRequest()->getFiles(), '->followRedirect() drops files with POST method on response code: '.$code.'.');
  523. $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->followRedirect() keeps $_SERVER with POST method on response code: '.$code.'.');
  524. $this->assertEmpty($client->getRequest()->getContent(), '->followRedirect() drops content with POST method on response code: '.$code.'.');
  525. $this->assertEquals('GET', $client->getRequest()->getMethod(), '->followRedirect() drops request method to GET on response code: '.$code.'.');
  526. }
  527. }
  528. /**
  529. * @dataProvider getTestsForMetaRefresh
  530. */
  531. public function testFollowMetaRefresh(string $content, string $expectedEndingUrl, bool $followMetaRefresh = true)
  532. {
  533. $client = new TestClient();
  534. $client->followMetaRefresh($followMetaRefresh);
  535. $client->setNextResponse(new Response($content));
  536. $client->request('GET', 'http://www.example.com/foo/foobar');
  537. $this->assertEquals($expectedEndingUrl, $client->getRequest()->getUri());
  538. }
  539. public function getTestsForMetaRefresh()
  540. {
  541. return array(
  542. array('<html><head><meta http-equiv="Refresh" content="4" /><meta http-equiv="refresh" content="0; URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
  543. array('<html><head><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
  544. array('<html><head><meta http-equiv="refresh" content="0;URL=\'http://www.example.com/redirected\'"/></head></html>', 'http://www.example.com/redirected'),
  545. array('<html><head><meta http-equiv="refresh" content=\'0;URL="http://www.example.com/redirected"\'/></head></html>', 'http://www.example.com/redirected'),
  546. array('<html><head><meta http-equiv="refresh" content="0; URL = http://www.example.com/redirected"/></head></html>', 'http://www.example.com/redirected'),
  547. array('<html><head><meta http-equiv="refresh" content="0;URL= http://www.example.com/redirected "/></head></html>', 'http://www.example.com/redirected'),
  548. array('<html><head><meta http-equiv="refresh" content="0;url=http://www.example.com/redirected "/></head></html>', 'http://www.example.com/redirected'),
  549. array('<html><head><noscript><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></noscript></head></head></html>', 'http://www.example.com/redirected'),
  550. // Non-zero timeout should not result in a redirect.
  551. array('<html><head><meta http-equiv="refresh" content="4; URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/foo/foobar'),
  552. array('<html><body></body></html>', 'http://www.example.com/foo/foobar'),
  553. // Invalid meta tag placement should not result in a redirect.
  554. array('<html><body><meta http-equiv="refresh" content="0;url=http://www.example.com/redirected"/></body></html>', 'http://www.example.com/foo/foobar'),
  555. // Valid meta refresh should not be followed if disabled.
  556. array('<html><head><meta http-equiv="refresh" content="0;URL=http://www.example.com/redirected"/></head></html>', 'http://www.example.com/foo/foobar', false),
  557. );
  558. }
  559. public function testBack()
  560. {
  561. $client = new TestClient();
  562. $parameters = array('foo' => 'bar');
  563. $files = array('myfile.foo' => 'baz');
  564. $server = array('X_TEST_FOO' => 'bazbar');
  565. $content = 'foobarbaz';
  566. $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
  567. $client->request('GET', 'http://www.example.com/foo');
  568. $client->back();
  569. $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->back() goes back in the history');
  570. $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->back() keeps parameters');
  571. $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->back() keeps files');
  572. $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->back() keeps $_SERVER');
  573. $this->assertEquals($content, $client->getRequest()->getContent(), '->back() keeps content');
  574. }
  575. public function testForward()
  576. {
  577. $client = new TestClient();
  578. $parameters = array('foo' => 'bar');
  579. $files = array('myfile.foo' => 'baz');
  580. $server = array('X_TEST_FOO' => 'bazbar');
  581. $content = 'foobarbaz';
  582. $client->request('GET', 'http://www.example.com/foo/foobar');
  583. $client->request('GET', 'http://www.example.com/foo', $parameters, $files, $server, $content);
  584. $client->back();
  585. $client->forward();
  586. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->forward() goes forward in the history');
  587. $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->forward() keeps parameters');
  588. $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->forward() keeps files');
  589. $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->forward() keeps $_SERVER');
  590. $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content');
  591. }
  592. public function testBackAndFrowardWithRedirects()
  593. {
  594. $client = new TestClient();
  595. $client->request('GET', 'http://www.example.com/foo');
  596. $client->setNextResponse(new Response('', 301, array('Location' => 'http://www.example.com/redirected')));
  597. $client->request('GET', 'http://www.example.com/bar');
  598. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), 'client followed redirect');
  599. $client->back();
  600. $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->back() goes back in the history skipping redirects');
  601. $client->forward();
  602. $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->forward() goes forward in the history skipping redirects');
  603. }
  604. public function testReload()
  605. {
  606. $client = new TestClient();
  607. $parameters = array('foo' => 'bar');
  608. $files = array('myfile.foo' => 'baz');
  609. $server = array('X_TEST_FOO' => 'bazbar');
  610. $content = 'foobarbaz';
  611. $client->request('GET', 'http://www.example.com/foo/foobar', $parameters, $files, $server, $content);
  612. $client->reload();
  613. $this->assertEquals('http://www.example.com/foo/foobar', $client->getRequest()->getUri(), '->reload() reloads the current page');
  614. $this->assertArrayHasKey('foo', $client->getRequest()->getParameters(), '->reload() keeps parameters');
  615. $this->assertArrayHasKey('myfile.foo', $client->getRequest()->getFiles(), '->reload() keeps files');
  616. $this->assertArrayHasKey('X_TEST_FOO', $client->getRequest()->getServer(), '->reload() keeps $_SERVER');
  617. $this->assertEquals($content, $client->getRequest()->getContent(), '->reload() keeps content');
  618. }
  619. public function testRestart()
  620. {
  621. $client = new TestClient();
  622. $client->request('GET', 'http://www.example.com/foo/foobar');
  623. $client->restart();
  624. $this->assertTrue($client->getHistory()->isEmpty(), '->restart() clears the history');
  625. $this->assertEquals(array(), $client->getCookieJar()->all(), '->restart() clears the cookies');
  626. }
  627. public function testInsulatedRequests()
  628. {
  629. $client = new TestClient();
  630. $client->insulate();
  631. $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar')");
  632. $client->request('GET', 'http://www.example.com/foo/foobar');
  633. $this->assertEquals('foobar', $client->getResponse()->getContent(), '->insulate() process the request in a forked process');
  634. $client->setNextScript("new Symfony\Component\BrowserKit\Response('foobar)");
  635. try {
  636. $client->request('GET', 'http://www.example.com/foo/foobar');
  637. $this->fail('->request() throws a \RuntimeException if the script has an error');
  638. } catch (\Exception $e) {
  639. $this->assertInstanceOf('RuntimeException', $e, '->request() throws a \RuntimeException if the script has an error');
  640. }
  641. }
  642. public function testGetServerParameter()
  643. {
  644. $client = new TestClient();
  645. $this->assertEquals('', $client->getServerParameter('HTTP_HOST'));
  646. $this->assertEquals('Symfony BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
  647. $this->assertEquals('testvalue', $client->getServerParameter('testkey', 'testvalue'));
  648. }
  649. public function testSetServerParameter()
  650. {
  651. $client = new TestClient();
  652. $this->assertEquals('', $client->getServerParameter('HTTP_HOST'));
  653. $this->assertEquals('Symfony BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
  654. $client->setServerParameter('HTTP_HOST', 'testhost');
  655. $this->assertEquals('testhost', $client->getServerParameter('HTTP_HOST'));
  656. $client->setServerParameter('HTTP_USER_AGENT', 'testua');
  657. $this->assertEquals('testua', $client->getServerParameter('HTTP_USER_AGENT'));
  658. }
  659. public function testSetServerParameterInRequest()
  660. {
  661. $client = new TestClient();
  662. $this->assertEquals('', $client->getServerParameter('HTTP_HOST'));
  663. $this->assertEquals('Symfony BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
  664. $client->request('GET', 'https://www.example.com/https/www.example.com', array(), array(), array(
  665. 'HTTP_HOST' => 'testhost',
  666. 'HTTP_USER_AGENT' => 'testua',
  667. 'HTTPS' => false,
  668. 'NEW_SERVER_KEY' => 'new-server-key-value',
  669. ));
  670. $this->assertEquals('', $client->getServerParameter('HTTP_HOST'));
  671. $this->assertEquals('Symfony BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
  672. $this->assertEquals('http://www.example.com/https/www.example.com', $client->getRequest()->getUri());
  673. $server = $client->getRequest()->getServer();
  674. $this->assertArrayHasKey('HTTP_USER_AGENT', $server);
  675. $this->assertEquals('testua', $server['HTTP_USER_AGENT']);
  676. $this->assertArrayHasKey('HTTP_HOST', $server);
  677. $this->assertEquals('testhost', $server['HTTP_HOST']);
  678. $this->assertArrayHasKey('NEW_SERVER_KEY', $server);
  679. $this->assertEquals('new-server-key-value', $server['NEW_SERVER_KEY']);
  680. $this->assertArrayHasKey('HTTPS', $server);
  681. $this->assertFalse($server['HTTPS']);
  682. }
  683. public function testInternalRequest()
  684. {
  685. $client = new TestClient();
  686. $client->request('GET', 'https://www.example.com/https/www.example.com', array(), array(), array(
  687. 'HTTP_HOST' => 'testhost',
  688. 'HTTP_USER_AGENT' => 'testua',
  689. 'HTTPS' => false,
  690. 'NEW_SERVER_KEY' => 'new-server-key-value',
  691. ));
  692. $this->assertInstanceOf('Symfony\Component\BrowserKit\Request', $client->getInternalRequest());
  693. }
  694. /**
  695. * @group legacy
  696. * @expectedDeprecation Calling the "Symfony\Component\BrowserKit\Client::getInternalRequest()" method before the "request()" one is deprecated since Symfony 4.1 and will throw an exception in 5.0.
  697. */
  698. public function testInternalRequestNull()
  699. {
  700. $client = new TestClient();
  701. $this->assertNull($client->getInternalRequest());
  702. }
  703. }