Skip to content

Commit

Permalink
[make:registration] tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jrushlow committed Apr 17, 2024
1 parent d33269c commit ea34834
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/Maker/MakeRegistrationForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@
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\Test\WebTestCase;
use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper;
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
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;
Expand Down Expand Up @@ -68,6 +71,8 @@
*/
final class MakeRegistrationForm extends AbstractMaker
{
use CanGenerateTestsTrait;

private string $userClass;
private string $usernameField;
private string $passwordField;
Expand Down Expand Up @@ -104,6 +109,8 @@ public function configureCommand(Command $command, InputConfiguration $inputConf
$command
->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeRegistrationForm.txt'))
;

$this->addWithTestsOption($command);
}

public function interact(InputInterface $input, ConsoleStyle $io, Command $command): void
Expand Down Expand Up @@ -180,6 +187,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<string, mixed> $securityData */
Expand Down Expand Up @@ -400,6 +409,34 @@ 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,
TemplatedEmail::class,
WebTestCase::class,
$userRepoVars['repository_full_class_name'],
]);

$generator->generateFile(
targetPath: sprintf('tests/%s.php', $testClassDetails->getShortName()),
templateName: 'registration/Test.WithVerify.tpl.php',
variables: array_merge([
'use_statements' => $useStatements,
'from_email' => $this->fromEmailAddress,
], $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);
Expand Down
66 changes: 66 additions & 0 deletions src/Resources/skeleton/registration/Test.WithVerify.tpl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?= "<?php\n" ?>
namespace App\Tests;

<?= $use_statements ?>

class RegistrationControllerTest extends WebTestCase
{
public function testRegister(): void
{
$client = static::createClient();

$container = static::getContainer();
$em = $container->get('doctrine.orm.entity_manager');
$userRepository = $container->get(<?= $repository_class_name ?>::class);

foreach ($userRepository->findAll() as $user) {
$em->remove($user);
}

$em->flush();

self::assertCount(0, $userRepository->findAll());

// Register a new user
$client->request('GET', '/register');
self::assertResponseIsSuccessful();

$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('/');
self::assertCount(1, $userRepository->findAll());
self::assertFalse(($user = $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', '<?= $from_email ?>');
self::assertEmailAddressContains($messages[0], 'to', 'me@example.com');
self::assertEmailTextBodyContains($messages[0], 'This link will expire in 1 hour.');

// Login the new user
$client->followRedirect();
$client->loginUser($user);

// Get the verification link from the email
/** @var TemplatedEmail $templatedEmail */
$templatedEmail = $messages[0];
$messageBody = $templatedEmail->getHtmlBody();

preg_match('#(http://localhost/verify/email.+)">#', $messageBody, $resetLink);

// "Click" the link, and see if the user is verified
$client->request('GET', $resetLink[1]);
$client->followRedirect();

self::assertTrue(static::getContainer()->get(UserRepository::class)->findAll()[0]->isVerified());
}
}
44 changes: 44 additions & 0 deletions tests/Maker/MakeRegistrationFormTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,50 @@ public function getTestDetails(): \Generator
$this->runRegistrationTest($runner, 'it_generates_registration_form_with_verification.php');
}),
];

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
Expand Down

0 comments on commit ea34834

Please sign in to comment.