RequestHandlerComponentTest.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. <?php
  2. /**
  3. * RequestHandlerComponentTest file
  4. *
  5. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  14. * @package Cake.Test.Case.Controller.Component
  15. * @since CakePHP(tm) v 1.2.0.5435
  16. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  17. */
  18. App::uses('Controller', 'Controller');
  19. App::uses('RequestHandlerComponent', 'Controller/Component');
  20. App::uses('CakeRequest', 'Network');
  21. App::uses('CakeResponse', 'Network');
  22. App::uses('Router', 'Routing');
  23. App::uses('JsonView', 'View');
  24. /**
  25. * RequestHandlerTestController class
  26. *
  27. * @package Cake.Test.Case.Controller.Component
  28. */
  29. class RequestHandlerTestController extends Controller {
  30. /**
  31. * uses property
  32. *
  33. * @var mixed
  34. */
  35. public $uses = null;
  36. /**
  37. * test method for ajax redirection
  38. *
  39. * @return void
  40. */
  41. public function destination() {
  42. $this->viewPath = 'Posts';
  43. $this->render('index');
  44. }
  45. /**
  46. * test method for ajax redirection + parameter parsing
  47. *
  48. * @return void
  49. */
  50. public function param_method($one = null, $two = null) {
  51. echo "one: $one two: $two";
  52. $this->autoRender = false;
  53. }
  54. /**
  55. * test method for testing layout rendering when isAjax()
  56. *
  57. * @return void
  58. */
  59. public function ajax2_layout() {
  60. if ($this->autoLayout) {
  61. $this->layout = 'ajax2';
  62. }
  63. $this->destination();
  64. }
  65. }
  66. /**
  67. * CustomJsonView class
  68. *
  69. * @package Cake.Test.Case.Controller.Component
  70. */
  71. class CustomJsonView extends JsonView {
  72. }
  73. /**
  74. * RequestHandlerComponentTest class
  75. *
  76. * @package Cake.Test.Case.Controller.Component
  77. */
  78. class RequestHandlerComponentTest extends CakeTestCase {
  79. /**
  80. * Controller property
  81. *
  82. * @var RequestHandlerTestController
  83. */
  84. public $Controller;
  85. /**
  86. * RequestHandler property
  87. *
  88. * @var RequestHandlerComponent
  89. */
  90. public $RequestHandler;
  91. /**
  92. * setUp method
  93. *
  94. * @return void
  95. */
  96. public function setUp() {
  97. parent::setUp();
  98. $this->_init();
  99. }
  100. /**
  101. * init method
  102. *
  103. * @return void
  104. */
  105. protected function _init() {
  106. $request = new CakeRequest('controller_posts/index');
  107. $response = new CakeResponse();
  108. $this->Controller = new RequestHandlerTestController($request, $response);
  109. $this->Controller->constructClasses();
  110. $this->RequestHandler = new RequestHandlerComponent($this->Controller->Components);
  111. $this->_extensions = Router::extensions();
  112. }
  113. /**
  114. * tearDown method
  115. *
  116. * @return void
  117. */
  118. public function tearDown() {
  119. parent::tearDown();
  120. unset($this->RequestHandler, $this->Controller);
  121. if (!headers_sent()) {
  122. header('Content-type: text/html'); //reset content type.
  123. }
  124. call_user_func_array('Router::parseExtensions', $this->_extensions);
  125. }
  126. /**
  127. * Test that the constructor sets the settings.
  128. *
  129. * @return void
  130. */
  131. public function testConstructorSettings() {
  132. $settings = array(
  133. 'ajaxLayout' => 'test_ajax',
  134. 'viewClassMap' => array('json' => 'MyPlugin.MyJson')
  135. );
  136. $Collection = new ComponentCollection();
  137. $Collection->init($this->Controller);
  138. $RequestHandler = new RequestHandlerComponent($Collection, $settings);
  139. $this->assertEquals('test_ajax', $RequestHandler->ajaxLayout);
  140. $this->assertEquals(array('json' => 'MyPlugin.MyJson'), $RequestHandler->settings['viewClassMap']);
  141. }
  142. /**
  143. * testInitializeCallback method
  144. *
  145. * @return void
  146. */
  147. public function testInitializeCallback() {
  148. $this->assertNull($this->RequestHandler->ext);
  149. $this->Controller->request->params['ext'] = 'rss';
  150. $this->RequestHandler->initialize($this->Controller);
  151. $this->assertEquals('rss', $this->RequestHandler->ext);
  152. }
  153. /**
  154. * test that a mapped Accept-type header will set $this->ext correctly.
  155. *
  156. * @return void
  157. */
  158. public function testInitializeContentTypeSettingExt() {
  159. $this->assertNull($this->RequestHandler->ext);
  160. $_SERVER['HTTP_ACCEPT'] = 'application/json';
  161. Router::parseExtensions('json');
  162. $this->RequestHandler->initialize($this->Controller);
  163. $this->assertEquals('json', $this->RequestHandler->ext);
  164. }
  165. /**
  166. * Test that RequestHandler sets $this->ext when jQuery sends its wonky-ish headers.
  167. *
  168. * @return void
  169. */
  170. public function testInitializeContentTypeWithjQueryAccept() {
  171. $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, */*; q=0.01';
  172. $this->assertNull($this->RequestHandler->ext);
  173. Router::parseExtensions('json');
  174. $this->RequestHandler->initialize($this->Controller);
  175. $this->assertEquals('json', $this->RequestHandler->ext);
  176. }
  177. /**
  178. * Test that RequestHandler sets $this->ext when jQuery sends its wonky-ish headers
  179. * and the application is configured to handle multiple extensions
  180. *
  181. * @return void
  182. */
  183. public function testInitializeContentTypeWithjQueryAcceptAndMultiplesExtensions() {
  184. $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, */*; q=0.01';
  185. $this->assertNull($this->RequestHandler->ext);
  186. Router::parseExtensions('rss', 'json');
  187. $this->RequestHandler->initialize($this->Controller);
  188. $this->assertEquals('json', $this->RequestHandler->ext);
  189. }
  190. /**
  191. * Test that RequestHandler does not set $this->ext when multiple accepts are sent.
  192. *
  193. * @return void
  194. */
  195. public function testInitializeNoContentTypeWithSingleAccept() {
  196. $_SERVER['HTTP_ACCEPT'] = 'application/json, text/html, */*; q=0.01';
  197. $this->assertNull($this->RequestHandler->ext);
  198. Router::parseExtensions('json');
  199. $this->RequestHandler->initialize($this->Controller);
  200. $this->assertNull($this->RequestHandler->ext);
  201. }
  202. /**
  203. * Test that ext is set to the first listed extension with multiple accepted
  204. * content types.
  205. * Having multiple types accepted with same weight, means the client lets the
  206. * server choose the returned content type.
  207. *
  208. * @return void
  209. */
  210. public function testInitializeNoContentTypeWithMultipleAcceptedTypes() {
  211. $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, application/xml, */*; q=0.01';
  212. $this->assertNull($this->RequestHandler->ext);
  213. Router::parseExtensions('xml', 'json');
  214. $this->RequestHandler->initialize($this->Controller);
  215. $this->assertEquals('xml', $this->RequestHandler->ext);
  216. $this->RequestHandler->ext = null;
  217. Router::setExtensions(array('json', 'xml'), false);
  218. $this->RequestHandler->initialize($this->Controller);
  219. $this->assertEquals('json', $this->RequestHandler->ext);
  220. }
  221. /**
  222. * Test that ext is set to type with highest weight
  223. *
  224. * @return void
  225. */
  226. public function testInitializeContentTypeWithMultipleAcceptedTypes() {
  227. $_SERVER['HTTP_ACCEPT'] = 'text/csv;q=1.0, application/json;q=0.8, application/xml;q=0.7';
  228. $this->assertNull($this->RequestHandler->ext);
  229. Router::parseExtensions('xml', 'json');
  230. $this->RequestHandler->initialize($this->Controller);
  231. $this->assertEquals('json', $this->RequestHandler->ext);
  232. }
  233. /**
  234. * Test that ext is not set with confusing android accepts headers.
  235. *
  236. * @return void
  237. */
  238. public function testInitializeAmbiguousAndroidAccepts() {
  239. $_SERVER['HTTP_ACCEPT'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
  240. $this->assertNull($this->RequestHandler->ext);
  241. Router::parseExtensions('html', 'xml');
  242. $this->RequestHandler->initialize($this->Controller);
  243. $this->assertNull($this->RequestHandler->ext);
  244. }
  245. /**
  246. * Test that the headers sent by firefox are not treated as XML requests.
  247. *
  248. * @return void
  249. */
  250. public function testInititalizeFirefoxHeaderNotXml() {
  251. $_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;image/png,image/jpeg,image/*;q=0.9,*/*;q=0.8';
  252. Router::parseExtensions('xml', 'json');
  253. $this->RequestHandler->initialize($this->Controller);
  254. $this->assertNull($this->RequestHandler->ext);
  255. }
  256. /**
  257. * Test that a type mismatch doesn't incorrectly set the ext
  258. *
  259. * @return void
  260. */
  261. public function testInitializeContentTypeAndExtensionMismatch() {
  262. $this->assertNull($this->RequestHandler->ext);
  263. $extensions = Router::extensions();
  264. Router::parseExtensions('xml');
  265. $this->Controller->request = $this->getMock('CakeRequest');
  266. $this->Controller->request->expects($this->any())
  267. ->method('accepts')
  268. ->will($this->returnValue(array('application/json')));
  269. $this->RequestHandler->initialize($this->Controller);
  270. $this->assertNull($this->RequestHandler->ext);
  271. call_user_func_array(array('Router', 'parseExtensions'), $extensions);
  272. }
  273. /**
  274. * testViewClassMap method
  275. *
  276. * @return void
  277. */
  278. public function testViewClassMap() {
  279. $this->RequestHandler->settings = array('viewClassMap' => array('json' => 'CustomJson'));
  280. $this->RequestHandler->initialize($this->Controller);
  281. $result = $this->RequestHandler->viewClassMap();
  282. $expected = array(
  283. 'json' => 'CustomJson',
  284. 'xml' => 'Xml'
  285. );
  286. $this->assertEquals($expected, $result);
  287. $result = $this->RequestHandler->viewClassMap('xls', 'Excel.Excel');
  288. $expected = array(
  289. 'json' => 'CustomJson',
  290. 'xml' => 'Xml',
  291. 'xls' => 'Excel.Excel'
  292. );
  293. $this->assertEquals($expected, $result);
  294. $this->RequestHandler->renderAs($this->Controller, 'json');
  295. $this->assertEquals('CustomJson', $this->Controller->viewClass);
  296. }
  297. /**
  298. * testDisabling method
  299. *
  300. * @return void
  301. */
  302. public function testDisabling() {
  303. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
  304. $this->_init();
  305. $this->RequestHandler->initialize($this->Controller);
  306. $this->Controller->beforeFilter();
  307. $this->RequestHandler->startup($this->Controller);
  308. $this->assertEquals(true, $this->Controller->params['isAjax']);
  309. }
  310. /**
  311. * testAutoAjaxLayout method
  312. *
  313. * @return void
  314. */
  315. public function testAutoAjaxLayout() {
  316. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
  317. $this->RequestHandler->startup($this->Controller);
  318. $this->assertEquals($this->Controller->layout, $this->RequestHandler->ajaxLayout);
  319. $this->_init();
  320. $this->Controller->request->params['ext'] = 'js';
  321. $this->RequestHandler->initialize($this->Controller);
  322. $this->RequestHandler->startup($this->Controller);
  323. $this->assertNotEquals('ajax', $this->Controller->layout);
  324. unset($_SERVER['HTTP_X_REQUESTED_WITH']);
  325. }
  326. /**
  327. * testStartupCallback method
  328. *
  329. * @return void
  330. */
  331. public function testStartupCallback() {
  332. $_SERVER['REQUEST_METHOD'] = 'PUT';
  333. $_SERVER['CONTENT_TYPE'] = 'application/xml';
  334. $this->Controller->request = $this->getMock('CakeRequest', array('_readInput'));
  335. $this->RequestHandler->startup($this->Controller);
  336. $this->assertTrue(is_array($this->Controller->data));
  337. $this->assertFalse(is_object($this->Controller->data));
  338. }
  339. /**
  340. * testStartupCallback with charset.
  341. *
  342. * @return void
  343. */
  344. public function testStartupCallbackCharset() {
  345. $_SERVER['REQUEST_METHOD'] = 'PUT';
  346. $_SERVER['CONTENT_TYPE'] = 'application/xml; charset=UTF-8';
  347. $this->Controller->request = $this->getMock('CakeRequest', array('_readInput'));
  348. $this->RequestHandler->startup($this->Controller);
  349. $this->assertTrue(is_array($this->Controller->data));
  350. $this->assertFalse(is_object($this->Controller->data));
  351. }
  352. /**
  353. * Test mapping a new type and having startup process it.
  354. *
  355. * @return void
  356. */
  357. public function testStartupCustomTypeProcess() {
  358. if (!function_exists('str_getcsv')) {
  359. $this->markTestSkipped('Need "str_getcsv" for this test.');
  360. }
  361. $_SERVER['REQUEST_METHOD'] = 'POST';
  362. $_SERVER['CONTENT_TYPE'] = 'text/csv';
  363. $this->Controller->request = $this->getMock('CakeRequest', array('_readInput'));
  364. $this->Controller->request->expects($this->once())
  365. ->method('_readInput')
  366. ->will($this->returnValue('"A","csv","string"'));
  367. $this->RequestHandler->addInputType('csv', array('str_getcsv'));
  368. $this->RequestHandler->startup($this->Controller);
  369. $expected = array(
  370. 'A', 'csv', 'string'
  371. );
  372. $this->assertEquals($expected, $this->Controller->request->data);
  373. }
  374. /**
  375. * testNonAjaxRedirect method
  376. *
  377. * @return void
  378. */
  379. public function testNonAjaxRedirect() {
  380. $this->RequestHandler->initialize($this->Controller);
  381. $this->RequestHandler->startup($this->Controller);
  382. $this->assertNull($this->RequestHandler->beforeRedirect($this->Controller, '/'));
  383. }
  384. /**
  385. * test that redirects with ajax and no URL don't do anything.
  386. *
  387. * @return void
  388. */
  389. public function testAjaxRedirectWithNoUrl() {
  390. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
  391. $this->Controller->response = $this->getMock('CakeResponse');
  392. $this->Controller->response->expects($this->never())
  393. ->method('body');
  394. $this->RequestHandler->initialize($this->Controller);
  395. $this->RequestHandler->startup($this->Controller);
  396. $this->assertNull($this->RequestHandler->beforeRedirect($this->Controller, null));
  397. }
  398. /**
  399. * testRenderAs method
  400. *
  401. * @return void
  402. */
  403. public function testRenderAs() {
  404. $this->assertFalse(in_array('Rss', $this->Controller->helpers));
  405. $this->RequestHandler->renderAs($this->Controller, 'rss');
  406. $this->assertTrue(in_array('Rss', $this->Controller->helpers));
  407. $this->Controller->viewPath = 'request_handler_test\\rss';
  408. $this->RequestHandler->renderAs($this->Controller, 'js');
  409. $this->assertEquals('request_handler_test' . DS . 'js', $this->Controller->viewPath);
  410. }
  411. /**
  412. * test that attachment headers work with renderAs
  413. *
  414. * @return void
  415. */
  416. public function testRenderAsWithAttachment() {
  417. $this->RequestHandler->request = $this->getMock('CakeRequest');
  418. $this->RequestHandler->request->expects($this->any())
  419. ->method('parseAccept')
  420. ->will($this->returnValue(array('1.0' => array('application/xml'))));
  421. $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download', 'charset'));
  422. $this->RequestHandler->response->expects($this->at(0))
  423. ->method('type')
  424. ->with('application/xml');
  425. $this->RequestHandler->response->expects($this->at(1))
  426. ->method('charset')
  427. ->with('UTF-8');
  428. $this->RequestHandler->response->expects($this->at(2))
  429. ->method('download')
  430. ->with('myfile.xml');
  431. $this->RequestHandler->renderAs($this->Controller, 'xml', array('attachment' => 'myfile.xml'));
  432. $this->assertEquals('Xml', $this->Controller->viewClass);
  433. }
  434. /**
  435. * test that respondAs works as expected.
  436. *
  437. * @return void
  438. */
  439. public function testRespondAs() {
  440. $this->RequestHandler->response = $this->getMock('CakeResponse', array('type'));
  441. $this->RequestHandler->response->expects($this->at(0))->method('type')
  442. ->with('application/json');
  443. $this->RequestHandler->response->expects($this->at(1))->method('type')
  444. ->with('text/xml');
  445. $result = $this->RequestHandler->respondAs('json');
  446. $this->assertTrue($result);
  447. $result = $this->RequestHandler->respondAs('text/xml');
  448. $this->assertTrue($result);
  449. }
  450. /**
  451. * test that attachment headers work with respondAs
  452. *
  453. * @return void
  454. */
  455. public function testRespondAsWithAttachment() {
  456. $this->RequestHandler = $this->getMock(
  457. 'RequestHandlerComponent',
  458. array('_header'),
  459. array(&$this->Controller->Components)
  460. );
  461. $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download'));
  462. $this->RequestHandler->request = $this->getMock('CakeRequest');
  463. $this->RequestHandler->request->expects($this->once())
  464. ->method('parseAccept')
  465. ->will($this->returnValue(array('1.0' => array('application/xml'))));
  466. $this->RequestHandler->response->expects($this->once())->method('download')
  467. ->with('myfile.xml');
  468. $this->RequestHandler->response->expects($this->once())->method('type')
  469. ->with('application/xml');
  470. $result = $this->RequestHandler->respondAs('xml', array('attachment' => 'myfile.xml'));
  471. $this->assertTrue($result);
  472. }
  473. /**
  474. * test that calling renderAs() more than once continues to work.
  475. *
  476. * @link #6466
  477. * @return void
  478. */
  479. public function testRenderAsCalledTwice() {
  480. $this->RequestHandler->renderAs($this->Controller, 'print');
  481. $this->assertEquals('RequestHandlerTest' . DS . 'print', $this->Controller->viewPath);
  482. $this->assertEquals('print', $this->Controller->layoutPath);
  483. $this->RequestHandler->renderAs($this->Controller, 'js');
  484. $this->assertEquals('RequestHandlerTest' . DS . 'js', $this->Controller->viewPath);
  485. $this->assertEquals('js', $this->Controller->layoutPath);
  486. $this->assertTrue(in_array('Js', $this->Controller->helpers));
  487. }
  488. /**
  489. * testRequestClientTypes method
  490. *
  491. * @return void
  492. */
  493. public function testRequestClientTypes() {
  494. $_SERVER['HTTP_X_PROTOTYPE_VERSION'] = '1.5';
  495. $this->assertEquals('1.5', $this->RequestHandler->getAjaxVersion());
  496. unset($_SERVER['HTTP_X_REQUESTED_WITH'], $_SERVER['HTTP_X_PROTOTYPE_VERSION']);
  497. $this->assertFalse($this->RequestHandler->getAjaxVersion());
  498. }
  499. /**
  500. * Tests the detection of various Flash versions
  501. *
  502. * @return void
  503. */
  504. public function testFlashDetection() {
  505. $request = $this->getMock('CakeRequest');
  506. $request->expects($this->once())->method('is')
  507. ->with('flash')
  508. ->will($this->returnValue(true));
  509. $this->RequestHandler->request = $request;
  510. $this->assertTrue($this->RequestHandler->isFlash());
  511. }
  512. /**
  513. * testRequestContentTypes method
  514. *
  515. * @return void
  516. */
  517. public function testRequestContentTypes() {
  518. $_SERVER['REQUEST_METHOD'] = 'GET';
  519. $this->assertNull($this->RequestHandler->requestedWith());
  520. $_SERVER['REQUEST_METHOD'] = 'POST';
  521. $_SERVER['CONTENT_TYPE'] = 'application/json';
  522. $this->assertEquals('json', $this->RequestHandler->requestedWith());
  523. $result = $this->RequestHandler->requestedWith(array('json', 'xml'));
  524. $this->assertEquals('json', $result);
  525. $result = $this->RequestHandler->requestedWith(array('rss', 'atom'));
  526. $this->assertFalse($result);
  527. $_SERVER['REQUEST_METHOD'] = 'DELETE';
  528. $this->assertEquals('json', $this->RequestHandler->requestedWith());
  529. $_SERVER['REQUEST_METHOD'] = 'POST';
  530. unset($_SERVER['CONTENT_TYPE']);
  531. $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json';
  532. $result = $this->RequestHandler->requestedWith(array('json', 'xml'));
  533. $this->assertEquals('json', $result);
  534. $result = $this->RequestHandler->requestedWith(array('rss', 'atom'));
  535. $this->assertFalse($result);
  536. $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*';
  537. $this->assertTrue($this->RequestHandler->isXml());
  538. $this->assertFalse($this->RequestHandler->isAtom());
  539. $this->assertFalse($this->RequestHandler->isRSS());
  540. $_SERVER['HTTP_ACCEPT'] = 'application/atom+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*';
  541. $this->assertTrue($this->RequestHandler->isAtom());
  542. $this->assertFalse($this->RequestHandler->isRSS());
  543. $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*';
  544. $this->assertFalse($this->RequestHandler->isAtom());
  545. $this->assertTrue($this->RequestHandler->isRSS());
  546. $this->assertFalse($this->RequestHandler->isWap());
  547. $_SERVER['HTTP_ACCEPT'] = 'text/vnd.wap.wml,text/html,text/plain,image/png,*/*';
  548. $this->assertTrue($this->RequestHandler->isWap());
  549. $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*';
  550. }
  551. /**
  552. * testResponseContentType method
  553. *
  554. * @return void
  555. */
  556. public function testResponseContentType() {
  557. $this->assertEquals('html', $this->RequestHandler->responseType());
  558. $this->assertTrue($this->RequestHandler->respondAs('atom'));
  559. $this->assertEquals('atom', $this->RequestHandler->responseType());
  560. }
  561. /**
  562. * testMobileDeviceDetection method
  563. *
  564. * @return void
  565. */
  566. public function testMobileDeviceDetection() {
  567. $request = $this->getMock('CakeRequest');
  568. $request->expects($this->once())->method('is')
  569. ->with('mobile')
  570. ->will($this->returnValue(true));
  571. $this->RequestHandler->request = $request;
  572. $this->assertTrue($this->RequestHandler->isMobile());
  573. }
  574. /**
  575. * testRequestProperties method
  576. *
  577. * @return void
  578. */
  579. public function testRequestProperties() {
  580. $request = $this->getMock('CakeRequest');
  581. $request->expects($this->once())->method('is')
  582. ->with('ssl')
  583. ->will($this->returnValue(true));
  584. $this->RequestHandler->request = $request;
  585. $this->assertTrue($this->RequestHandler->isSsl());
  586. }
  587. /**
  588. * testRequestMethod method
  589. *
  590. * @return void
  591. */
  592. public function testRequestMethod() {
  593. $request = $this->getMock('CakeRequest');
  594. $request->expects($this->at(0))->method('is')
  595. ->with('get')
  596. ->will($this->returnValue(true));
  597. $request->expects($this->at(1))->method('is')
  598. ->with('post')
  599. ->will($this->returnValue(false));
  600. $request->expects($this->at(2))->method('is')
  601. ->with('delete')
  602. ->will($this->returnValue(true));
  603. $request->expects($this->at(3))->method('is')
  604. ->with('put')
  605. ->will($this->returnValue(false));
  606. $this->RequestHandler->request = $request;
  607. $this->assertTrue($this->RequestHandler->isGet());
  608. $this->assertFalse($this->RequestHandler->isPost());
  609. $this->assertTrue($this->RequestHandler->isDelete());
  610. $this->assertFalse($this->RequestHandler->isPut());
  611. }
  612. /**
  613. * test that map alias converts aliases to content types.
  614. *
  615. * @return void
  616. */
  617. public function testMapAlias() {
  618. $result = $this->RequestHandler->mapAlias('xml');
  619. $this->assertEquals('application/xml', $result);
  620. $result = $this->RequestHandler->mapAlias('text/html');
  621. $this->assertNull($result);
  622. $result = $this->RequestHandler->mapAlias('wap');
  623. $this->assertEquals('text/vnd.wap.wml', $result);
  624. $result = $this->RequestHandler->mapAlias(array('xml', 'js', 'json'));
  625. $expected = array('application/xml', 'application/javascript', 'application/json');
  626. $this->assertEquals($expected, $result);
  627. }
  628. /**
  629. * test accepts() on the component
  630. *
  631. * @return void
  632. */
  633. public function testAccepts() {
  634. $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
  635. $this->assertTrue($this->RequestHandler->accepts(array('js', 'xml', 'html')));
  636. $this->assertFalse($this->RequestHandler->accepts(array('gif', 'jpeg', 'foo')));
  637. $_SERVER['HTTP_ACCEPT'] = '*/*;q=0.5';
  638. $this->assertFalse($this->RequestHandler->accepts('rss'));
  639. }
  640. /**
  641. * test accepts and prefers methods.
  642. *
  643. * @return void
  644. */
  645. public function testPrefers() {
  646. $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*';
  647. $this->assertNotEquals('rss', $this->RequestHandler->prefers());
  648. $this->RequestHandler->ext = 'rss';
  649. $this->assertEquals('rss', $this->RequestHandler->prefers());
  650. $this->assertFalse($this->RequestHandler->prefers('xml'));
  651. $this->assertEquals('xml', $this->RequestHandler->prefers(array('js', 'xml', 'xhtml')));
  652. $this->assertFalse($this->RequestHandler->prefers(array('red', 'blue')));
  653. $this->assertEquals('xhtml', $this->RequestHandler->prefers(array('js', 'json', 'xhtml')));
  654. $this->assertTrue($this->RequestHandler->prefers(array('rss')), 'Should return true if input matches ext.');
  655. $this->assertFalse($this->RequestHandler->prefers(array('html')), 'No match with ext, return false.');
  656. $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
  657. $this->_init();
  658. $this->assertEquals('xml', $this->RequestHandler->prefers());
  659. $_SERVER['HTTP_ACCEPT'] = '*/*;q=0.5';
  660. $this->assertEquals('html', $this->RequestHandler->prefers());
  661. $this->assertFalse($this->RequestHandler->prefers('rss'));
  662. }
  663. /**
  664. * testCustomContent method
  665. *
  666. * @return void
  667. */
  668. public function testCustomContent() {
  669. $_SERVER['HTTP_ACCEPT'] = 'text/x-mobile,text/html;q=0.9,text/plain;q=0.8,*/*;q=0.5';
  670. $this->RequestHandler->setContent('mobile', 'text/x-mobile');
  671. $this->RequestHandler->startup($this->Controller);
  672. $this->assertEquals('mobile', $this->RequestHandler->prefers());
  673. }
  674. /**
  675. * testClientProperties method
  676. *
  677. * @return void
  678. */
  679. public function testClientProperties() {
  680. $request = $this->getMock('CakeRequest');
  681. $request->expects($this->once())->method('referer');
  682. $request->expects($this->once())->method('clientIp')->will($this->returnValue(false));
  683. $this->RequestHandler->request = $request;
  684. $this->RequestHandler->getReferer();
  685. $this->RequestHandler->getClientIP(false);
  686. }
  687. /**
  688. * test that ajax requests involving redirects trigger requestAction instead.
  689. *
  690. * @return void
  691. */
  692. public function testAjaxRedirectAsRequestAction() {
  693. App::build(array(
  694. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  695. ), App::RESET);
  696. $this->Controller->RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  697. $this->Controller->request = $this->getMock('CakeRequest');
  698. $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader'));
  699. $this->Controller->RequestHandler->request = $this->Controller->request;
  700. $this->Controller->RequestHandler->response = $this->Controller->response;
  701. $this->Controller->request->expects($this->any())->method('is')->will($this->returnValue(true));
  702. $this->Controller->RequestHandler->expects($this->once())->method('_stop');
  703. ob_start();
  704. $this->Controller->RequestHandler->beforeRedirect(
  705. $this->Controller, array('controller' => 'request_handler_test', 'action' => 'destination')
  706. );
  707. $result = ob_get_clean();
  708. $this->assertRegExp('/posts index/', $result, 'RequestAction redirect failed.');
  709. App::build();
  710. }
  711. /**
  712. * test that ajax requests involving redirects don't force no layout
  713. * this would cause the ajax layout to not be rendered.
  714. *
  715. * @return void
  716. */
  717. public function testAjaxRedirectAsRequestActionStillRenderingLayout() {
  718. App::build(array(
  719. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  720. ), App::RESET);
  721. $this->Controller->RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  722. $this->Controller->request = $this->getMock('CakeRequest');
  723. $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader'));
  724. $this->Controller->RequestHandler->request = $this->Controller->request;
  725. $this->Controller->RequestHandler->response = $this->Controller->response;
  726. $this->Controller->request->expects($this->any())->method('is')->will($this->returnValue(true));
  727. $this->Controller->RequestHandler->expects($this->once())->method('_stop');
  728. ob_start();
  729. $this->Controller->RequestHandler->beforeRedirect(
  730. $this->Controller, array('controller' => 'request_handler_test', 'action' => 'ajax2_layout')
  731. );
  732. $result = ob_get_clean();
  733. $this->assertRegExp('/posts index/', $result, 'RequestAction redirect failed.');
  734. $this->assertRegExp('/Ajax!/', $result, 'Layout was not rendered.');
  735. App::build();
  736. }
  737. /**
  738. * test that the beforeRedirect callback properly converts
  739. * array URLs into their correct string ones, and adds base => false so
  740. * the correct URLs are generated.
  741. *
  742. * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp-1x/tickets/276
  743. * @return void
  744. */
  745. public function testBeforeRedirectCallbackWithArrayUrl() {
  746. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
  747. Router::setRequestInfo(array(
  748. array('plugin' => null, 'controller' => 'accounts', 'action' => 'index', 'pass' => array(), 'named' => array(), 'form' => array(), 'url' => array('url' => 'accounts/')),
  749. array('base' => '/officespace', 'here' => '/officespace/accounts/', 'webroot' => '/officespace/')
  750. ));
  751. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  752. $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader'));
  753. $RequestHandler->request = new CakeRequest('posts/index');
  754. $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader'));
  755. ob_start();
  756. $RequestHandler->beforeRedirect(
  757. $this->Controller,
  758. array('controller' => 'request_handler_test', 'action' => 'param_method', 'first', 'second')
  759. );
  760. $result = ob_get_clean();
  761. $this->assertEquals('one: first two: second', $result);
  762. }
  763. /**
  764. * assure that beforeRedirect with a status code will correctly set the status header
  765. *
  766. * @return void
  767. */
  768. public function testBeforeRedirectCallingHeader() {
  769. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
  770. $controller = $this->getMock('Controller', array('header'));
  771. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  772. $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader', 'statusCode'));
  773. $RequestHandler->request = $this->getMock('CakeRequest');
  774. $RequestHandler->request->expects($this->once())->method('is')
  775. ->with('ajax')
  776. ->will($this->returnValue(true));
  777. $RequestHandler->response->expects($this->once())->method('statusCode')->with(403);
  778. ob_start();
  779. $RequestHandler->beforeRedirect($controller, 'request_handler_test/param_method/first/second', 403);
  780. ob_get_clean();
  781. }
  782. /**
  783. * @expectedException CakeException
  784. * @return void
  785. */
  786. public function testAddInputTypeException() {
  787. $this->RequestHandler->addInputType('csv', array('I am not callable'));
  788. }
  789. /**
  790. * Test checkNotModified method
  791. *
  792. * @return void
  793. */
  794. public function testCheckNotModifiedByEtagStar() {
  795. $_SERVER['HTTP_IF_NONE_MATCH'] = '*';
  796. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  797. $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
  798. $RequestHandler->response->etag('something');
  799. $RequestHandler->response->expects($this->once())->method('notModified');
  800. $this->assertFalse($RequestHandler->beforeRender($this->Controller));
  801. }
  802. /**
  803. * Test checkNotModified method
  804. *
  805. * @return void
  806. */
  807. public function testCheckNotModifiedByEtagExact() {
  808. $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
  809. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  810. $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
  811. $RequestHandler->response->etag('something', true);
  812. $RequestHandler->response->expects($this->once())->method('notModified');
  813. $this->assertFalse($RequestHandler->beforeRender($this->Controller));
  814. }
  815. /**
  816. * Test checkNotModified method
  817. *
  818. * @return void
  819. */
  820. public function testCheckNotModifiedByEtagAndTime() {
  821. $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
  822. $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
  823. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  824. $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
  825. $RequestHandler->response->etag('something', true);
  826. $RequestHandler->response->modified('2012-01-01 00:00:00');
  827. $RequestHandler->response->expects($this->once())->method('notModified');
  828. $this->assertFalse($RequestHandler->beforeRender($this->Controller));
  829. }
  830. /**
  831. * Test checkNotModified method
  832. *
  833. * @return void
  834. */
  835. public function testCheckNotModifiedNoInfo() {
  836. $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
  837. $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
  838. $RequestHandler->response->expects($this->never())->method('notModified');
  839. $this->assertNull($RequestHandler->beforeRender($this->Controller));
  840. }
  841. }