IntegrationTestCaseTest.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\TestSuite;
  16. use Cake\Core\Configure;
  17. use Cake\Event\EventManager;
  18. use Cake\Network\Response;
  19. use Cake\Routing\DispatcherFactory;
  20. use Cake\Routing\Router;
  21. use Cake\TestSuite\IntegrationTestCase;
  22. use Cake\Test\Fixture\AssertIntegrationTestCase;
  23. use Cake\Utility\Security;
  24. /**
  25. * Self test of the IntegrationTestCase
  26. */
  27. class IntegrationTestCaseTest extends IntegrationTestCase
  28. {
  29. /**
  30. * Setup method
  31. *
  32. * @return void
  33. */
  34. public function setUp()
  35. {
  36. parent::setUp();
  37. Configure::write('App.namespace', 'TestApp');
  38. Router::connect('/:controller/:action/*', [], ['routeClass' => 'InflectedRoute']);
  39. DispatcherFactory::clear();
  40. DispatcherFactory::add('Routing');
  41. DispatcherFactory::add('ControllerFactory');
  42. $this->useHttpServer(false);
  43. }
  44. /**
  45. * Test building a request.
  46. *
  47. * @return void
  48. */
  49. public function testRequestBuilding()
  50. {
  51. $this->configRequest([
  52. 'headers' => ['X-CSRF-Token' => 'abc123'],
  53. 'base' => '',
  54. 'webroot' => '/',
  55. 'environment' => [
  56. 'PHP_AUTH_USER' => 'foo',
  57. 'PHP_AUTH_PW' => 'bar'
  58. ]
  59. ]);
  60. $this->cookie('split_token', 'def345');
  61. $this->session(['User' => ['id' => 1, 'username' => 'mark']]);
  62. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  63. $this->assertEquals('abc123', $request['environment']['HTTP_X_CSRF_TOKEN']);
  64. $this->assertEquals('/tasks/add', $request['url']);
  65. $this->assertArrayHasKey('split_token', $request['cookies']);
  66. $this->assertEquals('def345', $request['cookies']['split_token']);
  67. $this->assertEquals(['id' => '1', 'username' => 'mark'], $request['session']->read('User'));
  68. $this->assertEquals('foo', $request['environment']['PHP_AUTH_USER']);
  69. $this->assertEquals('bar', $request['environment']['PHP_AUTH_PW']);
  70. }
  71. /**
  72. * Test request building adds csrf tokens
  73. *
  74. * @return void
  75. */
  76. public function testRequestBuildingCsrfTokens()
  77. {
  78. $this->enableCsrfToken();
  79. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  80. $this->assertArrayHasKey('csrfToken', $request['cookies']);
  81. $this->assertArrayHasKey('_csrfToken', $request['post']);
  82. $this->assertSame($request['cookies']['csrfToken'], $request['post']['_csrfToken']);
  83. $this->cookie('csrfToken', '');
  84. $request = $this->_buildRequest('/tasks/add', 'POST', [
  85. '_csrfToken' => 'fale',
  86. 'title' => 'First post'
  87. ]);
  88. $this->assertSame('', $request['cookies']['csrfToken']);
  89. $this->assertSame('fale', $request['post']['_csrfToken']);
  90. }
  91. /**
  92. * Test multiple actions using CSRF tokens don't fail
  93. *
  94. * @return void
  95. */
  96. public function testEnableCsrfMultipleRequests()
  97. {
  98. $this->enableCsrfToken();
  99. $first = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  100. $second = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'Second post']);
  101. $this->assertSame(
  102. $first['cookies']['csrfToken'],
  103. $second['post']['_csrfToken'],
  104. 'Csrf token should match cookie'
  105. );
  106. $this->assertSame(
  107. $first['post']['_csrfToken'],
  108. $second['post']['_csrfToken'],
  109. 'Tokens should be consistent per test method'
  110. );
  111. }
  112. /**
  113. * Test pre-determined CSRF tokens.
  114. *
  115. * @return void
  116. */
  117. public function testEnableCsrfPredeterminedCookie()
  118. {
  119. $this->enableCsrfToken();
  120. $value = 'I am a teapot';
  121. $this->cookie('csrfToken', $value);
  122. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  123. $this->assertSame($value, $request['cookies']['csrfToken'], 'Csrf token should match cookie');
  124. $this->assertSame($value, $request['post']['_csrfToken'], 'Tokens should match');
  125. }
  126. /**
  127. * Test building a request, with query parameters
  128. *
  129. * @return void
  130. */
  131. public function testRequestBuildingQueryParameters()
  132. {
  133. $request = $this->_buildRequest('/tasks/view?archived=yes', 'GET', []);
  134. $this->assertEquals('/tasks/view', $request['url']);
  135. $this->assertEquals('yes', $request['query']['archived']);
  136. }
  137. /**
  138. * Test cookie encrypted
  139. *
  140. * @see CookieComponentControllerTest
  141. */
  142. public function testCookieEncrypted()
  143. {
  144. Security::salt('abcdabcdabcdabcdabcdabcdabcdabcdabcd');
  145. $this->cookieEncrypted('KeyOfCookie', 'Encrypted with aes by default');
  146. $request = $this->_buildRequest('/tasks/view', 'GET', []);
  147. $this->assertStringStartsWith('Q2FrZQ==.', $request['cookies']['KeyOfCookie']);
  148. }
  149. /**
  150. * Test sending get requests.
  151. *
  152. * @return void
  153. */
  154. public function testGet()
  155. {
  156. $this->assertNull($this->_response);
  157. $this->get('/request_action/test_request_action');
  158. $this->assertNotEmpty($this->_response);
  159. $this->assertInstanceOf('Cake\Network\Response', $this->_response);
  160. $this->assertEquals('This is a test', $this->_response->body());
  161. }
  162. /**
  163. * Test sending get requests with Http\Server
  164. *
  165. * @return void
  166. */
  167. public function testGetHttpServer()
  168. {
  169. DispatcherFactory::clear();
  170. $this->useHttpServer(true);
  171. $this->assertNull($this->_response);
  172. $this->get('/request_action/test_request_action');
  173. $this->assertNotEmpty($this->_response);
  174. $this->assertInstanceOf('Cake\Network\Response', $this->_response);
  175. $this->assertEquals('This is a test', $this->_response->body());
  176. $this->assertHeader('X-Middleware', 'true');
  177. }
  178. /**
  179. * Test that the PSR7 requests get query string data
  180. *
  181. * @return void
  182. */
  183. public function testQueryStringHttpServer()
  184. {
  185. $this->useHttpServer(true);
  186. $this->configRequest(['headers' => ['Content-Type' => 'text/plain']]);
  187. $this->get('/request_action/params_pass?q=query');
  188. $this->assertResponseOk();
  189. $this->assertResponseContains('"q":"query"');
  190. $this->assertResponseContains('"contentType":"text\/plain"');
  191. $this->assertHeader('X-Middleware', 'true');
  192. }
  193. /**
  194. * Test that the PSR7 requests get cookies
  195. *
  196. * @return void
  197. */
  198. public function testGetCookiesHttpServer()
  199. {
  200. $this->useHttpServer(true);
  201. $this->configRequest(['cookies' => ['split_test' => 'abc']]);
  202. $this->get('/request_action/cookie_pass');
  203. $this->assertResponseOk();
  204. $this->assertResponseContains('"split_test":"abc"');
  205. $this->assertHeader('X-Middleware', 'true');
  206. }
  207. /**
  208. * Test that the PSR7 requests get post data
  209. *
  210. * @return void
  211. */
  212. public function testPostDataHttpServer()
  213. {
  214. $this->useHttpServer(true);
  215. $this->post('/request_action/post_pass', ['title' => 'value']);
  216. $data = json_decode($this->_response->body());
  217. $this->assertEquals('value', $data->title);
  218. $this->assertHeader('X-Middleware', 'true');
  219. }
  220. /**
  221. * Test sending requests stores references to controller/view/layout.
  222. *
  223. * @return void
  224. */
  225. public function testRequestSetsProperties()
  226. {
  227. $this->post('/posts/index');
  228. $this->assertInstanceOf('Cake\Controller\Controller', $this->_controller);
  229. $this->assertNotEmpty($this->_viewName, 'View name not set');
  230. $this->assertContains('Template' . DS . 'Posts' . DS . 'index.ctp', $this->_viewName);
  231. $this->assertNotEmpty($this->_layoutName, 'Layout name not set');
  232. $this->assertContains('Template' . DS . 'Layout' . DS . 'default.ctp', $this->_layoutName);
  233. $this->assertTemplate('index');
  234. $this->assertLayout('default');
  235. $this->assertEquals('value', $this->viewVariable('test'));
  236. }
  237. /**
  238. * Test PSR7 requests store references to controller/view/layout
  239. *
  240. * @return void
  241. */
  242. public function testRequestSetsPropertiesHttpServer()
  243. {
  244. $this->useHttpServer(true);
  245. DispatcherFactory::clear();
  246. $this->post('/posts/index');
  247. $this->assertInstanceOf('Cake\Controller\Controller', $this->_controller);
  248. $this->assertNotEmpty($this->_viewName, 'View name not set');
  249. $this->assertContains('Template' . DS . 'Posts' . DS . 'index.ctp', $this->_viewName);
  250. $this->assertNotEmpty($this->_layoutName, 'Layout name not set');
  251. $this->assertContains('Template' . DS . 'Layout' . DS . 'default.ctp', $this->_layoutName);
  252. $this->assertTemplate('index');
  253. $this->assertLayout('default');
  254. $this->assertEquals('value', $this->viewVariable('test'));
  255. }
  256. /**
  257. * Assert that the stored template doesn't change when cells are rendered.
  258. *
  259. * @return void
  260. */
  261. public function testAssertTemplateAfterCellRender()
  262. {
  263. $this->get('/posts/get');
  264. $this->assertContains('Template' . DS . 'Posts' . DS . 'get.ctp', $this->_viewName);
  265. $this->assertTemplate('get');
  266. $this->assertResponseContains('cellcontent');
  267. }
  268. /**
  269. * Test array URLs
  270. *
  271. * @return void
  272. */
  273. public function testArrayUrls()
  274. {
  275. $this->post(['controller' => 'Posts', 'action' => 'index']);
  276. $this->assertEquals('value', $this->viewVariable('test'));
  277. }
  278. /**
  279. * Test flash and cookie assertions
  280. *
  281. * @return void
  282. */
  283. public function testFlashSessionAndCookieAsserts()
  284. {
  285. $this->post('/posts/index');
  286. $this->assertSession('An error message', 'Flash.flash.0.message');
  287. $this->assertCookie(1, 'remember_me');
  288. $this->assertCookieNotSet('user_id');
  289. }
  290. /**
  291. * Tests the failure message for assertCookieNotSet
  292. *
  293. * @expectedException PHPUnit_Framework_AssertionFailedError
  294. * @expectedExceptionMessage Cookie 'remember_me' has been set
  295. * @return void
  296. */
  297. public function testCookieNotSetFailure()
  298. {
  299. $this->post('/posts/index');
  300. $this->assertCookieNotSet('remember_me');
  301. }
  302. /**
  303. * Tests the failure message for assertCookieNotSet when no
  304. * response whas generated
  305. *
  306. * @expectedException PHPUnit_Framework_AssertionFailedError
  307. * @expectedExceptionMessage No response set, cannot assert cookies.
  308. * @return void
  309. */
  310. public function testCookieNotSetFailureNoResponse()
  311. {
  312. $this->assertCookieNotSet('remember_me');
  313. }
  314. /**
  315. * Test error handling and error page rendering.
  316. *
  317. * @return void
  318. */
  319. public function testPostAndErrorHandling()
  320. {
  321. $this->post('/request_action/error_method');
  322. $this->assertResponseNotEmpty();
  323. $this->assertResponseContains('Not there or here');
  324. $this->assertResponseContains('<!DOCTYPE html>');
  325. }
  326. /**
  327. * Test posting to a secured form action.
  328. *
  329. * @return void
  330. */
  331. public function testPostSecuredForm()
  332. {
  333. $this->enableSecurityToken();
  334. $data = [
  335. 'title' => 'Some title',
  336. 'body' => 'Some text'
  337. ];
  338. $this->post('/posts/securePost', $data);
  339. $this->assertResponseOk();
  340. $this->assertResponseContains('Request was accepted');
  341. }
  342. /**
  343. * Test posting to a secured form action with nested data.
  344. *
  345. * @return void
  346. */
  347. public function testPostSecuredFormNestedData()
  348. {
  349. $this->enableSecurityToken();
  350. $data = [
  351. 'title' => 'New post',
  352. 'comments' => [
  353. ['comment' => 'A new comment']
  354. ],
  355. 'tags' => ['_ids' => [1, 2, 3, 4]]
  356. ];
  357. $this->post('/posts/securePost', $data);
  358. $this->assertResponseOk();
  359. $this->assertResponseContains('Request was accepted');
  360. }
  361. /**
  362. * Test posting to a secured form action action.
  363. *
  364. * @return void
  365. */
  366. public function testPostSecuredFormFailure()
  367. {
  368. $data = [
  369. 'title' => 'Some title',
  370. 'body' => 'Some text'
  371. ];
  372. $this->post('/posts/securePost', $data);
  373. $this->assertResponseError();
  374. }
  375. /**
  376. * Test that exceptions being thrown are handled correctly.
  377. *
  378. * @return void
  379. */
  380. public function testWithExpectedException()
  381. {
  382. $this->get('/tests_apps/throw_exception');
  383. $this->assertResponseCode(500);
  384. }
  385. /**
  386. * Test that exceptions being thrown are handled correctly.
  387. *
  388. * @expectedException PHPUnit_Framework_AssertionFailedError
  389. * @return void
  390. */
  391. public function testWithUnexpectedException()
  392. {
  393. $this->get('/tests_apps/throw_exception');
  394. $this->assertResponseCode(501);
  395. }
  396. /**
  397. * Test redirecting and integration tests.
  398. *
  399. * @return void
  400. */
  401. public function testRedirect()
  402. {
  403. $this->post('/tests_apps/redirect_to');
  404. $this->assertResponseSuccess();
  405. $this->assertResponseCode(302);
  406. }
  407. /**
  408. * Test redirecting and integration tests.
  409. *
  410. * @return void
  411. */
  412. public function testRedirectPermanent()
  413. {
  414. $this->post('/tests_apps/redirect_to_permanent');
  415. $this->assertResponseSuccess();
  416. $this->assertResponseCode(301);
  417. }
  418. /**
  419. * Test the responseOk status assertion
  420. *
  421. * @return void
  422. */
  423. public function testAssertResponseStatusCodes()
  424. {
  425. $this->_response = new Response();
  426. $this->_response->statusCode(200);
  427. $this->assertResponseOk();
  428. $this->_response->statusCode(201);
  429. $this->assertResponseOk();
  430. $this->_response->statusCode(204);
  431. $this->assertResponseOk();
  432. $this->_response->statusCode(202);
  433. $this->assertResponseSuccess();
  434. $this->_response->statusCode(302);
  435. $this->assertResponseSuccess();
  436. $this->_response->statusCode(400);
  437. $this->assertResponseError();
  438. $this->_response->statusCode(417);
  439. $this->assertResponseError();
  440. $this->_response->statusCode(500);
  441. $this->assertResponseFailure();
  442. $this->_response->statusCode(505);
  443. $this->assertResponseFailure();
  444. $this->_response->statusCode(301);
  445. $this->assertResponseCode(301);
  446. }
  447. /**
  448. * Test the location header assertion.
  449. *
  450. * @return void
  451. */
  452. public function testAssertRedirect()
  453. {
  454. $this->_response = new Response();
  455. $this->_response->header('Location', 'http://localhost/tasks/index');
  456. $this->assertRedirect();
  457. $this->assertRedirect('/tasks/index');
  458. $this->assertRedirect(['controller' => 'Tasks', 'action' => 'index']);
  459. $this->assertResponseEmpty();
  460. }
  461. /**
  462. * Test the location header assertion.
  463. *
  464. * @return void
  465. */
  466. public function testAssertNoRedirect()
  467. {
  468. $this->_response = new Response();
  469. $this->assertNoRedirect();
  470. }
  471. /**
  472. * Test the location header assertion.
  473. *
  474. * @return void
  475. */
  476. public function testAssertNoRedirectFail()
  477. {
  478. $test = new AssertIntegrationTestCase('testBadAssertNoRedirect');
  479. $result = $test->run();
  480. ob_start();
  481. $this->assertFalse($result->wasSuccessful());
  482. $this->assertEquals(1, $result->failureCount());
  483. }
  484. /**
  485. * Test the location header assertion string contains
  486. *
  487. * @return void
  488. */
  489. public function testAssertRedirectContains()
  490. {
  491. $this->_response = new Response();
  492. $this->_response->header('Location', 'http://localhost/tasks/index');
  493. $this->assertRedirectContains('/tasks/index');
  494. }
  495. /**
  496. * Test the header assertion.
  497. *
  498. * @return void
  499. */
  500. public function testAssertHeader()
  501. {
  502. $this->_response = new Response();
  503. $this->_response->header('Etag', 'abc123');
  504. $this->assertHeader('Etag', 'abc123');
  505. }
  506. /**
  507. * Test the header contains assertion.
  508. *
  509. * @return void
  510. */
  511. public function testAssertHeaderContains()
  512. {
  513. $this->_response = new Response();
  514. $this->_response->header('Etag', 'abc123');
  515. $this->assertHeaderContains('Etag', 'abc');
  516. }
  517. /**
  518. * Test the content type assertion.
  519. *
  520. * @return void
  521. */
  522. public function testAssertContentType()
  523. {
  524. $this->_response = new Response();
  525. $this->_response->type('json');
  526. $this->assertContentType('json');
  527. $this->assertContentType('application/json');
  528. }
  529. /**
  530. * Test that type() in an action sets the content-type header.
  531. *
  532. * @return void
  533. */
  534. public function testContentTypeInAction()
  535. {
  536. $this->get('/tests_apps/set_type');
  537. $this->assertHeader('Content-Type', 'application/json; charset=UTF-8');
  538. $this->assertContentType('json');
  539. $this->assertContentType('application/json');
  540. }
  541. /**
  542. * Test the content assertion.
  543. *
  544. * @return void
  545. */
  546. public function testAssertResponseContains()
  547. {
  548. $this->_response = new Response();
  549. $this->_response->body('Some content');
  550. $this->assertResponseContains('content');
  551. }
  552. /**
  553. * Test the negated content assertion.
  554. *
  555. * @return void
  556. */
  557. public function testAssertResponseNotContains()
  558. {
  559. $this->_response = new Response();
  560. $this->_response->body('Some content');
  561. $this->assertResponseNotContains('contents');
  562. }
  563. /**
  564. * Test that works in tandem with testEventManagerReset2 to
  565. * test the EventManager reset.
  566. *
  567. * The return value is passed to testEventManagerReset2 as
  568. * an arguments.
  569. *
  570. * @return \Cake\Event\EventManager
  571. */
  572. public function testEventManagerReset1()
  573. {
  574. return EventManager::instance();
  575. }
  576. /**
  577. * Test if the EventManager is reset between tests.
  578. *
  579. * @depends testEventManagerReset1
  580. * @return void
  581. */
  582. public function testEventManagerReset2($prevEventManager)
  583. {
  584. $this->assertNotSame($prevEventManager, EventManager::instance());
  585. }
  586. /**
  587. * Test sending file in requests.
  588. *
  589. * @return void
  590. */
  591. public function testSendFile()
  592. {
  593. $this->get('/posts/file');
  594. $this->assertFileResponse(TEST_APP . 'TestApp' . DS . 'Controller' . DS . 'PostsController.php');
  595. }
  596. /**
  597. * Test that assertFile requires a response
  598. *
  599. * @expectedException PHPUnit_Framework_AssertionFailedError
  600. * @expectedExceptionMessage No response set, cannot assert file
  601. * @return void
  602. */
  603. public function testAssertFileNoReponse()
  604. {
  605. $this->assertFileResponse('foo');
  606. }
  607. /**
  608. * Test that assertFile requires a file
  609. *
  610. * @expectedException PHPUnit_Framework_AssertionFailedError
  611. * @expectedExceptionMessage No file was sent in this response
  612. * @return void
  613. */
  614. public function testAssertFileNoFile()
  615. {
  616. $this->get('/posts/get');
  617. $this->assertFileResponse('foo');
  618. }
  619. }