IntegrationTestTraitTest.php 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\TestSuite;
  17. use Cake\Controller\Controller;
  18. use Cake\Core\Configure;
  19. use Cake\Event\EventManager;
  20. use Cake\Http\Cookie\Cookie;
  21. use Cake\Http\Middleware\EncryptedCookieMiddleware;
  22. use Cake\Http\Response;
  23. use Cake\Http\Session;
  24. use Cake\Routing\Route\InflectedRoute;
  25. use Cake\Routing\Router;
  26. use Cake\Test\Fixture\AssertIntegrationTestCase;
  27. use Cake\TestSuite\IntegrationTestTrait;
  28. use Cake\TestSuite\TestCase;
  29. use Cake\Utility\Security;
  30. use PHPUnit\Framework\AssertionFailedError;
  31. use Zend\Diactoros\UploadedFile;
  32. /**
  33. * Self test of the IntegrationTestTrait
  34. */
  35. class IntegrationTestTraitTest extends TestCase
  36. {
  37. use IntegrationTestTrait;
  38. /**
  39. * stub encryption key.
  40. *
  41. * @var string
  42. */
  43. public $key = 'abcdabcdabcdabcdabcdabcdabcdabcdabcd';
  44. /**
  45. * Setup method
  46. *
  47. * @return void
  48. */
  49. public function setUp(): void
  50. {
  51. parent::setUp();
  52. static::setAppNamespace();
  53. Router::reload();
  54. Router::extensions(['json']);
  55. Router::scope('/', function ($routes) {
  56. $routes->registerMiddleware('cookie', new EncryptedCookieMiddleware(['secrets'], $this->key));
  57. $routes->applyMiddleware('cookie');
  58. $routes->setRouteClass(InflectedRoute::class);
  59. $routes->get('/get/:controller/:action', []);
  60. $routes->head('/head/:controller/:action', []);
  61. $routes->options('/options/:controller/:action', []);
  62. $routes->connect('/:controller/:action/*', []);
  63. });
  64. $this->configApplication(Configure::read('App.namespace') . '\Application', null);
  65. }
  66. /**
  67. * Tests that all data that used by the request is cast to strings
  68. *
  69. * @return void
  70. */
  71. public function testDataCastToString()
  72. {
  73. $data = [
  74. 'title' => 'Blog Post',
  75. 'status' => 1,
  76. 'published' => true,
  77. 'not_published' => false,
  78. 'comments' => [
  79. [
  80. 'body' => 'Comment',
  81. 'status' => 1,
  82. ],
  83. ],
  84. 'file' => [
  85. 'tmp_name' => __FILE__,
  86. 'size' => 42,
  87. 'error' => 0,
  88. 'type' => 'text/plain',
  89. 'name' => 'Uploaded file',
  90. ],
  91. 'pictures' => [
  92. 'name' => [
  93. ['file' => 'a-file.png'],
  94. ['file' => 'a-moose.png'],
  95. ],
  96. 'type' => [
  97. ['file' => 'image/png'],
  98. ['file' => 'image/jpg'],
  99. ],
  100. 'tmp_name' => [
  101. ['file' => __FILE__],
  102. ['file' => __FILE__],
  103. ],
  104. 'error' => [
  105. ['file' => 0],
  106. ['file' => 0],
  107. ],
  108. 'size' => [
  109. ['file' => 17188],
  110. ['file' => 2010],
  111. ],
  112. ],
  113. 'upload' => new UploadedFile(__FILE__, 42, 0),
  114. ];
  115. $request = $this->_buildRequest('/posts/add', 'POST', $data);
  116. $this->assertIsString($request['post']['status']);
  117. $this->assertIsString($request['post']['published']);
  118. $this->assertSame('0', $request['post']['not_published']);
  119. $this->assertIsString($request['post']['comments'][0]['status']);
  120. $this->assertIsInt($request['post']['file']['error']);
  121. $this->assertIsInt($request['post']['file']['size']);
  122. $this->assertIsInt($request['post']['pictures']['error'][0]['file']);
  123. $this->assertIsInt($request['post']['pictures']['error'][1]['file']);
  124. $this->assertIsInt($request['post']['pictures']['size'][0]['file']);
  125. $this->assertIsInt($request['post']['pictures']['size'][1]['file']);
  126. $this->assertInstanceOf(UploadedFile::class, $request['post']['upload']);
  127. }
  128. /**
  129. * Test building a request.
  130. *
  131. * @return void
  132. */
  133. public function testRequestBuilding()
  134. {
  135. $this->configRequest([
  136. 'headers' => [
  137. 'X-CSRF-Token' => 'abc123',
  138. 'Content-Type' => 'application/json',
  139. 'Accept' => 'application/json',
  140. ],
  141. 'base' => '',
  142. 'webroot' => '/',
  143. 'environment' => [
  144. 'PHP_AUTH_USER' => 'foo',
  145. 'PHP_AUTH_PW' => 'bar',
  146. ],
  147. ]);
  148. $this->cookie('split_token', 'def345');
  149. $this->session(['User' => ['id' => '1', 'username' => 'mark']]);
  150. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  151. $this->assertSame('abc123', $request['environment']['HTTP_X_CSRF_TOKEN']);
  152. $this->assertSame('application/json', $request['environment']['CONTENT_TYPE']);
  153. $this->assertSame('/tasks/add', $request['url']);
  154. $this->assertArrayHasKey('split_token', $request['cookies']);
  155. $this->assertSame('def345', $request['cookies']['split_token']);
  156. $this->assertSame(['id' => '1', 'username' => 'mark'], $request['session']->read('User'));
  157. $this->assertSame('foo', $request['environment']['PHP_AUTH_USER']);
  158. $this->assertSame('bar', $request['environment']['PHP_AUTH_PW']);
  159. }
  160. /**
  161. * Test request building adds csrf tokens
  162. *
  163. * @return void
  164. */
  165. public function testRequestBuildingCsrfTokens()
  166. {
  167. $this->enableCsrfToken();
  168. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  169. $this->assertArrayHasKey('csrfToken', $request['cookies']);
  170. $this->assertArrayHasKey('_csrfToken', $request['post']);
  171. $this->assertSame($request['cookies']['csrfToken'], $request['post']['_csrfToken']);
  172. $this->cookie('csrfToken', '');
  173. $request = $this->_buildRequest('/tasks/add', 'POST', [
  174. '_csrfToken' => 'fale',
  175. 'title' => 'First post',
  176. ]);
  177. $this->assertSame('', $request['cookies']['csrfToken']);
  178. $this->assertSame('fale', $request['post']['_csrfToken']);
  179. }
  180. /**
  181. * Test multiple actions using CSRF tokens don't fail
  182. *
  183. * @return void
  184. */
  185. public function testEnableCsrfMultipleRequests()
  186. {
  187. $this->enableCsrfToken();
  188. $first = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  189. $second = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'Second post']);
  190. $this->assertSame(
  191. $first['cookies']['csrfToken'],
  192. $second['post']['_csrfToken'],
  193. 'Csrf token should match cookie'
  194. );
  195. $this->assertSame(
  196. $first['post']['_csrfToken'],
  197. $second['post']['_csrfToken'],
  198. 'Tokens should be consistent per test method'
  199. );
  200. }
  201. /**
  202. * Test pre-determined CSRF tokens.
  203. *
  204. * @return void
  205. */
  206. public function testEnableCsrfPredeterminedCookie()
  207. {
  208. $this->enableCsrfToken();
  209. $value = 'I am a teapot';
  210. $this->cookie('csrfToken', $value);
  211. $request = $this->_buildRequest('/tasks/add', 'POST', ['title' => 'First post']);
  212. $this->assertSame($value, $request['cookies']['csrfToken'], 'Csrf token should match cookie');
  213. $this->assertSame($value, $request['post']['_csrfToken'], 'Tokens should match');
  214. }
  215. /**
  216. * Test building a request, with query parameters
  217. *
  218. * @return void
  219. */
  220. public function testRequestBuildingQueryParameters()
  221. {
  222. $request = $this->_buildRequest('/tasks/view?archived=yes', 'GET', []);
  223. $this->assertSame('/tasks/view', $request['url']);
  224. $this->assertSame('archived=yes', $request['environment']['QUERY_STRING']);
  225. $this->assertSame('/tasks/view', $request['environment']['REQUEST_URI']);
  226. }
  227. /**
  228. * Test cookie encrypted
  229. *
  230. * @see CookieComponentControllerTest
  231. */
  232. public function testCookieEncrypted()
  233. {
  234. Security::setSalt($this->key);
  235. $this->cookieEncrypted('KeyOfCookie', 'Encrypted with aes by default');
  236. $request = $this->_buildRequest('/tasks/view', 'GET', []);
  237. $this->assertStringStartsWith('Q2FrZQ==.', $request['cookies']['KeyOfCookie']);
  238. }
  239. /**
  240. * Test sending get request and using default `test_app/config/routes.php`.
  241. *
  242. * @return void
  243. */
  244. public function testGetUsingApplicationWithPluginRoutes()
  245. {
  246. // first clean routes to have Router::$initailized === false
  247. Router::reload();
  248. $this->clearPlugins();
  249. $this->configApplication(Configure::read('App.namespace') . '\ApplicationWithPluginRoutes', null);
  250. $this->get('/test_plugin');
  251. $this->assertResponseOk();
  252. }
  253. /**
  254. * Test sending get request and using default `test_app/config/routes.php`.
  255. *
  256. * @return void
  257. */
  258. public function testGetUsingApplicationWithDefaultRoutes()
  259. {
  260. // first clean routes to have Router::$initialized === false
  261. Router::reload();
  262. $this->configApplication(Configure::read('App.namespace') . '\ApplicationWithDefaultRoutes', null);
  263. $this->get('/some_alias');
  264. $this->assertResponseOk();
  265. $this->assertSame('5', $this->_getBodyAsString());
  266. }
  267. public function testExceptionsInMiddlewareJsonView()
  268. {
  269. Router::reload();
  270. Router::connect('/json_response/api_get_data', [
  271. 'controller' => 'JsonResponse',
  272. 'action' => 'apiGetData',
  273. ]);
  274. $this->configApplication(Configure::read('App.namespace') . '\ApplicationWithExceptionsInMiddleware', null);
  275. $this->_request['headers'] = [ "Accept" => "application/json" ];
  276. $this->get('/json_response/api_get_data');
  277. $this->assertResponseCode(403);
  278. $this->assertHeader('Content-Type', 'application/json');
  279. $this->assertResponseContains('"message": "Sample Message"');
  280. $this->assertResponseContains('"code": 403');
  281. }
  282. /**
  283. * Test sending head requests.
  284. *
  285. * @return void
  286. */
  287. public function testHead()
  288. {
  289. $this->assertNull($this->_response);
  290. $this->head('/request_action/test_request_action');
  291. $this->assertNotEmpty($this->_response);
  292. $this->assertInstanceOf('Cake\Http\Response', $this->_response);
  293. $this->assertResponseSuccess();
  294. }
  295. /**
  296. * Test sending head requests.
  297. *
  298. * @return void
  299. */
  300. public function testHeadMethodRoute()
  301. {
  302. $this->head('/head/request_action/test_request_action');
  303. $this->assertResponseSuccess();
  304. }
  305. /**
  306. * Test sending options requests.
  307. *
  308. * @return void
  309. */
  310. public function testOptions()
  311. {
  312. $this->assertNull($this->_response);
  313. $this->options('/request_action/test_request_action');
  314. $this->assertNotEmpty($this->_response);
  315. $this->assertInstanceOf('Cake\Http\Response', $this->_response);
  316. $this->assertResponseSuccess();
  317. }
  318. /**
  319. * Test sending options requests.
  320. *
  321. * @return void
  322. */
  323. public function testOptionsMethodRoute()
  324. {
  325. $this->options('/options/request_action/test_request_action');
  326. $this->assertResponseSuccess();
  327. }
  328. /**
  329. * Test sending get requests sets the request method
  330. *
  331. * @return void
  332. */
  333. public function testGetSpecificRouteHttpServer()
  334. {
  335. $this->get('/get/request_action/test_request_action');
  336. $this->assertResponseOk();
  337. $this->assertSame('This is a test', (string)$this->_response->getBody());
  338. }
  339. /**
  340. * Test customizing the app class.
  341. *
  342. * @return void
  343. */
  344. public function testConfigApplication()
  345. {
  346. $this->expectException(\LogicException::class);
  347. $this->expectExceptionMessage('Cannot load `TestApp\MissingApp` for use in integration');
  348. $this->configApplication('TestApp\MissingApp', []);
  349. $this->get('/request_action/test_request_action');
  350. }
  351. /**
  352. * Test sending get requests with Http\Server
  353. *
  354. * @return void
  355. */
  356. public function testGetHttpServer()
  357. {
  358. $this->assertNull($this->_response);
  359. $this->get('/request_action/test_request_action');
  360. $this->assertNotEmpty($this->_response);
  361. $this->assertInstanceOf('Cake\Http\Response', $this->_response);
  362. $this->assertSame('This is a test', (string)$this->_response->getBody());
  363. $this->assertHeader('X-Middleware', 'true');
  364. }
  365. /**
  366. * Test that the PSR7 requests get query string data
  367. *
  368. * @return void
  369. */
  370. public function testGetQueryStringHttpServer()
  371. {
  372. $this->configRequest(['headers' => ['Content-Type' => 'text/plain']]);
  373. $this->get('/request_action/params_pass?q=query');
  374. $this->assertResponseOk();
  375. $this->assertResponseContains('"q":"query"');
  376. $this->assertResponseContains('"contentType":"text\/plain"');
  377. $this->assertHeader('X-Middleware', 'true');
  378. $request = $this->_controller->getRequest();
  379. $this->assertStringContainsString('/request_action/params_pass?q=query', $request->getRequestTarget());
  380. }
  381. /**
  382. * Test that the PSR7 requests get query string data
  383. *
  384. * @return void
  385. */
  386. public function testGetQueryStringSetsHere()
  387. {
  388. $this->configRequest(['headers' => ['Content-Type' => 'text/plain']]);
  389. $this->get('/request_action/params_pass?q=query');
  390. $this->assertResponseOk();
  391. $this->assertResponseContains('"q":"query"');
  392. $this->assertResponseContains('"contentType":"text\/plain"');
  393. $this->assertHeader('X-Middleware', 'true');
  394. $request = $this->_controller->getRequest();
  395. $this->assertStringContainsString('/request_action/params_pass?q=query', $request->getRequestTarget());
  396. $this->assertStringContainsString('/request_action/params_pass', $request->getAttribute('here'));
  397. }
  398. /**
  399. * Test that the PSR7 requests get cookies
  400. *
  401. * @return void
  402. */
  403. public function testGetCookiesHttpServer()
  404. {
  405. $this->configRequest(['cookies' => ['split_test' => 'abc']]);
  406. $this->get('/request_action/cookie_pass');
  407. $this->assertResponseOk();
  408. $this->assertResponseContains('"split_test":"abc"');
  409. $this->assertHeader('X-Middleware', 'true');
  410. }
  411. /**
  412. * Test that the PSR7 requests receive post data
  413. *
  414. * @return void
  415. */
  416. public function testPostDataHttpServer()
  417. {
  418. $this->post('/request_action/post_pass', ['title' => 'value']);
  419. $data = json_decode('' . $this->_response->getBody());
  420. $this->assertSame('value', $data->title);
  421. $this->assertHeader('X-Middleware', 'true');
  422. }
  423. /**
  424. * Test that the uploaded files are passed correctly to the request
  425. *
  426. * @return void
  427. */
  428. public function testUploadedFiles()
  429. {
  430. $this->configRequest([
  431. 'files' => [
  432. 'file' => [
  433. 'tmp_name' => __FILE__,
  434. 'size' => 42,
  435. 'error' => 0,
  436. 'type' => 'text/plain',
  437. 'name' => 'Uploaded file',
  438. ],
  439. 'pictures' => [
  440. 'name' => [
  441. ['file' => 'a-file.png'],
  442. ['file' => 'a-moose.png'],
  443. ],
  444. 'type' => [
  445. ['file' => 'image/png'],
  446. ['file' => 'image/jpg'],
  447. ],
  448. 'tmp_name' => [
  449. ['file' => __FILE__],
  450. ['file' => __FILE__],
  451. ],
  452. 'error' => [
  453. ['file' => 0],
  454. ['file' => 0],
  455. ],
  456. 'size' => [
  457. ['file' => 17188],
  458. ['file' => 2010],
  459. ],
  460. ],
  461. 'upload' => new UploadedFile(__FILE__, 42, 0),
  462. ],
  463. ]);
  464. $this->post('/request_action/uploaded_files');
  465. $this->assertHeader('X-Middleware', 'true');
  466. $data = json_decode((string)$this->_response->getBody(), true);
  467. $this->assertSame([
  468. 'file' => 'Uploaded file',
  469. 'pictures.0.file' => 'a-file.png',
  470. 'pictures.1.file' => 'a-moose.png',
  471. 'upload' => null,
  472. ], $data);
  473. }
  474. /**
  475. * Test that the PSR7 requests receive encoded data.
  476. *
  477. * @return void
  478. */
  479. public function testInputDataHttpServer()
  480. {
  481. $this->post('/request_action/input_test', '{"hello":"world"}');
  482. if ($this->_response->getBody()->isSeekable()) {
  483. $this->_response->getBody()->rewind();
  484. }
  485. $this->assertSame('world', $this->_response->getBody()->getContents());
  486. $this->assertHeader('X-Middleware', 'true');
  487. }
  488. /**
  489. * Test that the PSR7 requests receive encoded data.
  490. *
  491. * @return void
  492. */
  493. public function testInputDataSecurityToken()
  494. {
  495. $this->enableSecurityToken();
  496. $this->post('/request_action/input_test', '{"hello":"world"}');
  497. $this->assertSame('world', '' . $this->_response->getBody());
  498. $this->assertHeader('X-Middleware', 'true');
  499. }
  500. /**
  501. * Test that the PSR7 requests get cookies
  502. *
  503. * @return void
  504. */
  505. public function testSessionHttpServer()
  506. {
  507. $this->session(['foo' => 'session data']);
  508. $this->get('/request_action/session_test');
  509. $this->assertResponseOk();
  510. $this->assertResponseContains('session data');
  511. $this->assertHeader('X-Middleware', 'true');
  512. }
  513. /**
  514. * Test sending requests stores references to controller/view/layout.
  515. *
  516. * @return void
  517. */
  518. public function testRequestSetsProperties()
  519. {
  520. $this->post('/posts/index');
  521. $this->assertInstanceOf('Cake\Controller\Controller', $this->_controller);
  522. $this->assertNotEmpty($this->_viewName, 'View name not set');
  523. $this->assertStringContainsString('templates' . DS . 'Posts' . DS . 'index.php', $this->_viewName);
  524. $this->assertNotEmpty($this->_layoutName, 'Layout name not set');
  525. $this->assertStringContainsString('templates' . DS . 'layout' . DS . 'default.php', $this->_layoutName);
  526. $this->assertTemplate('index');
  527. $this->assertLayout('default');
  528. $this->assertSame('value', $this->viewVariable('test'));
  529. }
  530. /**
  531. * Test PSR7 requests store references to controller/view/layout
  532. *
  533. * @return void
  534. */
  535. public function testRequestSetsPropertiesHttpServer()
  536. {
  537. $this->post('/posts/index');
  538. $this->assertInstanceOf('Cake\Controller\Controller', $this->_controller);
  539. $this->assertNotEmpty($this->_viewName, 'View name not set');
  540. $this->assertStringContainsString('templates' . DS . 'Posts' . DS . 'index.php', $this->_viewName);
  541. $this->assertNotEmpty($this->_layoutName, 'Layout name not set');
  542. $this->assertStringContainsString('templates' . DS . 'layout' . DS . 'default.php', $this->_layoutName);
  543. $this->assertTemplate('index');
  544. $this->assertLayout('default');
  545. $this->assertSame('value', $this->viewVariable('test'));
  546. }
  547. /**
  548. * Tests URLs containing extensions.
  549. *
  550. * @return void
  551. */
  552. public function testRequestWithExt()
  553. {
  554. $this->get(['controller' => 'Posts', 'action' => 'ajax', '_ext' => 'json']);
  555. $this->assertResponseCode(200);
  556. }
  557. /**
  558. * Assert that the stored template doesn't change when cells are rendered.
  559. *
  560. * @return void
  561. */
  562. public function testAssertTemplateAfterCellRender()
  563. {
  564. $this->get('/posts/get');
  565. $this->assertStringContainsString('templates' . DS . 'Posts' . DS . 'get.php', $this->_viewName);
  566. $this->assertTemplate('get');
  567. $this->assertResponseContains('cellcontent');
  568. }
  569. /**
  570. * Test array URLs
  571. *
  572. * @return void
  573. */
  574. public function testArrayUrls()
  575. {
  576. $this->post(['controller' => 'Posts', 'action' => 'index', '_method' => 'POST']);
  577. $this->assertResponseOk();
  578. $this->assertSame('value', $this->viewVariable('test'));
  579. }
  580. /**
  581. * Test array URL with host
  582. *
  583. * @return void
  584. */
  585. public function testArrayUrlWithHost()
  586. {
  587. $this->get([
  588. 'controller' => 'Posts',
  589. 'action' => 'hostData',
  590. '_host' => 'app.example.org',
  591. '_ssl' => true,
  592. ]);
  593. $this->assertResponseOk();
  594. $this->assertResponseContains('"isSsl":true');
  595. $this->assertResponseContains('"host":"app.example.org"');
  596. }
  597. /**
  598. * Test array URLs with an empty router.
  599. *
  600. * @return void
  601. */
  602. public function testArrayUrlsEmptyRouter()
  603. {
  604. Router::reload();
  605. $this->assertEmpty(Router::getRouteCollection()->routes());
  606. $this->get(['controller' => 'Posts', 'action' => 'index']);
  607. $this->assertResponseOk();
  608. $this->assertSame('value', $this->viewVariable('test'));
  609. }
  610. /**
  611. * Test flash and cookie assertions
  612. *
  613. * @return void
  614. */
  615. public function testFlashSessionAndCookieAsserts()
  616. {
  617. $this->post('/posts/index');
  618. $this->assertSession('An error message', 'Flash.flash.0.message');
  619. $this->assertCookie(1, 'remember_me');
  620. $this->assertCookieNotSet('user_id');
  621. }
  622. /**
  623. * Test flash and cookie assertions
  624. *
  625. * @return void
  626. */
  627. public function testFlashSessionAndCookieAssertsHttpServer()
  628. {
  629. $this->post('/posts/index');
  630. $this->assertSession('An error message', 'Flash.flash.0.message');
  631. $this->assertCookieNotSet('user_id');
  632. $this->assertCookie(1, 'remember_me');
  633. }
  634. /**
  635. * Test flash assertions stored with enableRememberFlashMessages() after they
  636. * are rendered
  637. *
  638. * @return void
  639. */
  640. public function testFlashAssertionsAfterRender()
  641. {
  642. $this->enableRetainFlashMessages();
  643. $this->get('/posts/index/with_flash');
  644. $this->assertSession('An error message', 'Flash.flash.0.message');
  645. }
  646. /**
  647. * Test flash assertions stored with enableRememberFlashMessages() even if
  648. * no view is rendered
  649. *
  650. * @return void
  651. */
  652. public function testFlashAssertionsWithNoRender()
  653. {
  654. $this->enableRetainFlashMessages();
  655. $this->get('/posts/flashNoRender');
  656. $this->assertRedirect();
  657. $this->assertSession('An error message', 'Flash.flash.0.message');
  658. }
  659. /**
  660. * Tests assertCookieNotSet assertion
  661. *
  662. * @return void
  663. */
  664. public function testAssertCookieNotSet()
  665. {
  666. $this->cookie('test', 'value');
  667. $this->get('/cookie_component_test/remove_cookie/test');
  668. $this->assertCookieNotSet('test');
  669. }
  670. /**
  671. * Tests the failure message for assertCookieNotSet
  672. *
  673. * @return void
  674. */
  675. public function testCookieNotSetFailure()
  676. {
  677. $this->expectException(AssertionFailedError::class);
  678. $this->expectExceptionMessage('Failed asserting that \'remember_me\' cookie is not set');
  679. $this->post('/posts/index');
  680. $this->assertCookieNotSet('remember_me');
  681. }
  682. /**
  683. * Tests the failure message for assertCookieNotSet when no
  684. * response whas generated
  685. *
  686. * @return void
  687. */
  688. public function testCookieNotSetFailureNoResponse()
  689. {
  690. $this->expectException(AssertionFailedError::class);
  691. $this->expectExceptionMessage('No response set, cannot assert content.');
  692. $this->assertCookieNotSet('remember_me');
  693. }
  694. /**
  695. * Test error handling and error page rendering.
  696. *
  697. * @return void
  698. */
  699. public function testPostAndErrorHandling()
  700. {
  701. $this->post('/request_action/error_method');
  702. $this->assertResponseNotEmpty();
  703. $this->assertResponseContains('Not there or here');
  704. $this->assertResponseContains('<!DOCTYPE html>');
  705. }
  706. /**
  707. * Test posting to a secured form action.
  708. *
  709. * @return void
  710. */
  711. public function testPostSecuredForm()
  712. {
  713. $this->enableSecurityToken();
  714. $data = [
  715. 'title' => 'Some title',
  716. 'body' => 'Some text',
  717. ];
  718. $this->post('/posts/securePost', $data);
  719. $this->assertResponseOk();
  720. $this->assertResponseContains('Request was accepted');
  721. }
  722. /**
  723. * Test posting to a secured form action with nested data.
  724. *
  725. * @return void
  726. */
  727. public function testPostSecuredFormNestedData()
  728. {
  729. $this->enableSecurityToken();
  730. $data = [
  731. 'title' => 'New post',
  732. 'comments' => [
  733. ['comment' => 'A new comment'],
  734. ],
  735. 'tags' => ['_ids' => [1, 2, 3, 4]],
  736. ];
  737. $this->post('/posts/securePost', $data);
  738. $this->assertResponseOk();
  739. $this->assertResponseContains('Request was accepted');
  740. }
  741. /**
  742. * Test posting to a secured form action with unlocked fields
  743. *
  744. * @return void
  745. */
  746. public function testPostSecuredFormUnlockedFieldsFails()
  747. {
  748. $this->enableSecurityToken();
  749. $data = [
  750. 'title' => 'New post',
  751. 'comments' => [
  752. ['comment' => 'A new comment'],
  753. ],
  754. 'tags' => ['_ids' => [1, 2, 3, 4]],
  755. 'some_unlocked_field' => 'Unlocked data',
  756. ];
  757. $this->post('/posts/securePost', $data);
  758. $this->assertResponseCode(400);
  759. $this->assertResponseContains('Invalid security debug token.');
  760. }
  761. /**
  762. * Test posting to a secured form action with unlocked fields
  763. *
  764. * @return void
  765. */
  766. public function testPostSecuredFormUnlockedFieldsWithSet()
  767. {
  768. $this->enableSecurityToken();
  769. $data = [
  770. 'title' => 'New post',
  771. 'comments' => [
  772. ['comment' => 'A new comment'],
  773. ],
  774. 'tags' => ['_ids' => [1, 2, 3, 4]],
  775. 'some_unlocked_field' => 'Unlocked data',
  776. ];
  777. $this->setUnlockedFields(['some_unlocked_field']);
  778. $this->post('/posts/securePost', $data);
  779. $this->assertResponseOk();
  780. $this->assertResponseContains('Request was accepted');
  781. }
  782. /**
  783. * Test posting to a secured form action.
  784. *
  785. * @return void
  786. */
  787. public function testPostSecuredFormWithQuery()
  788. {
  789. $this->enableSecurityToken();
  790. $data = [
  791. 'title' => 'Some title',
  792. 'body' => 'Some text',
  793. ];
  794. $this->post('/posts/securePost?foo=bar', $data);
  795. $this->assertResponseOk();
  796. $this->assertResponseContains('Request was accepted');
  797. }
  798. /**
  799. * Test posting to a secured form action with a query that has a part that
  800. * will be encoded by the security component
  801. *
  802. * @return void
  803. */
  804. public function testPostSecuredFormWithUnencodedQuery()
  805. {
  806. $this->enableSecurityToken();
  807. $data = [
  808. 'title' => 'Some title',
  809. 'body' => 'Some text',
  810. ];
  811. $this->post('/posts/securePost?foo=/', $data);
  812. $this->assertResponseOk();
  813. $this->assertResponseContains('Request was accepted');
  814. }
  815. /**
  816. * Test posting to a secured form action action.
  817. *
  818. * @return void
  819. */
  820. public function testPostSecuredFormFailure()
  821. {
  822. $data = [
  823. 'title' => 'Some title',
  824. 'body' => 'Some text',
  825. ];
  826. $this->post('/posts/securePost', $data);
  827. $this->assertResponseError();
  828. }
  829. /**
  830. * Test that exceptions being thrown are handled correctly.
  831. *
  832. * @return void
  833. */
  834. public function testWithExpectedException()
  835. {
  836. $this->get('/tests_apps/throw_exception');
  837. $this->assertResponseCode(500);
  838. }
  839. /**
  840. * Test that exceptions being thrown are handled correctly by the psr7 stack.
  841. *
  842. * @return void
  843. */
  844. public function testWithExpectedExceptionHttpServer()
  845. {
  846. $this->get('/tests_apps/throw_exception');
  847. $this->assertResponseCode(500);
  848. }
  849. /**
  850. * Test that exceptions being thrown are handled correctly.
  851. *
  852. * @return void
  853. */
  854. public function testWithUnexpectedException()
  855. {
  856. $this->expectException(AssertionFailedError::class);
  857. $this->get('/tests_apps/throw_exception');
  858. $this->assertResponseCode(501);
  859. }
  860. /**
  861. * Test redirecting and integration tests.
  862. *
  863. * @return void
  864. */
  865. public function testRedirect()
  866. {
  867. $this->post('/tests_apps/redirect_to');
  868. $this->assertResponseSuccess();
  869. $this->assertResponseCode(302);
  870. }
  871. /**
  872. * Test redirecting and psr7 stack
  873. *
  874. * @return void
  875. */
  876. public function testRedirectHttpServer()
  877. {
  878. $this->post('/tests_apps/redirect_to');
  879. $this->assertResponseCode(302);
  880. $this->assertHeader('X-Middleware', 'true');
  881. }
  882. /**
  883. * Test redirecting and integration tests.
  884. *
  885. * @return void
  886. */
  887. public function testRedirectPermanent()
  888. {
  889. $this->post('/tests_apps/redirect_to_permanent');
  890. $this->assertResponseSuccess();
  891. $this->assertResponseCode(301);
  892. }
  893. /**
  894. * Test the responseOk status assertion
  895. *
  896. * @return void
  897. */
  898. public function testAssertResponseStatusCodes()
  899. {
  900. $this->_response = new Response();
  901. $this->_response = $this->_response->withStatus(200);
  902. $this->assertResponseOk();
  903. $this->_response = $this->_response->withStatus(201);
  904. $this->assertResponseOk();
  905. $this->_response = $this->_response->withStatus(204);
  906. $this->assertResponseOk();
  907. $this->_response = $this->_response->withStatus(202);
  908. $this->assertResponseSuccess();
  909. $this->_response = $this->_response->withStatus(302);
  910. $this->assertResponseSuccess();
  911. $this->_response = $this->_response->withStatus(400);
  912. $this->assertResponseError();
  913. $this->_response = $this->_response->withStatus(417);
  914. $this->assertResponseError();
  915. $this->_response = $this->_response->withStatus(500);
  916. $this->assertResponseFailure();
  917. $this->_response = $this->_response->withStatus(505);
  918. $this->assertResponseFailure();
  919. $this->_response = $this->_response->withStatus(301);
  920. $this->assertResponseCode(301);
  921. }
  922. /**
  923. * Test the location header assertion.
  924. *
  925. * @return void
  926. */
  927. public function testAssertRedirect()
  928. {
  929. $this->_response = new Response();
  930. $this->_response = $this->_response->withHeader('Location', 'http://localhost/get/tasks/index');
  931. $this->assertRedirect();
  932. $this->assertRedirect('/get/tasks/index');
  933. $this->assertRedirect(['controller' => 'Tasks', 'action' => 'index']);
  934. $this->assertResponseEmpty();
  935. }
  936. /**
  937. * Test the location header assertion.
  938. *
  939. * @return void
  940. */
  941. public function testAssertRedirectEquals()
  942. {
  943. $this->_response = new Response();
  944. $this->_response = $this->_response->withHeader('Location', '/get/tasks/index');
  945. $this->assertRedirect();
  946. $this->assertRedirectEquals('/get/tasks/index');
  947. $this->assertRedirectEquals(['controller' => 'Tasks', 'action' => 'index']);
  948. $this->assertResponseEmpty();
  949. }
  950. /**
  951. * Test the location header assertion string not contains
  952. *
  953. * @return void
  954. */
  955. public function testAssertRedirectNotContains()
  956. {
  957. $this->_response = new Response();
  958. $this->_response = $this->_response->withHeader('Location', 'http://localhost/tasks/index');
  959. $this->assertRedirectNotContains('test');
  960. }
  961. /**
  962. * Test the location header assertion.
  963. *
  964. * @return void
  965. */
  966. public function testAssertNoRedirect()
  967. {
  968. $this->_response = new Response();
  969. $this->assertNoRedirect();
  970. }
  971. /**
  972. * Test the location header assertion.
  973. *
  974. * @return void
  975. */
  976. public function testAssertNoRedirectFail()
  977. {
  978. $test = new AssertIntegrationTestCase('testBadAssertNoRedirect');
  979. $result = $test->run();
  980. $this->assertFalse($result->wasSuccessful());
  981. $this->assertSame(1, $result->failureCount());
  982. }
  983. /**
  984. * Test the location header assertion string contains
  985. *
  986. * @return void
  987. */
  988. public function testAssertRedirectContains()
  989. {
  990. $this->_response = new Response();
  991. $this->_response = $this->_response->withHeader('Location', 'http://localhost/tasks/index');
  992. $this->assertRedirectContains('/tasks/index');
  993. }
  994. /**
  995. * Test the header assertion.
  996. *
  997. * @return void
  998. */
  999. public function testAssertHeader()
  1000. {
  1001. $this->_response = new Response();
  1002. $this->_response = $this->_response->withHeader('Etag', 'abc123');
  1003. $this->assertHeader('Etag', 'abc123');
  1004. }
  1005. /**
  1006. * Test the header contains assertion.
  1007. *
  1008. * @return void
  1009. */
  1010. public function testAssertHeaderContains()
  1011. {
  1012. $this->_response = new Response();
  1013. $this->_response = $this->_response->withHeader('Etag', 'abc123');
  1014. $this->assertHeaderContains('Etag', 'abc');
  1015. }
  1016. /**
  1017. * Test the header not contains assertion.
  1018. *
  1019. * @return void
  1020. */
  1021. public function testAssertHeaderNotContains()
  1022. {
  1023. $this->_response = new Response();
  1024. $this->_response = $this->_response->withHeader('Etag', 'abc123');
  1025. $this->assertHeaderNotContains('Etag', 'xyz');
  1026. }
  1027. /**
  1028. * Test the content type assertion.
  1029. *
  1030. * @return void
  1031. */
  1032. public function testAssertContentType()
  1033. {
  1034. $this->_response = new Response();
  1035. $this->_response = $this->_response->withType('json');
  1036. $this->assertContentType('json');
  1037. $this->assertContentType('application/json');
  1038. }
  1039. /**
  1040. * Test that type() in an action sets the content-type header.
  1041. *
  1042. * @return void
  1043. */
  1044. public function testContentTypeInAction()
  1045. {
  1046. $this->get('/tests_apps/set_type');
  1047. $this->assertHeader('Content-Type', 'application/json');
  1048. $this->assertContentType('json');
  1049. $this->assertContentType('application/json');
  1050. }
  1051. /**
  1052. * Test the content assertion.
  1053. *
  1054. * @return void
  1055. */
  1056. public function testAssertResponseEquals()
  1057. {
  1058. $this->_response = new Response();
  1059. $this->_response = $this->_response->withStringBody('Some content');
  1060. $this->assertResponseEquals('Some content');
  1061. }
  1062. /**
  1063. * Test the negated content assertion.
  1064. *
  1065. * @return void
  1066. */
  1067. public function testAssertResponseNotEquals()
  1068. {
  1069. $this->_response = new Response();
  1070. $this->_response = $this->_response->withStringBody('Some content');
  1071. $this->assertResponseNotEquals('Some Content');
  1072. }
  1073. /**
  1074. * Test the content assertion.
  1075. *
  1076. * @return void
  1077. */
  1078. public function testAssertResponseContains()
  1079. {
  1080. $this->_response = new Response();
  1081. $this->_response = $this->_response->withStringBody('Some content');
  1082. $this->assertResponseContains('content');
  1083. }
  1084. /**
  1085. * Test the content assertion with no case sensitivity.
  1086. *
  1087. * @return void
  1088. */
  1089. public function testAssertResponseContainsWithIgnoreCaseFlag()
  1090. {
  1091. $this->_response = new Response();
  1092. $this->_response = $this->_response->withStringBody('Some content');
  1093. $this->assertResponseContains('some', 'Failed asserting that the body contains given content', true);
  1094. }
  1095. /**
  1096. * Test the negated content assertion.
  1097. *
  1098. * @return void
  1099. */
  1100. public function testAssertResponseNotContains()
  1101. {
  1102. $this->_response = new Response();
  1103. $this->_response = $this->_response->withStringBody('Some content');
  1104. $this->assertResponseNotContains('contents');
  1105. }
  1106. /**
  1107. * Test the content regexp assertion.
  1108. *
  1109. * @return void
  1110. */
  1111. public function testAssertResponseRegExp()
  1112. {
  1113. $this->_response = new Response();
  1114. $this->_response = $this->_response->withStringBody('Some content');
  1115. $this->assertResponseRegExp('/cont/');
  1116. }
  1117. /**
  1118. * Test the content regexp assertion failing
  1119. *
  1120. * @return void
  1121. */
  1122. public function testAssertResponseRegExpNoResponse()
  1123. {
  1124. $this->expectException(AssertionFailedError::class);
  1125. $this->expectExceptionMessage('No response set');
  1126. $this->assertResponseRegExp('/cont/');
  1127. }
  1128. /**
  1129. * Test the negated content regexp assertion.
  1130. *
  1131. * @return void
  1132. */
  1133. public function testAssertResponseNotRegExp()
  1134. {
  1135. $this->_response = new Response();
  1136. $this->_response = $this->_response->withStringBody('Some content');
  1137. $this->assertResponseNotRegExp('/cant/');
  1138. }
  1139. /**
  1140. * Test negated content regexp assertion failing
  1141. *
  1142. * @return void
  1143. */
  1144. public function testAssertResponseNotRegExpNoResponse()
  1145. {
  1146. $this->expectException(AssertionFailedError::class);
  1147. $this->expectExceptionMessage('No response set');
  1148. $this->assertResponseNotRegExp('/cont/');
  1149. }
  1150. /**
  1151. * Test that works in tandem with testEventManagerReset2 to
  1152. * test the EventManager reset.
  1153. *
  1154. * The return value is passed to testEventManagerReset2 as
  1155. * an arguments.
  1156. *
  1157. * @return \Cake\Event\EventManager
  1158. */
  1159. public function testEventManagerReset1()
  1160. {
  1161. $eventManager = EventManager::instance();
  1162. $this->assertInstanceOf('Cake\Event\EventManager', $eventManager);
  1163. return $eventManager;
  1164. }
  1165. /**
  1166. * Test if the EventManager is reset between tests.
  1167. *
  1168. * @depends testEventManagerReset1
  1169. * @return void
  1170. */
  1171. public function testEventManagerReset2($prevEventManager)
  1172. {
  1173. $this->assertInstanceOf('Cake\Event\EventManager', $prevEventManager);
  1174. $this->assertNotSame($prevEventManager, EventManager::instance());
  1175. }
  1176. /**
  1177. * Test sending file in requests.
  1178. *
  1179. * @return void
  1180. */
  1181. public function testSendFile()
  1182. {
  1183. $this->get('/posts/file');
  1184. $this->assertFileResponse(TEST_APP . 'TestApp' . DS . 'Controller' . DS . 'PostsController.php');
  1185. }
  1186. /**
  1187. * Test sending file with psr7 stack
  1188. *
  1189. * @return void
  1190. */
  1191. public function testSendFileHttpServer()
  1192. {
  1193. $this->get('/posts/file');
  1194. $this->assertFileResponse(TEST_APP . 'TestApp' . DS . 'Controller' . DS . 'PostsController.php');
  1195. }
  1196. /**
  1197. * Test that assertFile requires a response
  1198. *
  1199. * @return void
  1200. */
  1201. public function testAssertFileNoResponse()
  1202. {
  1203. $this->expectException(AssertionFailedError::class);
  1204. $this->expectExceptionMessage('No response set, cannot assert content');
  1205. $this->assertFileResponse('foo');
  1206. }
  1207. /**
  1208. * Test that assertFile requires a file
  1209. *
  1210. * @return void
  1211. */
  1212. public function testAssertFileNoFile()
  1213. {
  1214. $this->expectException(AssertionFailedError::class);
  1215. $this->expectExceptionMessage('Failed asserting that file was sent.');
  1216. $this->get('/posts/get');
  1217. $this->assertFileResponse('foo');
  1218. }
  1219. /**
  1220. * Test disabling the error handler middleware.
  1221. *
  1222. * @return void
  1223. */
  1224. public function testDisableErrorHandlerMiddleware()
  1225. {
  1226. $this->expectException(\Cake\Routing\Exception\MissingRouteException::class);
  1227. $this->expectExceptionMessage('A route matching "/foo" could not be found.');
  1228. $this->disableErrorHandlerMiddleware();
  1229. $this->get('/foo');
  1230. }
  1231. /**
  1232. * tests getting a secure action while passing a query string
  1233. *
  1234. * @return void
  1235. * @dataProvider methodsProvider
  1236. */
  1237. public function testSecureWithQueryString($method)
  1238. {
  1239. $this->enableSecurityToken();
  1240. $this->{$method}('/posts/securePost/?ids[]=1&ids[]=2');
  1241. $this->assertResponseOk();
  1242. }
  1243. /**
  1244. * Tests flash assertions
  1245. *
  1246. * @return void
  1247. * @throws \PHPUnit\Exception
  1248. */
  1249. public function testAssertFlashMessage()
  1250. {
  1251. $this->get('/posts/stacked_flash');
  1252. $this->assertFlashElement('flash/error');
  1253. $this->assertFlashElement('flash/success', 'custom');
  1254. $this->assertFlashMessage('Error 1');
  1255. $this->assertFlashMessageAt(0, 'Error 1');
  1256. $this->assertFlashElementAt(0, 'flash/error');
  1257. $this->assertFlashMessage('Error 2');
  1258. $this->assertFlashMessageAt(1, 'Error 2');
  1259. $this->assertFlashElementAt(1, 'flash/error');
  1260. $this->assertFlashMessage('Success 1', 'custom');
  1261. $this->assertFlashMessageAt(0, 'Success 1', 'custom');
  1262. $this->assertFlashElementAt(0, 'flash/success', 'custom');
  1263. $this->assertFlashMessage('Success 2', 'custom');
  1264. $this->assertFlashMessageAt(1, 'Success 2', 'custom');
  1265. $this->assertFlashElementAt(1, 'flash/success', 'custom');
  1266. }
  1267. /**
  1268. * Tests asserting flash messages without first sending a request
  1269. *
  1270. * @return void
  1271. */
  1272. public function testAssertFlashMessageWithoutSendingRequest()
  1273. {
  1274. $this->expectException(AssertionFailedError::class);
  1275. $message = 'There is no stored session data. Perhaps you need to run a request?';
  1276. $message .= ' Additionally, ensure `$this->enableRetainFlashMessages()` has been enabled for the test.';
  1277. $this->expectExceptionMessage($message);
  1278. $this->assertFlashMessage('Will not work');
  1279. }
  1280. /**
  1281. * tests failure messages for assertions
  1282. *
  1283. * @param string $assertion Assertion method
  1284. * @param string $message Expected failure message
  1285. * @param string $url URL to test
  1286. * @param mixed ...$rest
  1287. * @dataProvider assertionFailureMessagesProvider
  1288. */
  1289. public function testAssertionFailureMessages($assertion, $message, $url, ...$rest)
  1290. {
  1291. $this->expectException(AssertionFailedError::class);
  1292. $this->expectExceptionMessage($message);
  1293. Security::setSalt($this->key);
  1294. $this->get($url);
  1295. call_user_func_array([$this, $assertion], $rest);
  1296. }
  1297. /**
  1298. * data provider for assertion failure messages
  1299. *
  1300. * @return array
  1301. */
  1302. public function assertionFailureMessagesProvider()
  1303. {
  1304. $templateDir = TEST_APP . 'templates' . DS;
  1305. return [
  1306. 'assertContentType' => ['assertContentType', 'Failed asserting that \'test\' is set as the Content-Type (`text/html`).', '/posts/index', 'test'],
  1307. 'assertContentTypeVerbose' => ['assertContentType', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'test'],
  1308. 'assertCookie' => ['assertCookie', 'Failed asserting that \'test\' is in cookie \'remember_me\'.', '/posts/index', 'test', 'remember_me'],
  1309. 'assertCookieVerbose' => ['assertCookie', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'test', 'remember_me'],
  1310. 'assertCookieEncrypted' => ['assertCookieEncrypted', 'Failed asserting that \'test\' is encrypted in cookie \'secrets\'.', '/posts/secretCookie', 'test', 'secrets'],
  1311. 'assertCookieEncryptedVerbose' => ['assertCookieEncrypted', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'test', 'NameOfCookie'],
  1312. 'assertCookieNotSet' => ['assertCookieNotSet', 'Failed asserting that \'remember_me\' cookie is not set.', '/posts/index', 'remember_me'],
  1313. 'assertFileResponse' => ['assertFileResponse', 'Failed asserting that \'test\' file was sent.', '/posts/file', 'test'],
  1314. 'assertFileResponseVerbose' => ['assertFileResponse', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'test'],
  1315. 'assertHeader' => ['assertHeader', 'Failed asserting that \'test\' equals content in header \'X-Cake\' (`custom header`).', '/posts/header', 'X-Cake', 'test'],
  1316. 'assertHeaderContains' => ['assertHeaderContains', 'Failed asserting that \'test\' is in header \'X-Cake\' (`custom header`)', '/posts/header', 'X-Cake', 'test'],
  1317. 'assertHeaderNotContains' => ['assertHeaderNotContains', 'Failed asserting that \'custom header\' is not in header \'X-Cake\' (`custom header`)', '/posts/header', 'X-Cake', 'custom header'],
  1318. 'assertHeaderContainsVerbose' => ['assertHeaderContains', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'X-Cake', 'test'],
  1319. 'assertHeaderNotContainsVerbose' => ['assertHeaderNotContains', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'X-Cake', 'test'],
  1320. 'assertLayout' => ['assertLayout', 'Failed asserting that \'custom_layout\' equals layout file `' . $templateDir . 'layout' . DS . 'default.php`.', '/posts/index', 'custom_layout'],
  1321. 'assertLayoutVerbose' => ['assertLayout', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'custom_layout'],
  1322. 'assertRedirect' => ['assertRedirect', 'Failed asserting that \'http://localhost/\' equals content in header \'Location\' (`http://localhost/posts`).', '/posts/flashNoRender', '/'],
  1323. 'assertRedirectVerbose' => ['assertRedirect', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', '/'],
  1324. 'assertRedirectContains' => ['assertRedirectContains', 'Failed asserting that \'/posts/somewhere-else\' is in header \'Location\' (`http://localhost/posts`).', '/posts/flashNoRender', '/posts/somewhere-else'],
  1325. 'assertRedirectContainsVerbose' => ['assertRedirectContains', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', '/posts/somewhere-else'],
  1326. 'assertRedirectNotContainsVerbose' => ['assertRedirectNotContains', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', '/posts/somewhere-else'],
  1327. 'assertResponseCode' => ['assertResponseCode', 'Failed asserting that `302` matches response status code `200`.', '/posts/index', 302],
  1328. 'assertResponseContains' => ['assertResponseContains', 'Failed asserting that \'test\' is in response body.', '/posts/index', 'test'],
  1329. 'assertResponseEmpty' => ['assertResponseEmpty', 'Failed asserting that response body is empty.', '/posts/index'],
  1330. 'assertResponseEquals' => ['assertResponseEquals', 'Failed asserting that \'test\' matches response body.', '/posts/index', 'test'],
  1331. 'assertResponseEqualsVerbose' => ['assertResponseEquals', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'test'],
  1332. 'assertResponseError' => ['assertResponseError', 'Failed asserting that 200 is between 400 and 429.', '/posts/index'],
  1333. 'assertResponseFailure' => ['assertResponseFailure', 'Failed asserting that 200 is between 500 and 505.', '/posts/index'],
  1334. 'assertResponseNotContains' => ['assertResponseNotContains', 'Failed asserting that \'index\' is not in response body.', '/posts/index', 'index'],
  1335. 'assertResponseNotEmpty' => ['assertResponseNotEmpty', 'Failed asserting that response body is not empty.', '/posts/empty_response'],
  1336. 'assertResponseNotEquals' => ['assertResponseNotEquals', 'Failed asserting that \'posts index\' does not match response body.', '/posts/index/error', 'posts index'],
  1337. 'assertResponseNotRegExp' => ['assertResponseNotRegExp', 'Failed asserting that `/index/` PCRE pattern not found in response body.', '/posts/index/error', '/index/'],
  1338. 'assertResponseNotRegExpVerbose' => ['assertResponseNotRegExp', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', '/index/'],
  1339. 'assertResponseOk' => ['assertResponseOk', 'Failed asserting that 404 is between 200 and 204.', '/posts/missing', '/index/'],
  1340. 'assertResponseRegExp' => ['assertResponseRegExp', 'Failed asserting that `/test/` PCRE pattern found in response body.', '/posts/index/error', '/test/'],
  1341. 'assertResponseSuccess' => ['assertResponseSuccess', 'Failed asserting that 404 is between 200 and 308.', '/posts/missing'],
  1342. 'assertResponseSuccessVerbose' => ['assertResponseSuccess', 'Possibly related to Cake\Controller\Exception\MissingActionException: "Action PostsController::missing() could not be found, or is not accessible."', '/posts/missing'],
  1343. 'assertSession' => ['assertSession', 'Failed asserting that \'test\' is in session path \'Missing.path\'.', '/posts/index', 'test', 'Missing.path'],
  1344. 'assertTemplate' => ['assertTemplate', 'Failed asserting that \'custom_template\' equals template file `' . $templateDir . 'Posts' . DS . 'index.php`.', '/posts/index', 'custom_template'],
  1345. 'assertTemplateVerbose' => ['assertTemplate', 'Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."', '/notfound', 'custom_template'],
  1346. 'assertFlashMessage' => ['assertFlashMessage', 'Failed asserting that \'missing\' is in \'flash\' message.', '/posts/index', 'missing'],
  1347. 'assertFlashMessageWithKey' => ['assertFlashMessage', 'Failed asserting that \'missing\' is in \'auth\' message.', '/posts/index', 'missing', 'auth'],
  1348. 'assertFlashMessageAt' => ['assertFlashMessageAt', 'Failed asserting that \'missing\' is in \'flash\' message #0.', '/posts/index', 0, 'missing'],
  1349. 'assertFlashMessageAtWithKey' => ['assertFlashMessageAt', 'Failed asserting that \'missing\' is in \'auth\' message #0.', '/posts/index', 0, 'missing', 'auth'],
  1350. 'assertFlashElement' => ['assertFlashElement', 'Failed asserting that \'missing\' is in \'flash\' element.', '/posts/index', 'missing'],
  1351. 'assertFlashElementWithKey' => ['assertFlashElement', 'Failed asserting that \'missing\' is in \'auth\' element.', '/posts/index', 'missing', 'auth'],
  1352. 'assertFlashElementAt' => ['assertFlashElementAt', 'Failed asserting that \'missing\' is in \'flash\' element #0.', '/posts/index', 0, 'missing'],
  1353. 'assertFlashElementAtWithKey' => ['assertFlashElementAt', 'Failed asserting that \'missing\' is in \'auth\' element #0.', '/posts/index', 0, 'missing', 'auth'],
  1354. ];
  1355. }
  1356. /**
  1357. * data provider for HTTP methods
  1358. *
  1359. * @return array
  1360. */
  1361. public function methodsProvider()
  1362. {
  1363. return [
  1364. 'GET' => ['get'],
  1365. 'POST' => ['post'],
  1366. 'PATCH' => ['patch'],
  1367. 'PUT' => ['put'],
  1368. 'DELETE' => ['delete'],
  1369. ];
  1370. }
  1371. /**
  1372. * Test assertCookieNotSet is creating a verbose message
  1373. *
  1374. * @return void
  1375. */
  1376. public function testAssertCookieNotSetVerbose()
  1377. {
  1378. $this->expectException(AssertionFailedError::class);
  1379. $this->expectExceptionMessage('Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."');
  1380. $this->get('/notfound');
  1381. $this->_response = $this->_response->withCookie(new Cookie('cookie', 'value'));
  1382. $this->assertCookieNotSet('cookie');
  1383. }
  1384. /**
  1385. * Test assertNoRedirect is creating a verbose message
  1386. *
  1387. * @return void
  1388. */
  1389. public function testAssertNoRedirectVerbose()
  1390. {
  1391. $this->expectException(AssertionFailedError::class);
  1392. $this->expectExceptionMessage('Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."');
  1393. $this->get('/notfound');
  1394. $this->_response = $this->_response->withHeader('Location', '/redirect');
  1395. $this->assertNoRedirect();
  1396. }
  1397. /**
  1398. * Test the header assertion generating a verbose message.
  1399. *
  1400. * @return void
  1401. */
  1402. public function testAssertHeaderVerbose()
  1403. {
  1404. $this->expectException(AssertionFailedError::class);
  1405. $this->expectExceptionMessage('Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."');
  1406. $this->get('/notfound');
  1407. $this->assertHeader('Etag', 'abc123');
  1408. }
  1409. /**
  1410. * Test the assertResponseNotEquals generates a verbose message.
  1411. *
  1412. * @return void
  1413. */
  1414. public function testAssertResponseNotEqualsVerbose()
  1415. {
  1416. $this->expectException(AssertionFailedError::class);
  1417. $this->expectExceptionMessage('Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."');
  1418. $this->get('/notfound');
  1419. $this->_response = $this->_response->withStringBody('body');
  1420. $this->assertResponseNotEquals('body');
  1421. }
  1422. /**
  1423. * Test the assertResponseRegExp generates a verbose message.
  1424. *
  1425. * @return void
  1426. */
  1427. public function testAssertResponseRegExpVerbose()
  1428. {
  1429. $this->expectException(AssertionFailedError::class);
  1430. $this->expectExceptionMessage('Possibly related to Cake\Routing\Exception\MissingRouteException: "A route matching "/notfound" could not be found."');
  1431. $this->get('/notfound');
  1432. $this->_response = $this->_response->withStringBody('body');
  1433. $this->assertResponseRegExp('/patternNotFound/');
  1434. }
  1435. /**
  1436. * Test the assertion generates a verbose message for session related checks.
  1437. *
  1438. * @dataProvider assertionFailureSessionVerboseProvider
  1439. * @return void
  1440. */
  1441. public function testAssertSessionRelatedVerboseMessages($assertMethod, ...$rest)
  1442. {
  1443. $this->expectException(AssertionFailedError::class);
  1444. $this->expectExceptionMessage('Possibly related to OutOfBoundsException: "oh no!"');
  1445. $this->get('/posts/throw_exception');
  1446. $this->_requestSession = new Session();
  1447. call_user_func_array([$this, $assertMethod], $rest);
  1448. }
  1449. /**
  1450. * data provider for assertion verbose session related tests
  1451. *
  1452. * @return array
  1453. */
  1454. public function assertionFailureSessionVerboseProvider()
  1455. {
  1456. return [
  1457. 'assertFlashMessageVerbose' => ['assertFlashMessage', 'notfound'],
  1458. 'assertFlashMessageAtVerbose' => ['assertFlashMessageAt', 2, 'notfound'],
  1459. 'assertFlashElementVerbose' => ['assertFlashElement', 'notfound'],
  1460. 'assertSessionVerbose' => ['assertSession', 'notfound', 'notfound'],
  1461. ];
  1462. }
  1463. /**
  1464. * Test viewVariable not found
  1465. *
  1466. * @return void
  1467. */
  1468. public function testViewVariableNotFoundShouldReturnNull()
  1469. {
  1470. $this->_controller = new Controller();
  1471. $this->assertNull($this->viewVariable('notFound'));
  1472. }
  1473. }