CRUDControllerTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <?php
  2. /*
  3. * This file is part of the Sonata package.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Sonata\AdminBundle\Tests\Controller;
  11. use Symfony\Component\DependencyInjection\ContainerInterface;
  12. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Sonata\AdminBundle\Controller\CRUDController;
  15. use Sonata\AdminBundle\Admin\Pool;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Bridge\Twig\Extension\FormExtension;
  18. use Symfony\Component\HttpFoundation\Session\Session;
  19. use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
  20. /**
  21. * Test for CRUDController
  22. *
  23. * @author Andrej Hudec <pulzarraider@gmail.com>
  24. */
  25. class CRUDControllerTest extends \PHPUnit_Framework_TestCase
  26. {
  27. /**
  28. * @var CRUDController
  29. */
  30. private $controller;
  31. /**
  32. * @var Request
  33. */
  34. private $request;
  35. /**
  36. * @var Sonata\AdminBundle\Admin\AdminInterface
  37. */
  38. private $admin;
  39. /**
  40. * @var Pool
  41. */
  42. private $pool;
  43. /**
  44. * @var array
  45. */
  46. private $parameters;
  47. /**
  48. *
  49. * @var Session
  50. */
  51. private $session;
  52. /**
  53. * {@inheritDoc}
  54. */
  55. protected function setUp()
  56. {
  57. $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
  58. $this->request = new Request();
  59. $this->pool = new Pool($container, 'title', 'logo.png');
  60. $this->request->attributes->set('_sonata_admin', 'foo.admin');
  61. $this->admin = $this->getMock('Sonata\AdminBundle\Admin\AdminInterface');
  62. $this->parameters = array();
  63. // php 5.3 BC
  64. $params = &$this->parameters;
  65. $templating = $this->getMock('Symfony\Bundle\FrameworkBundle\Templating\DelegatingEngine', array(), array($container, array()));
  66. $templating->expects($this->any())
  67. ->method('renderResponse')
  68. ->will($this->returnCallback(function($view, array $parameters = array(), Response $response = null) use (&$params) {
  69. if (null === $response) {
  70. $response = new Response();
  71. }
  72. $params = $parameters;
  73. return $response;
  74. }));
  75. $this->session = new Session(new MockArraySessionStorage());
  76. // php 5.3 BC
  77. $pool = $this->pool;
  78. $request = $this->request;
  79. $admin = $this->admin;
  80. $session = $this->session;
  81. $twig = $this->getMockBuilder('Twig_Environment')
  82. ->disableOriginalConstructor()
  83. ->getMock();
  84. $twigRenderer = $this->getMock('Symfony\Bridge\Twig\Form\TwigRendererInterface');
  85. $formExtension = new FormExtension($twigRenderer);
  86. $twig->expects($this->any())
  87. ->method('getExtension')
  88. ->will($this->returnCallback(function($name) use ($formExtension) {
  89. switch ($name) {
  90. case 'form':
  91. return $formExtension;
  92. }
  93. return null;
  94. }));
  95. $container->expects($this->any())
  96. ->method('get')
  97. ->will($this->returnCallback(function($id) use ($pool, $request, $admin, $templating, $twig, $session) {
  98. switch ($id) {
  99. case 'sonata.admin.pool':
  100. return $pool;
  101. case 'request':
  102. return $request;
  103. case 'foo.admin':
  104. return $admin;
  105. case 'templating':
  106. return $templating;
  107. case 'twig':
  108. return $twig;
  109. case 'session':
  110. return $session;
  111. }
  112. return null;
  113. }));
  114. $this->admin->expects($this->any())
  115. ->method('getTemplate')
  116. ->will($this->returnCallback(function($name) {
  117. switch ($name) {
  118. case 'ajax':
  119. return 'SonataAdminBundle::ajax_layout.html.twig';
  120. case 'layout':
  121. return 'SonataAdminBundle::standard_layout.html.twig';
  122. }
  123. return null;
  124. }));
  125. $this->controller = new CRUDController();
  126. $this->controller->setContainer($container);
  127. }
  128. public function testRenderJson1()
  129. {
  130. $data = array('example'=>'123', 'foo'=>'bar');
  131. $this->request->headers->set('Content-Type', 'application/x-www-form-urlencoded');
  132. $response = $this->controller->renderJson($data);
  133. $this->assertEquals($response->headers->get('Content-Type'), 'application/json');
  134. $this->assertEquals(json_encode($data), $response->getContent());
  135. }
  136. public function testRenderJson2()
  137. {
  138. $data = array('example'=>'123', 'foo'=>'bar');
  139. $this->request->headers->set('Content-Type', 'multipart/form-data');
  140. $response = $this->controller->renderJson($data);
  141. $this->assertEquals($response->headers->get('Content-Type'), 'application/json');
  142. $this->assertEquals(json_encode($data), $response->getContent());
  143. }
  144. public function testRenderJsonAjax()
  145. {
  146. $data = array('example'=>'123', 'foo'=>'bar');
  147. $this->request->attributes->set('_xml_http_request', true);
  148. $this->request->headers->set('Content-Type', 'multipart/form-data');
  149. $response = $this->controller->renderJson($data);
  150. $this->assertEquals($response->headers->get('Content-Type'), 'text/plain');
  151. $this->assertEquals(json_encode($data), $response->getContent());
  152. }
  153. public function testIsXmlHttpRequest()
  154. {
  155. $this->assertFalse($this->controller->isXmlHttpRequest());
  156. $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
  157. $this->assertTrue($this->controller->isXmlHttpRequest());
  158. $this->request->headers->remove('X-Requested-With');
  159. $this->assertFalse($this->controller->isXmlHttpRequest());
  160. $this->request->attributes->set('_xml_http_request', true);
  161. $this->assertTrue($this->controller->isXmlHttpRequest());
  162. }
  163. public function testConfigureWithException()
  164. {
  165. $this->setExpectedException('RuntimeException', 'There is no `_sonata_admin` defined for the controller `Sonata\AdminBundle\Controller\CRUDController`');
  166. $this->request->attributes->remove('_sonata_admin');
  167. $this->controller->configure();
  168. }
  169. public function testConfigureWithException2()
  170. {
  171. $this->setExpectedException('RuntimeException', 'Unable to find the admin class related to the current controller (Sonata\AdminBundle\Controller\CRUDController)');
  172. $this->request->attributes->set('_sonata_admin', 'nonexistent.admin');
  173. $this->controller->configure();
  174. }
  175. public function testGetBaseTemplate()
  176. {
  177. $this->assertEquals('SonataAdminBundle::standard_layout.html.twig', $this->controller->getBaseTemplate());
  178. $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
  179. $this->assertEquals('SonataAdminBundle::ajax_layout.html.twig', $this->controller->getBaseTemplate());
  180. $this->request->headers->remove('X-Requested-With');
  181. $this->assertEquals('SonataAdminBundle::standard_layout.html.twig', $this->controller->getBaseTemplate());
  182. $this->request->attributes->set('_xml_http_request', true);
  183. $this->assertEquals('SonataAdminBundle::ajax_layout.html.twig', $this->controller->getBaseTemplate());
  184. }
  185. public function testRender()
  186. {
  187. $this->parameters = array();
  188. $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $this->controller->render('FooAdminBundle::foo.html.twig', array()));
  189. $this->assertEquals($this->admin, $this->parameters['admin']);
  190. $this->assertEquals('SonataAdminBundle::standard_layout.html.twig', $this->parameters['base_template']);
  191. $this->assertEquals($this->pool, $this->parameters['admin_pool']);
  192. }
  193. public function testRenderCustomParams()
  194. {
  195. $this->parameters = array();
  196. $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $this->controller->render('FooAdminBundle::foo.html.twig', array('foo'=>'bar')));
  197. $this->assertEquals($this->admin, $this->parameters['admin']);
  198. $this->assertEquals('SonataAdminBundle::standard_layout.html.twig', $this->parameters['base_template']);
  199. $this->assertEquals($this->pool, $this->parameters['admin_pool']);
  200. $this->assertEquals('bar', $this->parameters['foo']);
  201. }
  202. public function testRenderAjax()
  203. {
  204. $this->parameters = array();
  205. $this->request->headers->set('X-Requested-With', 'XMLHttpRequest');
  206. $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $this->controller->render('FooAdminBundle::foo.html.twig', array('foo'=>'bar')));
  207. $this->assertEquals($this->admin, $this->parameters['admin']);
  208. $this->assertEquals('SonataAdminBundle::ajax_layout.html.twig', $this->parameters['base_template']);
  209. $this->assertEquals($this->pool, $this->parameters['admin_pool']);
  210. $this->assertEquals('bar', $this->parameters['foo']);
  211. }
  212. public function testListActionAccessDenied()
  213. {
  214. $this->setExpectedException('Symfony\Component\Security\Core\Exception\AccessDeniedException');
  215. $this->admin->expects($this->once())
  216. ->method('isGranted')
  217. ->will($this->returnValue(false));
  218. $this->controller->listAction();
  219. }
  220. public function testListAction()
  221. {
  222. $datagrid = $this->getMock('Sonata\AdminBundle\Datagrid\DatagridInterface');
  223. $form = $this->getMockBuilder('Symfony\Component\Form\Form')
  224. ->disableOriginalConstructor()
  225. ->getMock();
  226. $form->expects($this->once())
  227. ->method('createView')
  228. ->will($this->returnValue($this->getMock('Symfony\Component\Form\FormView')));
  229. $this->admin->expects($this->once())
  230. ->method('getDatagrid')
  231. ->will($this->returnValue($datagrid));
  232. $datagrid->expects($this->once())
  233. ->method('getForm')
  234. ->will($this->returnValue($form));
  235. $this->parameters = array();
  236. $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $this->controller->listAction());
  237. $this->assertEquals($this->admin, $this->parameters['admin']);
  238. $this->assertEquals('SonataAdminBundle::standard_layout.html.twig', $this->parameters['base_template']);
  239. $this->assertEquals($this->pool, $this->parameters['admin_pool']);
  240. $this->assertEquals('list', $this->parameters['action']);
  241. $this->assertInstanceOf('Symfony\Component\Form\FormView', $this->parameters['form']);
  242. $this->assertInstanceOf('Sonata\AdminBundle\Datagrid\DatagridInterface', $this->parameters['datagrid']);
  243. $this->assertEquals('', $this->parameters['csrf_token']);
  244. }
  245. /**
  246. * @dataProvider getRedirectToTests
  247. */
  248. public function testRedirectTo($expected, $queryParams, $hasActiveSubclass)
  249. {
  250. $this->admin->expects($this->any())
  251. ->method('generateUrl')
  252. ->will($this->returnCallback(function($name, array $parameters = array(), $absolute = false) {
  253. $result = $name;
  254. if (!empty($parameters)) {
  255. $result .= '_'.implode('-', $parameters);
  256. }
  257. return $result;
  258. }));
  259. $this->admin->expects($this->any())
  260. ->method('generateObjectUrl')
  261. ->will($this->returnCallback(function($name, $object, array $parameters = array(), $absolute = false) {
  262. return get_class($object).'_'.$name;
  263. }));
  264. $this->admin->expects($this->any())
  265. ->method('hasActiveSubclass')
  266. ->will($this->returnValue($hasActiveSubclass));
  267. $object = new \stdClass();
  268. foreach ($queryParams as $key => $value) {
  269. $this->request->query->set($key, $value);
  270. }
  271. $response = $this->controller->redirectTo($object);
  272. $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response);
  273. $this->assertEquals($expected, $response->getTargetUrl());
  274. }
  275. public function getRedirectToTests()
  276. {
  277. return array(
  278. array('stdClass_edit', array(), false),
  279. array('list', array('btn_update_and_list'=>true), false),
  280. array('list', array('btn_create_and_list'=>true), false),
  281. array('create', array('btn_create_and_create'=>true), false),
  282. array('create_foo', array('btn_create_and_create'=>true, 'subclass'=>'foo'), true),
  283. );
  284. }
  285. public function testAddFlash()
  286. {
  287. $this->controller->addFlash('foo', 'bar');
  288. $this->assertSame(array('bar'), $this->session->getFlashBag()->get('foo'));
  289. }
  290. }