125 lines
4.1 KiB
PHP
125 lines
4.1 KiB
PHP
|
<?php
|
||
|
|
||
|
/*
|
||
|
* This file is part of the Symfony package.
|
||
|
*
|
||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||
|
*
|
||
|
* For the full copyright and license information, please view the LICENSE
|
||
|
* file that was distributed with this source code.
|
||
|
*/
|
||
|
|
||
|
namespace App\Tests\Command;
|
||
|
|
||
|
use App\Command\AddUserCommand;
|
||
|
use App\Repository\UserRepository;
|
||
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||
|
use Symfony\Component\Console\Tester\CommandTester;
|
||
|
|
||
|
class AddUserCommandTest extends KernelTestCase
|
||
|
{
|
||
|
private $userData = [
|
||
|
'username' => 'chuck_norris',
|
||
|
'password' => 'foobar',
|
||
|
'email' => 'chuck@norris.com',
|
||
|
'full-name' => 'Chuck Norris',
|
||
|
];
|
||
|
|
||
|
protected function setUp(): void
|
||
|
{
|
||
|
exec('stty 2>&1', $output, $exitcode);
|
||
|
$isSttySupported = 0 === $exitcode;
|
||
|
|
||
|
if ('Windows' === PHP_OS_FAMILY || !$isSttySupported) {
|
||
|
$this->markTestSkipped('`stty` is required to test this command.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dataProvider isAdminDataProvider
|
||
|
*
|
||
|
* This test provides all the arguments required by the command, so the
|
||
|
* command runs non-interactively and it won't ask for any argument.
|
||
|
*/
|
||
|
public function testCreateUserNonInteractive(bool $isAdmin): void
|
||
|
{
|
||
|
$input = $this->userData;
|
||
|
if ($isAdmin) {
|
||
|
$input['--admin'] = 1;
|
||
|
}
|
||
|
$this->executeCommand($input);
|
||
|
|
||
|
$this->assertUserCreated($isAdmin);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dataProvider isAdminDataProvider
|
||
|
*
|
||
|
* This test doesn't provide all the arguments required by the command, so
|
||
|
* the command runs interactively and it will ask for the value of the missing
|
||
|
* arguments.
|
||
|
* See https://symfony.com/doc/current/components/console/helpers/questionhelper.html#testing-a-command-that-expects-input
|
||
|
*/
|
||
|
public function testCreateUserInteractive(bool $isAdmin): void
|
||
|
{
|
||
|
$this->executeCommand(
|
||
|
// these are the arguments (only 1 is passed, the rest are missing)
|
||
|
$isAdmin ? ['--admin' => 1] : [],
|
||
|
// these are the responses given to the questions asked by the command
|
||
|
// to get the value of the missing required arguments
|
||
|
array_values($this->userData)
|
||
|
);
|
||
|
|
||
|
$this->assertUserCreated($isAdmin);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This is used to execute the same test twice: first for normal users
|
||
|
* (isAdmin = false) and then for admin users (isAdmin = true).
|
||
|
*/
|
||
|
public function isAdminDataProvider(): ?\Generator
|
||
|
{
|
||
|
yield [false];
|
||
|
yield [true];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This helper method checks that the user was correctly created and saved
|
||
|
* in the database.
|
||
|
*/
|
||
|
private function assertUserCreated(bool $isAdmin): void
|
||
|
{
|
||
|
$container = self::$container;
|
||
|
|
||
|
/** @var \App\Entity\User $user */
|
||
|
$user = $container->get(UserRepository::class)->findOneByEmail($this->userData['email']);
|
||
|
$this->assertNotNull($user);
|
||
|
|
||
|
$this->assertSame($this->userData['full-name'], $user->getFullName());
|
||
|
$this->assertSame($this->userData['username'], $user->getUsername());
|
||
|
$this->assertTrue($container->get('security.password_encoder')->isPasswordValid($user, $this->userData['password']));
|
||
|
$this->assertSame($isAdmin ? ['ROLE_ADMIN'] : ['ROLE_USER'], $user->getRoles());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This helper method abstracts the boilerplate code needed to test the
|
||
|
* execution of a command.
|
||
|
*
|
||
|
* @param array $arguments All the arguments passed when executing the command
|
||
|
* @param array $inputs The (optional) answers given to the command when it asks for the value of the missing arguments
|
||
|
*/
|
||
|
private function executeCommand(array $arguments, array $inputs = []): void
|
||
|
{
|
||
|
self::bootKernel();
|
||
|
|
||
|
// this uses a special testing container that allows you to fetch private services
|
||
|
$command = self::$container->get(AddUserCommand::class);
|
||
|
$command->setApplication(new Application(self::$kernel));
|
||
|
|
||
|
$commandTester = new CommandTester($command);
|
||
|
$commandTester->setInputs($inputs);
|
||
|
$commandTester->execute($arguments);
|
||
|
}
|
||
|
}
|