vendor/symfony/maker-bundle/src/Maker/MakeTest.php line 166

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony MakerBundle package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  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 Symfony\Bundle\MakerBundle\Maker;
  11. use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase as LegacyApiTestCase;
  12. use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
  13. use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
  14. use Symfony\Bundle\FrameworkBundle\Test\WebTestAssertionsTrait;
  15. use Symfony\Bundle\MakerBundle\ConsoleStyle;
  16. use Symfony\Bundle\MakerBundle\DependencyBuilder;
  17. use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
  18. use Symfony\Bundle\MakerBundle\Generator;
  19. use Symfony\Bundle\MakerBundle\InputAwareMakerInterface;
  20. use Symfony\Bundle\MakerBundle\InputConfiguration;
  21. use Symfony\Bundle\MakerBundle\Validator;
  22. use Symfony\Component\BrowserKit\History;
  23. use Symfony\Component\Console\Command\Command;
  24. use Symfony\Component\Console\Input\InputArgument;
  25. use Symfony\Component\Console\Input\InputInterface;
  26. use Symfony\Component\CssSelector\CssSelectorConverter;
  27. use Symfony\Component\Panther\PantherTestCaseTrait;
  28. /**
  29.  * @author Kévin Dunglas <kevin@dunglas.fr>
  30.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  31.  * @author Ryan Weaver <weaverryan@gmail.com>
  32.  */
  33. final class MakeTest extends AbstractMaker implements InputAwareMakerInterface
  34. {
  35.     private const DESCRIPTIONS = [
  36.         'TestCase' => 'basic PHPUnit tests',
  37.         'KernelTestCase' => 'basic tests that have access to Symfony services',
  38.         'WebTestCase' => 'to run browser-like scenarios, but that don\'t execute JavaScript code',
  39.         'ApiTestCase' => 'to run API-oriented scenarios',
  40.         'PantherTestCase' => 'to run e2e scenarios, using a real-browser or HTTP client and a real web server',
  41.     ];
  42.     private const DOCS = [
  43.         'TestCase' => 'https://symfony.com/doc/current/testing.html#unit-tests',
  44.         'KernelTestCase' => 'https://symfony.com/doc/current/testing/database.html#functional-testing-of-a-doctrine-repository',
  45.         'WebTestCase' => 'https://symfony.com/doc/current/testing.html#functional-tests',
  46.         'ApiTestCase' => 'https://api-platform.com/docs/distribution/testing/',
  47.         'PantherTestCase' => 'https://github.com/symfony/panther#testing-usage',
  48.     ];
  49.     public static function getCommandName(): string
  50.     {
  51.         return 'make:test';
  52.     }
  53.     /**
  54.      * @deprecated remove this method when removing make:unit-test and make:functional-test
  55.      */
  56.     public static function getCommandAliases(): iterable
  57.     {
  58.         yield 'make:unit-test';
  59.         yield 'make:functional-test';
  60.     }
  61.     public static function getCommandDescription(): string
  62.     {
  63.         return 'Creates a new test class';
  64.     }
  65.     public function configureCommand(Command $commandInputConfiguration $inputConfig): void
  66.     {
  67.         $typesDesc = [];
  68.         $typesHelp = [];
  69.         foreach (self::DESCRIPTIONS as $type => $desc) {
  70.             $typesDesc[] = sprintf('<fg=yellow>%s</> (%s)'$type$desc);
  71.             $typesHelp[] = sprintf('* <info>%s</info>: %s'$type$desc);
  72.         }
  73.         $command
  74.             ->addArgument('type'InputArgument::OPTIONAL'The type of test: '.implode(', '$typesDesc))
  75.             ->addArgument('name'InputArgument::OPTIONAL'The name of the test class (e.g. <fg=yellow>BlogPostTest</>)')
  76.             ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeTest.txt').implode("\n"$typesHelp));
  77.         $inputConfig->setArgumentAsNonInteractive('name');
  78.         $inputConfig->setArgumentAsNonInteractive('type');
  79.     }
  80.     public function interact(InputInterface $inputConsoleStyle $ioCommand $command): void
  81.     {
  82.         /* @deprecated remove the following block when removing make:unit-test and make:functional-test */
  83.         $this->handleDeprecatedMakerCommands($input$io);
  84.         if (null !== $type $input->getArgument('type')) {
  85.             if (!isset(self::DESCRIPTIONS[$type])) {
  86.                 throw new RuntimeCommandException(sprintf('The test type must be one of "%s", "%s" given.'implode('", "'array_keys(self::DESCRIPTIONS)), $type));
  87.             }
  88.         } else {
  89.             $input->setArgument(
  90.                 'type',
  91.                 $io->choice('Which test type would you like?'self::DESCRIPTIONS)
  92.             );
  93.         }
  94.         if ('ApiTestCase' === $input->getArgument('type') && !class_exists(ApiTestCase::class) && !class_exists(LegacyApiTestCase::class)) {
  95.             $io->warning([
  96.                 'API Platform is required for this test type. Install it with',
  97.                 'composer require api',
  98.             ]);
  99.         }
  100.         if ('PantherTestCase' === $input->getArgument('type') && !trait_exists(PantherTestCaseTrait::class)) {
  101.             $io->warning([
  102.                 'symfony/panther is required for this test type. Install it with',
  103.                 'composer require symfony/panther --dev',
  104.             ]);
  105.         }
  106.         if (null === $input->getArgument('name')) {
  107.             $io->writeln([
  108.                 '',
  109.                 'Choose a class name for your test, like:',
  110.                 ' * <fg=yellow>UtilTest</> (to create tests/UtilTest.php)',
  111.                 ' * <fg=yellow>Service\\UtilTest</> (to create tests/Service/UtilTest.php)',
  112.                 ' * <fg=yellow>\\App\Tests\\Service\\UtilTest</> (to create tests/Service/UtilTest.php)',
  113.             ]);
  114.             $nameArgument $command->getDefinition()->getArgument('name');
  115.             $value $io->ask($nameArgument->getDescription(), $nameArgument->getDefault(), [Validator::class, 'notBlank']);
  116.             $input->setArgument($nameArgument->getName(), $value);
  117.         }
  118.     }
  119.     public function generate(InputInterface $inputConsoleStyle $ioGenerator $generator): void
  120.     {
  121.         $testClassNameDetails $generator->createClassNameDetails(
  122.             $input->getArgument('name'),
  123.             'Tests\\',
  124.             'Test'
  125.         );
  126.         $type $input->getArgument('type');
  127.         $generator->generateClass(
  128.             $testClassNameDetails->getFullName(),
  129.             "test/$type.tpl.php",
  130.             [
  131.                 'web_assertions_are_available' => trait_exists(WebTestAssertionsTrait::class),
  132.                 'use_legacy_container_property' => $this->useLegacyContainerProperty(),
  133.                 'api_test_case_fqcn' => !class_exists(ApiTestCase::class) ? LegacyApiTestCase::class : ApiTestCase::class,
  134.             ]
  135.         );
  136.         $generator->writeChanges();
  137.         $this->writeSuccessMessage($io);
  138.         $io->text([
  139.             'Next: Open your new test class and start customizing it.',
  140.             sprintf('Find the documentation at <fg=yellow>%s</>'self::DOCS[$type]),
  141.         ]);
  142.     }
  143.     public function configureDependencies(DependencyBuilder $dependenciesInputInterface $input null): void
  144.     {
  145.         if (null === $input) {
  146.             return;
  147.         }
  148.         switch ($input->getArgument('type')) {
  149.             case 'WebTestCase':
  150.                 $dependencies->addClassDependency(
  151.                     History::class,
  152.                     'browser-kit',
  153.                     true,
  154.                     true
  155.                 );
  156.                 $dependencies->addClassDependency(
  157.                     CssSelectorConverter::class,
  158.                     'css-selector',
  159.                     true,
  160.                     true
  161.                 );
  162.                 return;
  163.             case 'ApiTestCase':
  164.                 $dependencies->addClassDependency(
  165.                     !class_exists(ApiTestCase::class) ? LegacyApiTestCase::class : ApiTestCase::class,
  166.                     'api',
  167.                     true,
  168.                     false
  169.                 );
  170.                 return;
  171.             case 'PantherTestCase':
  172.                 $dependencies->addClassDependency(
  173.                     PantherTestCaseTrait::class,
  174.                     'panther',
  175.                     true,
  176.                     true
  177.                 );
  178.                 return;
  179.         }
  180.     }
  181.     /**
  182.      * @deprecated
  183.      */
  184.     private function handleDeprecatedMakerCommands(InputInterface $inputConsoleStyle $io): void
  185.     {
  186.         $currentCommand $input->getFirstArgument();
  187.         switch ($currentCommand) {
  188.             case 'make:unit-test':
  189.                 $input->setArgument('type''TestCase');
  190.                 $io->warning('The "make:unit-test" command is deprecated, use "make:test" instead.');
  191.                 break;
  192.             case 'make:functional-test':
  193.                 $input->setArgument('type'trait_exists(PantherTestCaseTrait::class) ? 'WebTestCase' 'PantherTestCase');
  194.                 $io->warning('The "make:functional-test" command is deprecated, use "make:test" instead.');
  195.                 break;
  196.         }
  197.     }
  198.     private function useLegacyContainerProperty(): bool
  199.     {
  200.         // for 5.2 and lower
  201.         return !method_exists(KernelTestCase::class, 'getContainer');
  202.     }
  203. }