PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Test/PHPUnit/Controller/AbstractControllerTestCase.php

http://github.com/zendframework/zf2
PHP | 711 lines | 437 code | 69 blank | 205 comment | 61 complexity | 13c7275c43a450b5cde82056df109284 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Test\PHPUnit\Controller;
  10. use PHPUnit_Framework_TestCase;
  11. use PHPUnit_Framework_ExpectationFailedException;
  12. use Zend\Console\Console;
  13. use Zend\EventManager\StaticEventManager;
  14. use Zend\Http\Request as HttpRequest;
  15. use Zend\Mvc\Application;
  16. use Zend\Mvc\MvcEvent;
  17. use Zend\Stdlib\Exception\LogicException;
  18. use Zend\Stdlib\Parameters;
  19. use Zend\Stdlib\ResponseInterface;
  20. use Zend\Uri\Http as HttpUri;
  21. abstract class AbstractControllerTestCase extends PHPUnit_Framework_TestCase
  22. {
  23. /**
  24. * @var \Zend\Mvc\ApplicationInterface
  25. */
  26. protected $application;
  27. /**
  28. * @var array
  29. */
  30. protected $applicationConfig;
  31. /**
  32. * Flag to use console router or not
  33. * @var bool
  34. */
  35. protected $useConsoleRequest = false;
  36. /**
  37. * Flag console used before tests
  38. * @var bool
  39. */
  40. protected $usedConsoleBackup;
  41. /**
  42. * Trace error when exception is throwed in application
  43. * @var bool
  44. */
  45. protected $traceError = true;
  46. /**
  47. * Reset the application for isolation
  48. */
  49. protected function setUp()
  50. {
  51. $this->usedConsoleBackup = Console::isConsole();
  52. $this->reset();
  53. }
  54. /**
  55. * Restore params
  56. */
  57. protected function tearDown()
  58. {
  59. Console::overrideIsConsole($this->usedConsoleBackup);
  60. if (true !== $this->traceError) {
  61. return;
  62. }
  63. $exception = $this->getApplication()->getMvcEvent()->getParam('exception');
  64. if ($exception instanceof \Exception) {
  65. throw $exception;
  66. }
  67. }
  68. /**
  69. * Get the trace error flag
  70. * @return bool
  71. */
  72. public function getTraceError()
  73. {
  74. return $this->traceError;
  75. }
  76. /**
  77. * Set the trace error flag
  78. * @param bool $traceError
  79. * @return AbstractControllerTestCase
  80. */
  81. public function setTraceError($traceError)
  82. {
  83. $this->traceError = $traceError;
  84. return $this;
  85. }
  86. /**
  87. * Get the usage of the console router or not
  88. * @return bool $boolean
  89. */
  90. public function getUseConsoleRequest()
  91. {
  92. return $this->useConsoleRequest;
  93. }
  94. /**
  95. * Set the usage of the console router or not
  96. * @param bool $boolean
  97. * @return AbstractControllerTestCase
  98. */
  99. public function setUseConsoleRequest($boolean)
  100. {
  101. $this->useConsoleRequest = (bool) $boolean;
  102. return $this;
  103. }
  104. /**
  105. * Get the application config
  106. * @return array the application config
  107. */
  108. public function getApplicationConfig()
  109. {
  110. return $this->applicationConfig;
  111. }
  112. /**
  113. * Set the application config
  114. * @param array $applicationConfig
  115. * @return AbstractControllerTestCase
  116. * @throws LogicException
  117. */
  118. public function setApplicationConfig($applicationConfig)
  119. {
  120. if (null !== $this->application && null !== $this->applicationConfig) {
  121. throw new LogicException(
  122. 'Application config can not be set, the application is already built'
  123. );
  124. }
  125. // do not cache module config on testing environment
  126. if (isset($applicationConfig['module_listener_options']['config_cache_enabled'])) {
  127. $applicationConfig['module_listener_options']['config_cache_enabled'] = false;
  128. }
  129. $this->applicationConfig = $applicationConfig;
  130. return $this;
  131. }
  132. /**
  133. * Get the application object
  134. * @return \Zend\Mvc\ApplicationInterface
  135. */
  136. public function getApplication()
  137. {
  138. if ($this->application) {
  139. return $this->application;
  140. }
  141. $appConfig = $this->applicationConfig;
  142. Console::overrideIsConsole($this->getUseConsoleRequest());
  143. $this->application = Application::init($appConfig);
  144. $events = $this->application->getEventManager();
  145. $events->detach($this->application->getServiceManager()->get('SendResponseListener'));
  146. return $this->application;
  147. }
  148. /**
  149. * Get the service manager of the application object
  150. * @return \Zend\ServiceManager\ServiceManager
  151. */
  152. public function getApplicationServiceLocator()
  153. {
  154. return $this->getApplication()->getServiceManager();
  155. }
  156. /**
  157. * Get the application request object
  158. * @return \Zend\Stdlib\RequestInterface
  159. */
  160. public function getRequest()
  161. {
  162. return $this->getApplication()->getRequest();
  163. }
  164. /**
  165. * Get the application response object
  166. * @return ResponseInterface
  167. */
  168. public function getResponse()
  169. {
  170. return $this->getApplication()->getMvcEvent()->getResponse();
  171. }
  172. /**
  173. * Set the request URL
  174. *
  175. * @param string $url
  176. * @param string|null $method
  177. * @param array|null $params
  178. * @return AbstractControllerTestCase
  179. */
  180. public function url($url, $method = HttpRequest::METHOD_GET, $params = array())
  181. {
  182. $request = $this->getRequest();
  183. if ($this->useConsoleRequest) {
  184. preg_match_all('/(--\S+[= ]"[^\s"]*\s*[^\s"]*")|(--\S+=\S+|--\S+\s\S+|\S+)/', $url, $matches);
  185. $params = str_replace(array(' "', '"'), array('=', ''), $matches[0]);
  186. $request->params()->exchangeArray($params);
  187. return $this;
  188. }
  189. $query = $request->getQuery()->toArray();
  190. $post = $request->getPost()->toArray();
  191. $uri = new HttpUri($url);
  192. $queryString = $uri->getQuery();
  193. if ($queryString) {
  194. parse_str($queryString, $query);
  195. }
  196. if ($method == HttpRequest::METHOD_POST) {
  197. if (count($params) != 0) {
  198. $post = $params;
  199. }
  200. } elseif ($method == HttpRequest::METHOD_GET) {
  201. $query = array_merge($query, $params);
  202. } elseif ($method == HttpRequest::METHOD_PUT || $method == HttpRequest::METHOD_PATCH) {
  203. if (count($params) != 0) {
  204. $content = http_build_query($params);
  205. $request->setContent($content);
  206. }
  207. } elseif ($params) {
  208. trigger_error(
  209. 'Additional params is only supported by GET, POST, PUT and PATCH HTTP method',
  210. E_USER_NOTICE
  211. );
  212. }
  213. $request->setMethod($method);
  214. $request->setQuery(new Parameters($query));
  215. $request->setPost(new Parameters($post));
  216. $request->setUri($uri);
  217. $request->setRequestUri($uri->getPath());
  218. return $this;
  219. }
  220. /**
  221. * Dispatch the MVC with a URL
  222. * Accept a HTTP (simulate a customer action) or console route.
  223. *
  224. * The URL provided set the request URI in the request object.
  225. *
  226. * @param string $url
  227. * @param string|null $method
  228. * @param array|null $params
  229. * @throws \Exception
  230. */
  231. public function dispatch($url, $method = null, $params = array(), $isXmlHttpRequest = false)
  232. {
  233. if (!isset($method)
  234. && $this->getRequest() instanceof HttpRequest
  235. && $requestMethod = $this->getRequest()->getMethod()
  236. ) {
  237. $method = $requestMethod;
  238. } elseif (!isset($method)) {
  239. $method = HttpRequest::METHOD_GET;
  240. }
  241. if ($isXmlHttpRequest) {
  242. $headers = $this->getRequest()->getHeaders();
  243. $headers->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest');
  244. }
  245. $this->url($url, $method, $params);
  246. $this->getApplication()->run();
  247. }
  248. /**
  249. * Reset the request
  250. *
  251. * @return AbstractControllerTestCase
  252. */
  253. public function reset($keepPersistence = false)
  254. {
  255. // force to re-create all components
  256. $this->application = null;
  257. // reset server datas
  258. if (!$keepPersistence) {
  259. $_SESSION = array();
  260. $_COOKIE = array();
  261. }
  262. $_GET = array();
  263. $_POST = array();
  264. // reset singleton
  265. StaticEventManager::resetInstance();
  266. return $this;
  267. }
  268. /**
  269. * Trigger an application event
  270. *
  271. * @param string $eventName
  272. * @return \Zend\EventManager\ResponseCollection
  273. */
  274. public function triggerApplicationEvent($eventName)
  275. {
  276. $events = $this->getApplication()->getEventManager();
  277. $event = $this->getApplication()->getMvcEvent();
  278. if ($eventName != MvcEvent::EVENT_ROUTE && $eventName != MvcEvent::EVENT_DISPATCH) {
  279. return $events->trigger($eventName, $event);
  280. }
  281. $shortCircuit = function ($r) use ($event) {
  282. if ($r instanceof ResponseInterface) {
  283. return true;
  284. }
  285. if ($event->getError()) {
  286. return true;
  287. }
  288. return false;
  289. };
  290. return $events->trigger($eventName, $event, $shortCircuit);
  291. }
  292. /**
  293. * Assert modules were loaded with the module manager
  294. *
  295. * @param array $modules
  296. */
  297. public function assertModulesLoaded(array $modules)
  298. {
  299. $moduleManager = $this->getApplicationServiceLocator()->get('ModuleManager');
  300. $modulesLoaded = $moduleManager->getModules();
  301. $list = array_diff($modules, $modulesLoaded);
  302. if ($list) {
  303. throw new PHPUnit_Framework_ExpectationFailedException(
  304. sprintf('Several modules are not loaded "%s"', implode(', ', $list))
  305. );
  306. }
  307. $this->assertEquals(count($list), 0);
  308. }
  309. /**
  310. * Assert modules were not loaded with the module manager
  311. *
  312. * @param array $modules
  313. */
  314. public function assertNotModulesLoaded(array $modules)
  315. {
  316. $moduleManager = $this->getApplicationServiceLocator()->get('ModuleManager');
  317. $modulesLoaded = $moduleManager->getModules();
  318. $list = array_intersect($modules, $modulesLoaded);
  319. if ($list) {
  320. throw new PHPUnit_Framework_ExpectationFailedException(
  321. sprintf('Several modules WAS not loaded "%s"', implode(', ', $list))
  322. );
  323. }
  324. $this->assertEquals(count($list), 0);
  325. }
  326. /**
  327. * Retrieve the response status code
  328. *
  329. * @return int
  330. */
  331. protected function getResponseStatusCode()
  332. {
  333. $response = $this->getResponse();
  334. if (!$this->useConsoleRequest) {
  335. return $response->getStatusCode();
  336. }
  337. $match = $response->getErrorLevel();
  338. if (null === $match) {
  339. $match = 0;
  340. }
  341. return $match;
  342. }
  343. /**
  344. * Assert response status code
  345. *
  346. * @param int $code
  347. */
  348. public function assertResponseStatusCode($code)
  349. {
  350. if ($this->useConsoleRequest) {
  351. if (!in_array($code, array(0, 1))) {
  352. throw new PHPUnit_Framework_ExpectationFailedException(
  353. 'Console status code assert value must be O (valid) or 1 (error)'
  354. );
  355. }
  356. }
  357. $match = $this->getResponseStatusCode();
  358. if ($code != $match) {
  359. throw new PHPUnit_Framework_ExpectationFailedException(
  360. sprintf('Failed asserting response code "%s", actual status code is "%s"', $code, $match)
  361. );
  362. }
  363. $this->assertEquals($code, $match);
  364. }
  365. /**
  366. * Assert not response status code
  367. *
  368. * @param int $code
  369. */
  370. public function assertNotResponseStatusCode($code)
  371. {
  372. if ($this->useConsoleRequest) {
  373. if (!in_array($code, array(0, 1))) {
  374. throw new PHPUnit_Framework_ExpectationFailedException(
  375. 'Console status code assert value must be O (valid) or 1 (error)'
  376. );
  377. }
  378. }
  379. $match = $this->getResponseStatusCode();
  380. if ($code == $match) {
  381. throw new PHPUnit_Framework_ExpectationFailedException(
  382. sprintf('Failed asserting response code was NOT "%s"', $code)
  383. );
  384. }
  385. $this->assertNotEquals($code, $match);
  386. }
  387. /**
  388. * Assert the application exception and message
  389. *
  390. * @param $type application exception type
  391. * @param $message application exception message
  392. */
  393. public function assertApplicationException($type, $message = null)
  394. {
  395. $exception = $this->getApplication()->getMvcEvent()->getParam('exception');
  396. if (!$exception) {
  397. throw new PHPUnit_Framework_ExpectationFailedException(
  398. 'Failed asserting application exception, exception not exist'
  399. );
  400. }
  401. if (true === $this->traceError) {
  402. // set exception as null because we know and have assert the exception
  403. $this->getApplication()->getMvcEvent()->setParam('exception', null);
  404. }
  405. $this->setExpectedException($type, $message);
  406. throw $exception;
  407. }
  408. /**
  409. * Get the full current controller class name
  410. *
  411. * @return string
  412. */
  413. protected function getControllerFullClassName()
  414. {
  415. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  416. $controllerIdentifier = $routeMatch->getParam('controller');
  417. $controllerManager = $this->getApplicationServiceLocator()->get('ControllerManager');
  418. $controllerClass = $controllerManager->get($controllerIdentifier);
  419. return get_class($controllerClass);
  420. }
  421. /**
  422. * Assert that the application route match used the given module
  423. *
  424. * @param string $module
  425. */
  426. public function assertModuleName($module)
  427. {
  428. $controllerClass = $this->getControllerFullClassName();
  429. $match = substr($controllerClass, 0, strpos($controllerClass, '\\'));
  430. $match = strtolower($match);
  431. $module = strtolower($module);
  432. if ($module != $match) {
  433. throw new PHPUnit_Framework_ExpectationFailedException(
  434. sprintf('Failed asserting module name "%s", actual module name is "%s"', $module, $match)
  435. );
  436. }
  437. $this->assertEquals($module, $match);
  438. }
  439. /**
  440. * Assert that the application route match used NOT the given module
  441. *
  442. * @param string $module
  443. */
  444. public function assertNotModuleName($module)
  445. {
  446. $controllerClass = $this->getControllerFullClassName();
  447. $match = substr($controllerClass, 0, strpos($controllerClass, '\\'));
  448. $match = strtolower($match);
  449. $module = strtolower($module);
  450. if ($module == $match) {
  451. throw new PHPUnit_Framework_ExpectationFailedException(
  452. sprintf('Failed asserting module was NOT "%s"', $module)
  453. );
  454. }
  455. $this->assertNotEquals($module, $match);
  456. }
  457. /**
  458. * Assert that the application route match used the given controller class
  459. *
  460. * @param string $controller
  461. */
  462. public function assertControllerClass($controller)
  463. {
  464. $controllerClass = $this->getControllerFullClassName();
  465. $match = substr($controllerClass, strrpos($controllerClass, '\\')+1);
  466. $match = strtolower($match);
  467. $controller = strtolower($controller);
  468. if ($controller != $match) {
  469. throw new PHPUnit_Framework_ExpectationFailedException(
  470. sprintf('Failed asserting controller class "%s", actual controller class is "%s"', $controller, $match)
  471. );
  472. }
  473. $this->assertEquals($controller, $match);
  474. }
  475. /**
  476. * Assert that the application route match used NOT the given controller class
  477. *
  478. * @param string $controller
  479. */
  480. public function assertNotControllerClass($controller)
  481. {
  482. $controllerClass = $this->getControllerFullClassName();
  483. $match = substr($controllerClass, strrpos($controllerClass, '\\')+1);
  484. $match = strtolower($match);
  485. $controller = strtolower($controller);
  486. if ($controller == $match) {
  487. throw new PHPUnit_Framework_ExpectationFailedException(
  488. sprintf('Failed asserting controller class was NOT "%s"', $controller)
  489. );
  490. }
  491. $this->assertNotEquals($controller, $match);
  492. }
  493. /**
  494. * Assert that the application route match used the given controller name
  495. *
  496. * @param string $controller
  497. */
  498. public function assertControllerName($controller)
  499. {
  500. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  501. $match = $routeMatch->getParam('controller');
  502. $match = strtolower($match);
  503. $controller = strtolower($controller);
  504. if ($controller != $match) {
  505. throw new PHPUnit_Framework_ExpectationFailedException(
  506. sprintf('Failed asserting controller name "%s", actual controller name is "%s"', $controller, $match)
  507. );
  508. }
  509. $this->assertEquals($controller, $match);
  510. }
  511. /**
  512. * Assert that the application route match used NOT the given controller name
  513. *
  514. * @param string $controller
  515. */
  516. public function assertNotControllerName($controller)
  517. {
  518. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  519. $match = $routeMatch->getParam('controller');
  520. $match = strtolower($match);
  521. $controller = strtolower($controller);
  522. if ($controller == $match) {
  523. throw new PHPUnit_Framework_ExpectationFailedException(
  524. sprintf('Failed asserting controller name was NOT "%s"', $controller)
  525. );
  526. }
  527. $this->assertNotEquals($controller, $match);
  528. }
  529. /**
  530. * Assert that the application route match used the given action
  531. *
  532. * @param string $action
  533. */
  534. public function assertActionName($action)
  535. {
  536. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  537. $match = $routeMatch->getParam('action');
  538. $match = strtolower($match);
  539. $action = strtolower($action);
  540. if ($action != $match) {
  541. throw new PHPUnit_Framework_ExpectationFailedException(
  542. sprintf('Failed asserting action name "%s", actual action name is "%s"', $action, $match)
  543. );
  544. }
  545. $this->assertEquals($action, $match);
  546. }
  547. /**
  548. * Assert that the application route match used NOT the given action
  549. *
  550. * @param string $action
  551. */
  552. public function assertNotActionName($action)
  553. {
  554. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  555. $match = $routeMatch->getParam('action');
  556. $match = strtolower($match);
  557. $action = strtolower($action);
  558. if ($action == $match) {
  559. throw new PHPUnit_Framework_ExpectationFailedException(
  560. sprintf('Failed asserting action name was NOT "%s"', $action)
  561. );
  562. }
  563. $this->assertNotEquals($action, $match);
  564. }
  565. /**
  566. * Assert that the application route match used the given route name
  567. *
  568. * @param string $route
  569. */
  570. public function assertMatchedRouteName($route)
  571. {
  572. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  573. $match = $routeMatch->getMatchedRouteName();
  574. $match = strtolower($match);
  575. $route = strtolower($route);
  576. if ($route != $match) {
  577. throw new PHPUnit_Framework_ExpectationFailedException(
  578. sprintf('Failed asserting matched route name was "%s", actual matched route name is "%s"', $route, $match)
  579. );
  580. }
  581. $this->assertEquals($route, $match);
  582. }
  583. /**
  584. * Assert that the application route match used NOT the given route name
  585. *
  586. * @param string $route
  587. */
  588. public function assertNotMatchedRouteName($route)
  589. {
  590. $routeMatch = $this->getApplication()->getMvcEvent()->getRouteMatch();
  591. $match = $routeMatch->getMatchedRouteName();
  592. $match = strtolower($match);
  593. $route = strtolower($route);
  594. if ($route == $match) {
  595. throw new PHPUnit_Framework_ExpectationFailedException(
  596. sprintf('Failed asserting route matched was NOT "%s"', $route)
  597. );
  598. }
  599. $this->assertNotEquals($route, $match);
  600. }
  601. /**
  602. * Assert template name
  603. * Assert that a template was used somewhere in the view model tree
  604. *
  605. * @param string $templateName
  606. */
  607. public function assertTemplateName($templateName)
  608. {
  609. $viewModel = $this->getApplication()->getMvcEvent()->getViewModel();
  610. $this->assertTrue($this->searchTemplates($viewModel, $templateName));
  611. }
  612. /**
  613. * Assert not template name
  614. * Assert that a template was not used somewhere in the view model tree
  615. *
  616. * @param string $templateName
  617. */
  618. public function assertNotTemplateName($templateName)
  619. {
  620. $viewModel = $this->getApplication()->getMvcEvent()->getViewModel();
  621. $this->assertFalse($this->searchTemplates($viewModel, $templateName));
  622. }
  623. /**
  624. * Recursively search a view model and it's children for the given templateName
  625. *
  626. * @param \Zend\View\Model\ModelInterface $viewModel
  627. * @param string $templateName
  628. * @return boolean
  629. */
  630. protected function searchTemplates($viewModel, $templateName)
  631. {
  632. if ($viewModel->getTemplate($templateName) == $templateName) {
  633. return true;
  634. }
  635. foreach ($viewModel->getChildren() as $child) {
  636. return $this->searchTemplates($child, $templateName);
  637. }
  638. return false;
  639. }
  640. }