diff --git a/src/Maker/Common/CanGenerateTestsTrait.php b/src/Maker/Common/CanGenerateTestsTrait.php new file mode 100644 index 000000000..18d7566af --- /dev/null +++ b/src/Maker/Common/CanGenerateTestsTrait.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\MakerBundle\Maker\Common; + +use Symfony\Bundle\MakerBundle\ConsoleStyle; +use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; + +/** + * @author Jesse Rushlow + * + * @internal + */ +trait CanGenerateTestsTrait +{ + private bool $generateTests = false; + + public function configureCommandWithTestsOption(Command $command): Command + { + $testsHelp = file_get_contents(\dirname(__DIR__, 2).'/Resources/help/_WithTests.txt'); + $help = $command->getHelp()."\n".$testsHelp; + + $command + ->addOption(name: 'with-tests', mode: InputOption::VALUE_NONE, description: 'Generate PHPUnit Tests') + ->setHelp($help) + ; + + return $command; + } + + public function interactSetGenerateTests(InputInterface $input, ConsoleStyle $io): void + { + // Sanity check for maker dev's - End user should never see this. + if (!$input->hasOption('with-tests')) { + throw new RuntimeCommandException('Whoops! "--with-tests" option does not exist. Call "addWithTestsOptions()" in the makers "configureCommand().'); + } + + $this->generateTests = $input->getOption('with-tests'); + + if (!$this->generateTests) { + $this->generateTests = $io->confirm('Do you want to generate PHPUnit tests? [Experimental]', false); + } + } + + public function shouldGenerateTests(): bool + { + return $this->generateTests; + } +} diff --git a/src/Maker/MakeCrud.php b/src/Maker/MakeCrud.php index 0a5d2d4a1..c20487b39 100644 --- a/src/Maker/MakeCrud.php +++ b/src/Maker/MakeCrud.php @@ -24,6 +24,7 @@ use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper; use Symfony\Bundle\MakerBundle\Generator; use Symfony\Bundle\MakerBundle\InputConfiguration; +use Symfony\Bundle\MakerBundle\Maker\Common\CanGenerateTestsTrait; use Symfony\Bundle\MakerBundle\Renderer\FormTypeRenderer; use Symfony\Bundle\MakerBundle\Str; use Symfony\Bundle\MakerBundle\Util\UseStatementGenerator; @@ -45,6 +46,8 @@ */ final class MakeCrud extends AbstractMaker { + use CanGenerateTestsTrait; + private Inflector $inflector; private string $controllerClassName; private bool $generateTests = false; @@ -72,6 +75,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf ; $inputConfig->setArgumentAsNonInteractive('entity-class'); + $this->configureCommandWithTestsOption($command); } public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void @@ -96,7 +100,7 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma $defaultControllerClass ); - $this->generateTests = $io->confirm('Do you want to generate tests for the controller? [Experimental]', false); + $this->interactSetGenerateTests($input, $io); } public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void @@ -237,7 +241,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen ); } - if ($this->generateTests) { + if ($this->shouldGenerateTests()) { $testClassDetails = $generator->createClassNameDetails( $entityClassDetails->getRelativeNameWithoutSuffix(), 'Test\\Controller\\', diff --git a/src/Maker/MakeRegistrationForm.php b/src/Maker/MakeRegistrationForm.php index 4f937318b..dbd30a01c 100644 --- a/src/Maker/MakeRegistrationForm.php +++ b/src/Maker/MakeRegistrationForm.php @@ -12,11 +12,14 @@ namespace Symfony\Bundle\MakerBundle\Maker; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; +use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\Column; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\MakerBundle\ConsoleStyle; use Symfony\Bundle\MakerBundle\DependencyBuilder; use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper; @@ -24,6 +27,7 @@ use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Generator; use Symfony\Bundle\MakerBundle\InputConfiguration; +use Symfony\Bundle\MakerBundle\Maker\Common\CanGenerateTestsTrait; use Symfony\Bundle\MakerBundle\Renderer\FormTypeRenderer; use Symfony\Bundle\MakerBundle\Security\InteractiveSecurityHelper; use Symfony\Bundle\MakerBundle\Security\Model\Authenticator; @@ -68,6 +72,8 @@ */ final class MakeRegistrationForm extends AbstractMaker { + use CanGenerateTestsTrait; + private string $userClass; private string $usernameField; private string $passwordField; @@ -104,6 +110,8 @@ public function configureCommand(Command $command, InputConfiguration $inputConf $command ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeRegistrationForm.txt')) ; + + $this->configureCommandWithTestsOption($command); } public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void @@ -180,6 +188,8 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma $routeNames = array_keys($this->router->getRouteCollection()->all()); $this->redirectRouteName = $io->choice('What route should the user be redirected to after registration?', $routeNames); } + + $this->interactSetGenerateTests($input, $io); } /** @param array $securityData */ @@ -403,6 +413,35 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen $this->fileManager->dumpFile($classDetails->getPath(), $userManipulator->getSourceCode()); } + // Generate PHPUnit Tests + if ($this->shouldGenerateTests()) { + $testClassDetails = $generator->createClassNameDetails( + 'RegistrationControllerTest', + 'Test\\' + ); + + $useStatements = new UseStatementGenerator([ + EntityManager::class, + KernelBrowser::class, + TemplatedEmail::class, + WebTestCase::class, + $userRepoVars['repository_full_class_name'], + ]); + + $generator->generateFile( + targetPath: sprintf('tests/%s.php', $testClassDetails->getShortName()), + templateName: $this->willVerifyEmail ? 'registration/Test.WithVerify.tpl.php' : 'registration/Test.WithoutVerify.tpl.php', + variables: array_merge([ + 'use_statements' => $useStatements, + 'from_email' => $this->fromEmailAddress ?? null, + ], $userRepoVars) + ); + + if (!class_exists(WebTestCase::class)) { + $io->caution('You\'ll need to install the `symfony/test-pack` to execute the tests for your new controller.'); + } + } + $generator->writeChanges(); $this->writeSuccessMessage($io); diff --git a/src/Maker/MakeResetPassword.php b/src/Maker/MakeResetPassword.php index d6a845e2e..5af4878fc 100644 --- a/src/Maker/MakeResetPassword.php +++ b/src/Maker/MakeResetPassword.php @@ -16,6 +16,8 @@ use Symfony\Bridge\Twig\AppVariable; use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\MakerBundle\ConsoleStyle; use Symfony\Bundle\MakerBundle\DependencyBuilder; use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper; @@ -26,6 +28,7 @@ use Symfony\Bundle\MakerBundle\FileManager; use Symfony\Bundle\MakerBundle\Generator; use Symfony\Bundle\MakerBundle\InputConfiguration; +use Symfony\Bundle\MakerBundle\Maker\Common\CanGenerateTestsTrait; use Symfony\Bundle\MakerBundle\Maker\Common\UidTrait; use Symfony\Bundle\MakerBundle\Security\InteractiveSecurityHelper; use Symfony\Bundle\MakerBundle\Util\ClassNameDetails; @@ -51,6 +54,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Routing\Route as RouteObject; +use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Translation\Translator; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; @@ -81,11 +86,13 @@ */ class MakeResetPassword extends AbstractMaker { + use CanGenerateTestsTrait; use UidTrait; private string $fromEmailAddress; private string $fromEmailName; private string $controllerResetSuccessRedirect; + private ?RouteObject $controllerResetSuccessRoute = null; private string $userClass; private string $emailPropertyName; private string $emailGetterMethodName; @@ -95,6 +102,7 @@ public function __construct( private FileManager $fileManager, private DoctrineHelper $doctrineHelper, private EntityClassGenerator $entityClassGenerator, + private ?RouterInterface $router = null, ) { } @@ -115,6 +123,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf ; $this->addWithUuidOption($command); + $this->configureCommandWithTestsOption($command); } public function configureDependencies(DependencyBuilder $dependencies): void @@ -172,6 +181,10 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma Validator::notBlank(...) ); + if ($this->router instanceof RouterInterface) { + $this->controllerResetSuccessRoute = $this->router->getRouteCollection()->get($this->controllerResetSuccessRedirect); + } + $io->section('- Email -'); $emailText[] = 'These are used to generate the email code. Don\'t worry, you can change them in the code later!'; $io->text($emailText); @@ -187,6 +200,8 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma null, Validator::notBlank(...) ); + + $this->interactSetGenerateTests($input, $io); } public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void @@ -334,6 +349,44 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen 'resetPassword/twig_reset.tpl.php' ); + // Generate PHPUnit tests + if ($this->shouldGenerateTests()) { + $testClassDetails = $generator->createClassNameDetails( + 'ResetPasswordControllerTest', + 'Test\\', + ); + + $userRepositoryDetails = $generator->createClassNameDetails( + sprintf('%sRepository', $userClassNameDetails->getShortName()), + 'Repository\\' + ); + + $useStatements = new UseStatementGenerator([ + $userClassNameDetails->getFullName(), + $userRepositoryDetails->getFullName(), + EntityManagerInterface::class, + KernelBrowser::class, + WebTestCase::class, + UserPasswordHasherInterface::class, + ]); + + $generator->generateFile( + targetPath: sprintf('tests/%s.php', $testClassDetails->getShortName()), + templateName: 'resetPassword/Test.ResetPasswordController.tpl.php', + variables: [ + 'use_statements' => $useStatements, + 'user_short_name' => $userClassNameDetails->getShortName(), + 'user_repo_short_name' => $userRepositoryDetails->getShortName(), + 'success_route_path' => null !== $this->controllerResetSuccessRoute ? $this->controllerResetSuccessRoute->getPath() : '/', + 'from_email' => $this->fromEmailAddress, + ], + ); + + if (!class_exists(WebTestCase::class)) { + $io->caution('You\'ll need to install the `symfony/test-pack` to execute the tests for your new controller.'); + } + } + $generator->writeChanges(); $this->writeSuccessMessage($io); diff --git a/src/Resources/config/makers.xml b/src/Resources/config/makers.xml index 7062f826e..02c635941 100644 --- a/src/Resources/config/makers.xml +++ b/src/Resources/config/makers.xml @@ -89,6 +89,7 @@ + diff --git a/src/Resources/help/_WithTests.txt b/src/Resources/help/_WithTests.txt new file mode 100644 index 000000000..7430a6478 --- /dev/null +++ b/src/Resources/help/_WithTests.txt @@ -0,0 +1,6 @@ +To generate tailored PHPUnit tests, simply call: + +php %command.full_name% --with-tests + +This will generate a unit test in tests/ for you to review then use +to test the new functionality of your app. diff --git a/src/Resources/skeleton/registration/Test.WithVerify.tpl.php b/src/Resources/skeleton/registration/Test.WithVerify.tpl.php new file mode 100644 index 000000000..1b911c432 --- /dev/null +++ b/src/Resources/skeleton/registration/Test.WithVerify.tpl.php @@ -0,0 +1,75 @@ + +namespace App\Tests; + + + +class RegistrationControllerTest extends WebTestCase +{ + private KernelBrowser $client; + private $userRepository; + + protected function setUp(): void + { + $this->client = static::createClient(); + + // Ensure we have a clean database + $container = static::getContainer(); + + /** @var EntityManager $em */ + $em = $container->get('doctrine')->getManager(); + $this->userRepository = $container->get(::class); + + foreach ($this->userRepository->findAll() as $user) { + $em->remove($user); + } + + $em->flush(); + } + + public function testRegister(): void + { + // Register a new user + $this->client->request('GET', '/register'); + self::assertResponseIsSuccessful(); + self::assertPageTitleContains('Register'); + + $this->client->submitForm('Register', [ + 'registration_form[email]' => 'me@example.com', + 'registration_form[plainPassword]' => 'password', + 'registration_form[agreeTerms]' => true, + ]); + + // Ensure the response redirects after submitting the form, the user exists, and is not verified + // self::assertResponseRedirects('/'); @TODO: set the appropriate path that the user is redirected to. + self::assertCount(1, $this->userRepository->findAll()); + self::assertFalse(($user = $this->userRepository->findAll()[0])->isVerified()); + + // Ensure the verification email was sent + // Use either assertQueuedEmailCount() || assertEmailCount() depending on your mailer setup + // self::assertQueuedEmailCount(1); + self::assertEmailCount(1); + + self::assertCount(1, $messages = $this->getMailerMessages()); + self::assertEmailAddressContains($messages[0], 'from', ''); + self::assertEmailAddressContains($messages[0], 'to', 'me@example.com'); + self::assertEmailTextBodyContains($messages[0], 'This link will expire in 1 hour.'); + + // Login the new user + $this->client->followRedirect(); + $this->client->loginUser($user); + + // Get the verification link from the email + /** @var TemplatedEmail $templatedEmail */ + $templatedEmail = $messages[0]; + $messageBody = $templatedEmail->getHtmlBody(); + self::assertIsString($messageBody); + + preg_match('#(http://localhost/verify/email.+)">#', $messageBody, $resetLink); + + // "Click" the link and see if the user is verified + $this->client->request('GET', $resetLink[1]); + $this->client->followRedirect(); + + self::assertTrue(static::getContainer()->get(::class)->findAll()[0]->isVerified()); + } +} diff --git a/src/Resources/skeleton/registration/Test.WithoutVerify.tpl.php b/src/Resources/skeleton/registration/Test.WithoutVerify.tpl.php new file mode 100644 index 000000000..9b9477805 --- /dev/null +++ b/src/Resources/skeleton/registration/Test.WithoutVerify.tpl.php @@ -0,0 +1,46 @@ + +namespace App\Tests; + + + +class RegistrationControllerTest extends WebTestCase +{ + private KernelBrowser $client; + private $userRepository; + + protected function setUp(): void + { + $this->client = static::createClient(); + + // Ensure we have a clean database + $container = static::getContainer(); + + /** @var EntityManager $em */ + $em = $container->get('doctrine')->getManager(); + $this->userRepository = $container->get(::class); + + foreach ($this->userRepository->findAll() as $user) { + $em->remove($user); + } + + $em->flush(); + } + + public function testRegister(): void + { + // Register a new user + $this->client->request('GET', '/register'); + self::assertResponseIsSuccessful(); + self::assertPageTitleContains('Register'); + + $this->client->submitForm('Register', [ + 'registration_form[email]' => 'me@example.com', + 'registration_form[plainPassword]' => 'password', + 'registration_form[agreeTerms]' => true, + ]); + + // Ensure the response redirects after submitting the form, the user exists, and is not verified + // self::assertResponseRedirects('/'); @TODO: set the appropriate path that the user is redirected to. + self::assertCount(1, $this->userRepository->findAll()); + } +} diff --git a/src/Resources/skeleton/resetPassword/Test.ResetPasswordController.tpl.php b/src/Resources/skeleton/resetPassword/Test.ResetPasswordController.tpl.php new file mode 100644 index 000000000..e4ea1575f --- /dev/null +++ b/src/Resources/skeleton/resetPassword/Test.ResetPasswordController.tpl.php @@ -0,0 +1,98 @@ + +namespace App\Tests; + + + +class ResetPasswordTest extends WebTestCase +{ + private KernelBrowser $client; + private EntityManagerInterface $em; + private $userRepository; + + protected function setUp(): void + { + $this->client = static::createClient(); + + // Ensure we have a clean database + $container = static::getContainer(); + + /** @var EntityManagerInterface $em */ + $em = $container->get('doctrine')->getManager(); + $this->em = $em; + + $this->userRepository = $container->get(::class); + + foreach ($this->userRepository->findAll() as $user) { + $this->em->remove($user); + } + + $this->em->flush(); + } + + public function testResetPasswordController(): void + { + // Create a test user + $user = (new ()) + ->setEmail('me@example.com') + ->setPassword('a-test-password-that-will-be-changed-later') + ; + $this->em->persist($user); + $this->em->flush(); + + // Test Request reset password page + $this->client->request('GET', '/reset-password'); + + self::assertResponseIsSuccessful(); + self::assertPageTitleContains('Reset your password'); + + // Submit the reset password form and test email message is queued / sent + $this->client->submitForm('Send password reset email', [ + 'reset_password_request_form[email]' => 'me@example.com', + ]); + + // Ensure the reset password email was sent + // Use either assertQueuedEmailCount() || assertEmailCount() depending on your mailer setup + // self::assertQueuedEmailCount(1); + self::assertEmailCount(1); + + self::assertCount(1, $messages = $this->getMailerMessages()); + + self::assertEmailAddressContains($messages[0], 'from', ''); + self::assertEmailAddressContains($messages[0], 'to', 'me@example.com'); + self::assertEmailTextBodyContains($messages[0], 'This link will expire in 1 hour.'); + + self::assertResponseRedirects('/reset-password/check-email'); + + // Test check email landing page shows correct "expires at" time + $crawler = $this->client->followRedirect(); + + self::assertPageTitleContains('Password Reset Email Sent'); + self::assertStringContainsString('This link will expire in 1 hour', $crawler->html()); + + // Test the link sent in the email is valid + $email = $messages[0]->toString(); + preg_match('#(/reset-password/reset/[a-zA-Z0-9]+)#', $email, $resetLink); + + $this->client->request('GET', $resetLink[1]); + + self::assertResponseRedirects('/reset-password/reset'); + + $this->client->followRedirect(); + + // Test we can set a new password + $this->client->submitForm('Reset password', [ + 'change_password_form[plainPassword][first]' => 'newStrongPassword', + 'change_password_form[plainPassword][second]' => 'newStrongPassword', + ]); + + self::assertResponseRedirects(''); + + $user = $this->userRepository->findOneBy(['email' => 'me@example.com']); + + self::assertInstanceOf(::class, $user); + + /** @var UserPasswordHasherInterface $passwordHasher */ + $passwordHasher = static::getContainer()->get(UserPasswordHasherInterface::class); + self::assertTrue($passwordHasher->isPasswordValid($user, 'newStrongPassword')); + } +} diff --git a/tests/Maker/MakeRegistrationFormTest.php b/tests/Maker/MakeRegistrationFormTest.php index 939063348..3da7a3ebb 100644 --- a/tests/Maker/MakeRegistrationFormTest.php +++ b/tests/Maker/MakeRegistrationFormTest.php @@ -229,6 +229,89 @@ public function getTestDetails(): \Generator $this->runRegistrationTest($runner, 'it_generates_registration_form_with_verification.php'); }), ]; + + yield 'it_generates_registration_form_with_tests' => [$this->createRegistrationFormTest() + ->run(function (MakerTestRunner $runner) { + $this->makeUser($runner); + + $output = $runner->runMaker([ + 'n', // add UniqueEntity + 'n', // verify user + 'n', // automatically authenticate after registration + 'app_anonymous', // route number to redirect to + 'y', // Generate tests + ]); + + $this->assertStringContainsString('Success', $output); + $this->assertFileExists($runner->getPath('tests/RegistrationControllerTest.php')); + + $runner->configureDatabase(); + $runner->runTests(); + }), + ]; + + yield 'it_generates_registration_form_with_tests_using_flag' => [$this->createRegistrationFormTest() + ->run(function (MakerTestRunner $runner) { + $this->makeUser($runner); + + $output = $runner->runMaker([ + 'n', // add UniqueEntity + 'n', // verify user + 'n', // automatically authenticate after registration + 'app_anonymous', // route number to redirect to + ], '--with-tests'); + + $this->assertStringContainsString('Success', $output); + $this->assertFileExists($runner->getPath('tests/RegistrationControllerTest.php')); + + $runner->configureDatabase(); + $runner->runTests(); + }), + ]; + + yield 'it_generates_registration_form_with_verification_and_with_tests' => [$this->createRegistrationFormTest() + ->addExtraDependencies('symfonycasts/verify-email-bundle') + // needed for internal functional test + ->addExtraDependencies('symfony/web-profiler-bundle', 'mailer') + ->run(function (MakerTestRunner $runner) { + $runner->writeFile( + 'config/packages/mailer.yaml', + Yaml::dump(['framework' => [ + 'mailer' => ['dsn' => 'null://null'], + ]]) + ); + + $this->makeUser($runner); + + $output = $runner->runMaker([ + 'n', // add UniqueEntity + 'y', // verify user + 'y', // require authentication to verify user email + 'jr@rushlow.dev', // from email address + 'SymfonyCasts', // From Name + 'n', // no authenticate after + 'app_anonymous', // route number to redirect to + 'y', // Generate tests + ]); + + $this->assertStringContainsString('Success', $output); + + $generatedFiles = [ + 'src/Security/EmailVerifier.php', + 'templates/registration/confirmation_email.html.twig', + 'tests/RegistrationControllerTest.php', + ]; + + foreach ($generatedFiles as $file) { + $this->assertFileExists($runner->getPath($file)); + } + + $runner->runConsole('cache:clear', [], '--env=test'); + + $runner->configureDatabase(); + $runner->runTests(); + }), + ]; } private function makeUser(MakerTestRunner $runner, string $identifier = 'email'): void diff --git a/tests/Maker/MakeResetPasswordTest.php b/tests/Maker/MakeResetPasswordTest.php index ac0825369..7b137ceb2 100644 --- a/tests/Maker/MakeResetPasswordTest.php +++ b/tests/Maker/MakeResetPasswordTest.php @@ -82,6 +82,54 @@ public function getTestDetails(): \Generator }), ]; + yield 'it_generates_tests' => [$this->createMakerTest() + // Needed to assertEmails && NotCompromisedPassword + ->addExtraDependencies('symfony/mailer', 'symfony/http-client') + // @legacy - drop skipped versions when PHP 8.1 is no longer supported. + ->setSkippedPhpVersions(80100, 80109) + ->preRun(function (MakerTestRunner $runner) { + $runner->copy( + 'make-reset-password/src/Controller/FixtureController.php', + 'src/Controller/FixtureController.php' + ); + }) + ->run(function (MakerTestRunner $runner) { + $this->makeUser($runner); + + $output = $runner->runMaker([ + 'app_home', + 'jr@rushlow.dev', + 'SymfonyCasts', + 'y', + ]); + + $this->assertStringContainsString('Success', $output); + + $generatedFiles = [ + 'tests/ResetPasswordControllerTest.php', + ]; + + foreach ($generatedFiles as $file) { + $this->assertFileExists($runner->getPath($file)); + } + + $runner->writeFile( + 'config/packages/mailer.yaml', + Yaml::dump(['framework' => [ + 'mailer' => ['dsn' => 'null://null'], + ]]) + ); + + $runner->copy( + 'make-reset-password/tests/it_generates_with_normal_setup.php', + 'tests/ResetPasswordFunctionalTest.php' + ); + + $runner->configureDatabase(); + $runner->runTests(); + }), + ]; + yield 'it_generates_with_uuid' => [$this->createMakerTest() ->setSkippedPhpVersions(80100, 80109) ->addExtraDependencies('symfony/uid') diff --git a/tests/fixtures/make-reset-password/src/Controller/FixtureController.php b/tests/fixtures/make-reset-password/src/Controller/FixtureController.php new file mode 100644 index 000000000..9445c0f51 --- /dev/null +++ b/tests/fixtures/make-reset-password/src/Controller/FixtureController.php @@ -0,0 +1,16 @@ +json(['message' => 'success']); + } +}