GenerateAdminCommandTest.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. <?php
  2. /*
  3. * This file is part of the Sonata Project 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\Command;
  11. use Sonata\AdminBundle\Command\GenerateAdminCommand;
  12. use Sonata\AdminBundle\Tests\Fixtures\Bundle\DemoAdminBundle;
  13. use Sonata\AdminBundle\Tests\Helpers\PHPUnit_Framework_TestCase;
  14. use Symfony\Bundle\FrameworkBundle\Console\Application;
  15. use Symfony\Component\Console\Input\InputInterface;
  16. use Symfony\Component\Console\Output\OutputInterface;
  17. use Symfony\Component\Console\Question\Question;
  18. use Symfony\Component\Console\Tester\CommandTester;
  19. use Symfony\Component\DependencyInjection\Container;
  20. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  21. /**
  22. * @author Andrej Hudec <pulzarraider@gmail.com>
  23. */
  24. class GenerateAdminCommandTest extends PHPUnit_Framework_TestCase
  25. {
  26. /**
  27. * @var Application
  28. */
  29. private $application;
  30. /**
  31. * @var string
  32. */
  33. private $tempDirectory;
  34. /**
  35. * @var Container
  36. */
  37. private $container;
  38. /**
  39. * @var GenerateAdminCommand
  40. */
  41. private $command;
  42. protected function setUp()
  43. {
  44. // create temp dir
  45. $tempfile = tempnam(sys_get_temp_dir(), 'sonata_admin');
  46. if (file_exists($tempfile)) {
  47. unlink($tempfile);
  48. }
  49. mkdir($tempfile);
  50. $this->tempDirectory = $tempfile;
  51. $bundle = new DemoAdminBundle();
  52. $bundle->setPath($this->tempDirectory);
  53. $kernel = $this->createMock('Symfony\Component\HttpKernel\KernelInterface');
  54. $kernel->expects($this->any())
  55. ->method('getBundles')
  56. ->will($this->returnValue(array($bundle)));
  57. $parameterBag = new ParameterBag();
  58. $this->container = new Container($parameterBag);
  59. $kernel->expects($this->any())
  60. ->method('getBundle')
  61. ->with($this->equalTo('AcmeDemoBundle'))
  62. ->will($this->returnValue($bundle));
  63. $kernel->expects($this->any())
  64. ->method('getContainer')
  65. ->will($this->returnValue($this->container));
  66. $this->application = new Application($kernel);
  67. $this->command = new GenerateAdminCommand();
  68. $this->application->add($this->command);
  69. }
  70. public function tearDown()
  71. {
  72. if ($this->tempDirectory) {
  73. if (file_exists($this->tempDirectory.'/Controller/FooAdminController.php')) {
  74. unlink($this->tempDirectory.'/Controller/FooAdminController.php');
  75. }
  76. if (file_exists($this->tempDirectory.'/Admin/FooAdmin.php')) {
  77. unlink($this->tempDirectory.'/Admin/FooAdmin.php');
  78. }
  79. if (file_exists($this->tempDirectory.'/Resources/config/admin.yml')) {
  80. unlink($this->tempDirectory.'/Resources/config/admin.yml');
  81. }
  82. if (is_dir($this->tempDirectory.'/Controller')) {
  83. rmdir($this->tempDirectory.'/Controller');
  84. }
  85. if (is_dir($this->tempDirectory.'/Admin')) {
  86. rmdir($this->tempDirectory.'/Admin');
  87. }
  88. if (is_dir($this->tempDirectory.'/Resources/config')) {
  89. rmdir($this->tempDirectory.'/Resources/config');
  90. }
  91. if (is_dir($this->tempDirectory.'/Resources')) {
  92. rmdir($this->tempDirectory.'/Resources');
  93. }
  94. if (file_exists($this->tempDirectory) && is_dir($this->tempDirectory)) {
  95. rmdir($this->tempDirectory);
  96. }
  97. }
  98. }
  99. public function testExecute()
  100. {
  101. $this->command->setContainer($this->container);
  102. $this->container->set('sonata.admin.manager.foo', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  103. $command = $this->application->find('sonata:admin:generate');
  104. $commandTester = new CommandTester($command);
  105. $commandTester->execute(array(
  106. 'command' => $command->getName(),
  107. 'model' => 'Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Foo',
  108. '--bundle' => 'AcmeDemoBundle',
  109. '--admin' => 'FooAdmin',
  110. '--controller' => 'FooAdminController',
  111. '--services' => 'admin.yml',
  112. '--id' => 'acme_demo_admin.admin.foo',
  113. ), array('interactive' => false));
  114. $expectedOutput = '';
  115. $expectedOutput .= sprintf('%3$sThe admin class "Sonata\AdminBundle\Tests\Fixtures\Bundle\Admin\FooAdmin" has been generated under the file "%1$s%2$sAdmin%2$sFooAdmin.php".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  116. $expectedOutput .= sprintf('%3$sThe controller class "Sonata\AdminBundle\Tests\Fixtures\Bundle\Controller\FooAdminController" has been generated under the file "%1$s%2$sController%2$sFooAdminController.php".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  117. $expectedOutput .= sprintf('%3$sThe service "acme_demo_admin.admin.foo" has been appended to the file "%1$s%2$sResources%2$sconfig%2$sadmin.yml".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  118. $this->assertSame($expectedOutput, $commandTester->getDisplay());
  119. $this->assertFileExists($this->tempDirectory.'/Admin/FooAdmin.php');
  120. $this->assertFileExists($this->tempDirectory.'/Controller/FooAdminController.php');
  121. $this->assertFileExists($this->tempDirectory.'/Resources/config/admin.yml');
  122. $adminContent = file_get_contents($this->tempDirectory.'/Admin/FooAdmin.php');
  123. $this->assertContains('class FooAdmin extends AbstractAdmin', $adminContent);
  124. $this->assertContains('use Sonata\AdminBundle\Admin\AbstractAdmin;', $adminContent);
  125. $this->assertContains('use Sonata\AdminBundle\Datagrid\DatagridMapper;', $adminContent);
  126. $this->assertContains('use Sonata\AdminBundle\Datagrid\ListMapper;', $adminContent);
  127. $this->assertContains('use Sonata\AdminBundle\Form\FormMapper;', $adminContent);
  128. $this->assertContains('use Sonata\AdminBundle\Show\ShowMapper;', $adminContent);
  129. $this->assertContains('protected function configureDatagridFilters(DatagridMapper $datagridMapper)', $adminContent);
  130. $this->assertContains('protected function configureListFields(ListMapper $listMapper)', $adminContent);
  131. $this->assertContains('protected function configureFormFields(FormMapper $formMapper)', $adminContent);
  132. $this->assertContains('protected function configureShowFields(ShowMapper $showMapper)', $adminContent);
  133. $controllerContent = file_get_contents($this->tempDirectory.'/Controller/FooAdminController.php');
  134. $this->assertContains('class FooAdminController extends CRUDController', $controllerContent);
  135. $this->assertContains('use Sonata\AdminBundle\Controller\CRUDController;', $controllerContent);
  136. $configServiceContent = file_get_contents($this->tempDirectory.'/Resources/config/admin.yml');
  137. $this->assertContains('services:'."\n".' acme_demo_admin.admin.foo', $configServiceContent);
  138. $this->assertContains(' - { name: sonata.admin, manager_type: foo, group: admin, label: Foo }', $configServiceContent);
  139. }
  140. public function testExecuteWithExceptionNoModelManagers()
  141. {
  142. $this->expectException('RuntimeException', 'There are no model managers registered.');
  143. $this->command->setContainer($this->container);
  144. $command = $this->application->find('sonata:admin:generate');
  145. $commandTester = new CommandTester($command);
  146. $commandTester->execute(array(
  147. 'command' => $command->getName(),
  148. 'model' => 'Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Foo',
  149. '--bundle' => 'AcmeDemoBundle',
  150. '--admin' => 'FooAdmin',
  151. '--controller' => 'FooAdminController',
  152. '--services' => 'admin.yml',
  153. '--id' => 'acme_demo_admin.admin.foo',
  154. ), array('interactive' => false));
  155. }
  156. /**
  157. * @dataProvider getExecuteInteractiveTests
  158. */
  159. public function testExecuteInteractive($modelEntity)
  160. {
  161. $this->command->setContainer($this->container);
  162. $this->container->set('sonata.admin.manager.foo', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  163. $this->container->set('sonata.admin.manager.bar', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  164. $command = $this->application->find('sonata:admin:generate');
  165. // NEXT_MAJOR: Remove this BC code for SensioGeneratorBundle 2.3/2.4 after dropping support for Symfony 2.3
  166. // DialogHelper does not exist in SensioGeneratorBundle 2.5+
  167. if (class_exists('Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper')) {
  168. $dialog = $this->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper')
  169. ->setMethods(array('askConfirmation', 'askAndValidate'))
  170. ->getMock();
  171. $dialog->expects($this->any())
  172. ->method('askConfirmation')
  173. ->will($this->returnCallback(function (OutputInterface $output, $question, $default) {
  174. $questionClean = substr($question, 6, strpos($question, '</info>') - 6);
  175. switch ($questionClean) {
  176. case 'Do you want to generate a controller':
  177. return 'yes';
  178. case 'Do you want to update the services YAML configuration file':
  179. return 'yes';
  180. }
  181. return $default;
  182. }));
  183. $dialog->expects($this->any())
  184. ->method('askAndValidate')
  185. ->will($this->returnCallback(function (OutputInterface $output, $question, $validator, $attempts = false, $default = null) use ($modelEntity) {
  186. $questionClean = substr($question, 6, strpos($question, '</info>') - 6);
  187. switch ($questionClean) {
  188. case 'The fully qualified model class':
  189. return $modelEntity;
  190. case 'The bundle name':
  191. return 'AcmeDemoBundle';
  192. case 'The admin class basename':
  193. return 'FooAdmin';
  194. case 'The controller class basename':
  195. return 'FooAdminController';
  196. case 'The services YAML configuration file':
  197. return 'admin.yml';
  198. case 'The admin service ID':
  199. return 'acme_demo_admin.admin.foo';
  200. case 'The manager type':
  201. return 'foo';
  202. }
  203. return $default;
  204. }));
  205. $command->getHelperSet()->set($dialog, 'dialog');
  206. } else {
  207. $questionHelper = $this->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper')
  208. ->setMethods(array('ask'))
  209. ->getMock();
  210. $questionHelper->expects($this->any())
  211. ->method('ask')
  212. ->will($this->returnCallback(function (InputInterface $input, OutputInterface $output, Question $question) use ($modelEntity) {
  213. $questionClean = substr($question->getQuestion(), 6, strpos($question->getQuestion(), '</info>') - 6);
  214. switch ($questionClean) {
  215. // confirmations
  216. case 'Do you want to generate a controller':
  217. return 'yes';
  218. case 'Do you want to update the services YAML configuration file':
  219. return 'yes';
  220. // inputs
  221. case 'The fully qualified model class':
  222. return $modelEntity;
  223. case 'The bundle name':
  224. return 'AcmeDemoBundle';
  225. case 'The admin class basename':
  226. return 'FooAdmin';
  227. case 'The controller class basename':
  228. return 'FooAdminController';
  229. case 'The services YAML configuration file':
  230. return 'admin.yml';
  231. case 'The admin service ID':
  232. return 'acme_demo_admin.admin.foo';
  233. case 'The manager type':
  234. return 'foo';
  235. }
  236. return false;
  237. }));
  238. $command->getHelperSet()->set($questionHelper, 'question');
  239. }
  240. $commandTester = new CommandTester($command);
  241. $commandTester->execute(array(
  242. 'command' => $command->getName(),
  243. 'model' => $modelEntity,
  244. ));
  245. $expectedOutput = PHP_EOL.str_pad('', 41, ' ').PHP_EOL.' Welcome to the Sonata admin generator '.PHP_EOL.str_pad('', 41, ' ').PHP_EOL.PHP_EOL;
  246. $expectedOutput .= sprintf('%3$sThe admin class "Sonata\AdminBundle\Tests\Fixtures\Bundle\Admin\FooAdmin" has been generated under the file "%1$s%2$sAdmin%2$sFooAdmin.php".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  247. $expectedOutput .= sprintf('%3$sThe controller class "Sonata\AdminBundle\Tests\Fixtures\Bundle\Controller\FooAdminController" has been generated under the file "%1$s%2$sController%2$sFooAdminController.php".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  248. $expectedOutput .= sprintf('%3$sThe service "acme_demo_admin.admin.foo" has been appended to the file "%1$s%2$sResources%2$sconfig%2$sadmin.yml".%3$s', $this->tempDirectory, DIRECTORY_SEPARATOR, PHP_EOL);
  249. $this->assertSame($expectedOutput, str_replace("\n", PHP_EOL, str_replace(PHP_EOL, "\n", $commandTester->getDisplay())));
  250. $this->assertFileExists($this->tempDirectory.'/Admin/FooAdmin.php');
  251. $this->assertFileExists($this->tempDirectory.'/Controller/FooAdminController.php');
  252. $this->assertFileExists($this->tempDirectory.'/Resources/config/admin.yml');
  253. $adminContent = file_get_contents($this->tempDirectory.'/Admin/FooAdmin.php');
  254. $this->assertContains('class FooAdmin extends AbstractAdmin', $adminContent);
  255. $this->assertContains('use Sonata\AdminBundle\Admin\AbstractAdmin;', $adminContent);
  256. $this->assertContains('use Sonata\AdminBundle\Datagrid\DatagridMapper;', $adminContent);
  257. $this->assertContains('use Sonata\AdminBundle\Datagrid\ListMapper;', $adminContent);
  258. $this->assertContains('use Sonata\AdminBundle\Form\FormMapper;', $adminContent);
  259. $this->assertContains('use Sonata\AdminBundle\Show\ShowMapper;', $adminContent);
  260. $this->assertContains('protected function configureDatagridFilters(DatagridMapper $datagridMapper)', $adminContent);
  261. $this->assertContains('protected function configureListFields(ListMapper $listMapper)', $adminContent);
  262. $this->assertContains('protected function configureFormFields(FormMapper $formMapper)', $adminContent);
  263. $this->assertContains('protected function configureShowFields(ShowMapper $showMapper)', $adminContent);
  264. $controllerContent = file_get_contents($this->tempDirectory.'/Controller/FooAdminController.php');
  265. $this->assertContains('class FooAdminController extends CRUDController', $controllerContent);
  266. $this->assertContains('use Sonata\AdminBundle\Controller\CRUDController;', $controllerContent);
  267. $configServiceContent = file_get_contents($this->tempDirectory.'/Resources/config/admin.yml');
  268. $this->assertContains('services:'."\n".' acme_demo_admin.admin.foo', $configServiceContent);
  269. $this->assertContains(' - { name: sonata.admin, manager_type: foo, group: admin, label: Foo }', $configServiceContent);
  270. }
  271. public function getExecuteInteractiveTests()
  272. {
  273. return array(
  274. array('Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Foo'),
  275. array('Sonata\AdminBundle\Tests\Fixtures\Entity\Foo'),
  276. );
  277. }
  278. /**
  279. * @dataProvider getValidateManagerTypeTests
  280. */
  281. public function testValidateManagerType($expected, $managerType)
  282. {
  283. $this->command->setContainer($this->container);
  284. $this->container->set('sonata.admin.manager.foo', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  285. $this->container->set('sonata.admin.manager.bar', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  286. $this->assertSame($expected, $this->command->validateManagerType($managerType));
  287. }
  288. public function getValidateManagerTypeTests()
  289. {
  290. return array(
  291. array('foo', 'foo'),
  292. array('bar', 'bar'),
  293. );
  294. }
  295. public function testValidateManagerTypeWithException1()
  296. {
  297. $this->command->setContainer($this->container);
  298. $this->setExpectedException('InvalidArgumentException', 'Invalid manager type "foo". Available manager types are "".');
  299. $this->command->validateManagerType('foo');
  300. }
  301. public function testValidateManagerTypeWithException2()
  302. {
  303. $this->command->setContainer($this->container);
  304. $this->container->set('sonata.admin.manager.foo', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  305. $this->container->set('sonata.admin.manager.bar', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  306. $this->expectException('InvalidArgumentException', 'Invalid manager type "baz". Available manager types are "foo", "bar".');
  307. $this->command->validateManagerType('baz');
  308. }
  309. public function testValidateManagerTypeWithException3()
  310. {
  311. $this->expectException('InvalidArgumentException', 'Invalid manager type "baz". Available manager types are "".');
  312. $this->command->validateManagerType('baz');
  313. }
  314. public function testAnswerUpdateServicesWithNo()
  315. {
  316. $this->container->set('sonata.admin.manager.foo', $this->createMock('Sonata\AdminBundle\Model\ModelManagerInterface'));
  317. $modelEntity = 'Sonata\AdminBundle\Tests\Fixtures\Bundle\Entity\Foo';
  318. $command = $this->application->find('sonata:admin:generate');
  319. // NEXT_MAJOR: Remove this BC code for SensioGeneratorBundle 2.3/2.4 after dropping support for Symfony 2.3
  320. // DialogHelper does not exist in SensioGeneratorBundle 2.5+
  321. if (class_exists('Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper')) {
  322. $dialog = $this->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper')
  323. ->setMethods(array('askConfirmation', 'askAndValidate'))
  324. ->getMock();
  325. $dialog->expects($this->any())
  326. ->method('askConfirmation')
  327. ->will($this->returnCallback(function (OutputInterface $output, $question, $default) {
  328. $questionClean = substr($question, 6, strpos($question, '</info>') - 6);
  329. switch ($questionClean) {
  330. case 'Do you want to generate a controller':
  331. return false;
  332. case 'Do you want to update the services YAML configuration file':
  333. return false;
  334. }
  335. return $default;
  336. }));
  337. $dialog->expects($this->any())
  338. ->method('askAndValidate')
  339. ->will($this->returnCallback(function (OutputInterface $output, $question, $validator, $attempts = false, $default = null) use ($modelEntity) {
  340. $questionClean = substr($question, 6, strpos($question, '</info>') - 6);
  341. switch ($questionClean) {
  342. case 'The fully qualified model class':
  343. return $modelEntity;
  344. case 'The bundle name':
  345. return 'AcmeDemoBundle';
  346. case 'The admin class basename':
  347. return 'FooAdmin';
  348. case 'The controller class basename':
  349. return 'FooAdminController';
  350. case 'The services YAML configuration file':
  351. return 'admin.yml';
  352. case 'The admin service ID':
  353. return 'acme_demo_admin.admin.foo';
  354. case 'The manager type':
  355. return 'foo';
  356. }
  357. return $default;
  358. }));
  359. $command->getHelperSet()->set($dialog, 'dialog');
  360. } else {
  361. $questionHelper = $this->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper')
  362. ->setMethods(array('ask'))
  363. ->getMock();
  364. $questionHelper->expects($this->any())
  365. ->method('ask')
  366. ->will($this->returnCallback(function (InputInterface $input, OutputInterface $output, Question $question) use ($modelEntity) {
  367. $questionClean = substr($question->getQuestion(), 6, strpos($question->getQuestion(), '</info>') - 6);
  368. switch ($questionClean) {
  369. // confirmations
  370. case 'Do you want to generate a controller':
  371. return false;
  372. case 'Do you want to update the services YAML configuration file':
  373. return false;
  374. // inputs
  375. case 'The fully qualified model class':
  376. return $modelEntity;
  377. case 'The bundle name':
  378. return 'AcmeDemoBundle';
  379. case 'The admin class basename':
  380. return 'FooAdmin';
  381. }
  382. return false;
  383. }));
  384. $command->getHelperSet()->set($questionHelper, 'question');
  385. }
  386. $commandTester = new CommandTester($command);
  387. $commandTester->execute(array(
  388. 'command' => $command->getName(),
  389. 'model' => $modelEntity,
  390. ));
  391. $this->assertFalse(file_exists($this->tempDirectory.'/Resources/config/services.yml'));
  392. }
  393. }