Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use PHPUnit for command and DI tests #252

Merged
merged 1 commit into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.can-fail }}
strategy:
fail-fast: true
fail-fast: false
matrix:
php: [7.1, 7.2, 7.3, 7.4, 8.0]
symfony: [3.4.*, 4.4.*, 5.2.*, 5.3.*]
Expand Down Expand Up @@ -62,5 +62,8 @@ jobs:
env:
SYMFONY_REQUIRE: ${{ matrix.symfony }}

- name: Execute tests
- name: Run phpspec
run: bin/phpspec run -fpretty --verbose

- name: Run PHPUnit
run: bin/phpunit --verbose
61 changes: 61 additions & 0 deletions Tests/Functional/Command/ClearInvalidRefreshTokensCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Gesdinet\JWTRefreshTokenBundle\Tests\Functional\Command;

use Gesdinet\JWTRefreshTokenBundle\Command\ClearInvalidRefreshTokensCommand;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;

final class ClearInvalidRefreshTokensCommandTest extends TestCase
{
public function test_clears_tokens_without_timestamp(): void
{
/** @var MockObject&RefreshTokenInterface $refreshToken */
$refreshToken = $this->createMock(RefreshTokenInterface::class);
$refreshToken->expects($this->once())
->method('getRefreshToken')
->willReturn('refresh-token');

/** @var MockObject&RefreshTokenManagerInterface $refreshTokenManager */
$refreshTokenManager = $this->createMock(RefreshTokenManagerInterface::class);
$refreshTokenManager->expects($this->once())
->method('revokeAllInvalid')
->with($this->isInstanceOf(\DateTimeInterface::class))
->willReturn([$refreshToken]);

$command = new ClearInvalidRefreshTokensCommand($refreshTokenManager);

$commandTester = new CommandTester($command);
$commandTester->execute([]);

$this->assertSame(0, $commandTester->getStatusCode());
$this->assertStringContainsString('Revoke refresh-token', $commandTester->getDisplay());
}

public function test_clears_tokens_with_timestamp(): void
{
/** @var MockObject&RefreshTokenInterface $refreshToken */
$refreshToken = $this->createMock(RefreshTokenInterface::class);
$refreshToken->expects($this->once())
->method('getRefreshToken')
->willReturn('refresh-token');

/** @var MockObject&RefreshTokenManagerInterface $refreshTokenManager */
$refreshTokenManager = $this->createMock(RefreshTokenManagerInterface::class);
$refreshTokenManager->expects($this->once())
->method('revokeAllInvalid')
->with($this->isInstanceOf(\DateTimeInterface::class))
->willReturn([$refreshToken]);

$command = new ClearInvalidRefreshTokensCommand($refreshTokenManager);

$commandTester = new CommandTester($command);
$commandTester->execute(['datetime' => '2021-01-01']);

$this->assertSame(0, $commandTester->getStatusCode());
$this->assertStringContainsString('Revoke refresh-token', $commandTester->getDisplay());
}
}
59 changes: 59 additions & 0 deletions Tests/Functional/Command/RevokeRefreshTokenCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Gesdinet\JWTRefreshTokenBundle\Tests\Functional\Command;

use Gesdinet\JWTRefreshTokenBundle\Command\RevokeRefreshTokenCommand;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;

final class RevokeRefreshTokenCommandTest extends TestCase
{
public function test_does_not_revoke_a_nonexisting_token(): void
{
$token = 'refresh-token';

/** @var MockObject&RefreshTokenManagerInterface $refreshTokenManager */
$refreshTokenManager = $this->createMock(RefreshTokenManagerInterface::class);
$refreshTokenManager->expects($this->once())
->method('get')
->with($token)
->willReturn(null);

$command = new RevokeRefreshTokenCommand($refreshTokenManager);

$commandTester = new CommandTester($command);
$commandTester->execute(['refresh_token' => $token]);

$this->assertSame(-1, $commandTester->getStatusCode());
$this->assertStringContainsString('Not Found:', $commandTester->getDisplay());
}

public function test_revokes_a_token(): void
{
$token = 'refresh-token';

/** @var MockObject&RefreshTokenInterface $refreshToken */
$refreshToken = $this->createMock(RefreshTokenInterface::class);
$refreshToken->expects($this->once())
->method('getRefreshToken')
->willReturn($token);

/** @var MockObject&RefreshTokenManagerInterface $refreshTokenManager */
$refreshTokenManager = $this->createMock(RefreshTokenManagerInterface::class);
$refreshTokenManager->expects($this->once())
->method('get')
->with($token)
->willReturn($refreshToken);

$command = new RevokeRefreshTokenCommand($refreshTokenManager);

$commandTester = new CommandTester($command);
$commandTester->execute(['refresh_token' => $token]);

$this->assertSame(0, $commandTester->getStatusCode());
$this->assertStringContainsString('Revoke refresh-token', $commandTester->getDisplay());
}
}
44 changes: 44 additions & 0 deletions Tests/Functional/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Gesdinet\JWTRefreshTokenBundle\Tests\Functional\DependencyInjection;

use Gesdinet\JWTRefreshTokenBundle\DependencyInjection\Configuration;
use Gesdinet\JWTRefreshTokenBundle\Document\RefreshToken;
use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\Definition\ConfigurationInterface;

final class ConfigurationTest extends TestCase
{
use ConfigurationTestCaseTrait;

protected function getConfiguration(): ConfigurationInterface
{
return new Configuration();
}

public function test_default_configuration_is_valid(): void
{
$this->assertConfigurationIsValid([]);
}

public function test_custom_configuration_is_valid(): void
{
$this->assertConfigurationIsValid([
[
'ttl' => 123,
'ttl_update' => true,
'firewall' => 'main',
'user_provider' => 'my.user_provider',
'user_identity_field' => 'email',
'manager_type' => 'mongodb',
'refresh_token_class' => RefreshToken::class,
'object_manager' => 'doctrine_mongodb.odm.document_manager',
'user_checker' => 'my.user_checker',
'single_use' => true,
'token_parameter_name' => 'the_token',
'doctrine_mappings' => false,
],
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace Gesdinet\JWTRefreshTokenBundle\Tests\Functional\DependencyInjection;

use Gesdinet\JWTRefreshTokenBundle\DependencyInjection\GesdinetJWTRefreshTokenExtension;
use Gesdinet\JWTRefreshTokenBundle\Document\RefreshToken as RefreshTokenDocument;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken as RefreshTokenEntity;
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;

final class GesdinetJWTRefreshTokenExtensionTest extends AbstractExtensionTestCase
{
protected function getContainerExtensions(): array
{
return [
new GesdinetJWTRefreshTokenExtension(),
];
}

public function test_container_is_loaded_with_default_configuration(): void
{
$this->load();

$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.ttl', 2592000);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.ttl_update', false);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.security.firewall', 'api');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.user_provider', null);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.user_identity_field', 'username');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.single_use', false);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.token_parameter_name', 'refresh_token');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.doctrine_mappings', true);

$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.refresh_token.class', RefreshTokenEntity::class);
$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.object_manager.id', 'doctrine.orm.entity_manager');
$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.user_checker.id', 'security.user_checker');
}

public function test_container_is_loaded_with_custom_configuration(): void
{
$this->load([
'ttl' => 123,
'ttl_update' => true,
'firewall' => 'main',
'user_provider' => 'my.user_provider',
'user_identity_field' => 'email',
'manager_type' => 'mongodb',
'refresh_token_class' => RefreshTokenDocument::class,
'object_manager' => 'doctrine_mongodb.odm.document_manager',
'user_checker' => 'my.user_checker',
'single_use' => true,
'token_parameter_name' => 'the_token',
'doctrine_mappings' => false,
]);

$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.ttl', 123);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.ttl_update', true);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.security.firewall', 'main');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.user_provider', 'my.user_provider');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.user_identity_field', 'email');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.single_use', true);
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.token_parameter_name', 'the_token');
$this->assertContainerBuilderHasParameter('gesdinet_jwt_refresh_token.doctrine_mappings', false);

$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.refresh_token.class', RefreshTokenDocument::class);
$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.object_manager.id', 'doctrine_mongodb.odm.document_manager');
$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.user_checker.id', 'my.user_checker');
}

public function test_container_is_loaded_with_deprecated_parameters(): void
{
$this->load([
'manager_type' => 'mongodb',
'refresh_token_entity' => RefreshTokenDocument::class,
'entity_manager' => 'doctrine_mongodb.odm.document_manager',
]);

$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.refresh_token.class', RefreshTokenDocument::class);
$this->assertContainerBuilderHasParameter('gesdinet.jwtrefreshtoken.object_manager.id', 'doctrine_mongodb.odm.document_manager');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Gesdinet\JWTRefreshTokenBundle\Tests\Functional\DependencyInjection\Security\Factory;

use Gesdinet\JWTRefreshTokenBundle\DependencyInjection\Security\Factory\RefreshTokenAuthenticatorFactory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;

final class RefreshTokenAuthenticatorFactoryTest extends TestCase
{
/**
* @var RefreshTokenAuthenticatorFactory
*/
private $factory;

/**
* @var ContainerBuilder
*/
private $container;

public static function setUpBeforeClass(): void
{
if (!interface_exists(RememberMeHandlerInterface::class)) {
self::markTestSkipped('Only applies to Symfony 5.3+');
}
}

protected function setUp(): void
{
$this->factory = new RefreshTokenAuthenticatorFactory();
$this->container = new ContainerBuilder();
}

public function test_authenticator_service_is_created_with_default_configuration(): void
{
$this->factory->createAuthenticator(
$this->container,
'test',
[],
'app.user_provider'
);

$this->assertTrue($this->container->hasDefinition('security.authenticator.refresh_jwt.test'));
$this->assertTrue($this->container->hasDefinition('security.authentication.success_handler.test.refresh_jwt'));
$this->assertTrue($this->container->hasDefinition('security.authentication.failure_handler.test.refresh_jwt'));

/** @var ChildDefinition $successHandler */
$successHandler = $this->container->getDefinition('security.authentication.success_handler.test.refresh_jwt');
$this->assertSame('gesdinet.jwtrefreshtoken.security.authentication.success_handler', $successHandler->getParent());

/** @var ChildDefinition $failureHandler */
$failureHandler = $this->container->getDefinition('security.authentication.failure_handler.test.refresh_jwt');
$this->assertSame('gesdinet.jwtrefreshtoken.security.authentication.failure_handler', $failureHandler->getParent());
}

public function test_authenticator_service_is_created_with_custom_handlers(): void
{
$this->factory->createAuthenticator(
$this->container,
'test',
[
'success_handler' => 'app.security.authentication.success_handler',
'failure_handler' => 'app.security.authentication.failure_handler',
],
'app.user_provider'
);

$this->assertTrue($this->container->hasDefinition('security.authenticator.refresh_jwt.test'));
$this->assertTrue($this->container->hasDefinition('security.authentication.success_handler.test.refresh_jwt'));
$this->assertTrue($this->container->hasDefinition('security.authentication.failure_handler.test.refresh_jwt'));

/** @var ChildDefinition $successHandler */
$successHandler = $this->container->getDefinition('security.authentication.success_handler.test.refresh_jwt');
$this->assertSame('security.authentication.custom_success_handler', $successHandler->getParent());

/** @var Reference $wrappedSuccessHandler */
$wrappedSuccessHandler = $successHandler->getArgument(0);
$this->assertSame('app.security.authentication.success_handler', (string) $wrappedSuccessHandler);

/** @var ChildDefinition $failureHandler */
$failureHandler = $this->container->getDefinition('security.authentication.failure_handler.test.refresh_jwt');
$this->assertSame('security.authentication.custom_failure_handler', $failureHandler->getParent());

/** @var Reference $wrappedFailureHandler */
$wrappedFailureHandler = $failureHandler->getArgument(0);
$this->assertSame('app.security.authentication.failure_handler', (string) $wrappedFailureHandler);
}
}
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"doctrine/mongodb-odm-bundle": "^3.4|^4.0",
"doctrine/persistence": "^1.3.3|^2.0",
"doctrine/orm": "^2.4.8",
"phpspec/phpspec": "^3.0|^4.0|^5.0|^6.0|^7.0"
"matthiasnoback/symfony-dependency-injection-test": "^3.0|^4.0",
"phpspec/phpspec": "^3.0|^4.0|^5.0|^6.0|^7.0",
"phpunit/phpunit": "^7.5|^8.5|^9.5"
},
"conflict": {
"doctrine/persistence": "<1.3.3"
Expand All @@ -45,11 +47,15 @@
"autoload": {
"psr-4": {
"Gesdinet\\JWTRefreshTokenBundle\\": ""
}
},
"exclude-from-classmap": [
"/Tests/"
]
},
"autoload-dev": {
"psr-4": {
"Gesdinet\\JWTRefreshTokenBundle\\spec\\": "spec/"
"Gesdinet\\JWTRefreshTokenBundle\\spec\\": "spec/",
"Gesdinet\\JWTRefreshTokenBundle\\Tests\\": "Tests/"
}
},
"extra" : {
Expand Down
Loading