Skip to content

[SecurityBundle] Add tests for debug:firewall command #61334

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

Merged
merged 1 commit into from
Aug 6, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<?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 Symfony\Bundle\SecurityBundle\Tests\Command;

use PHPUnit\Framework\TestCase;
use Symfony\Bundle\SecurityBundle\Command\DebugFirewallCommand;
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;

class DebugFirewallCommandTest extends TestCase
{
public function testFirewallListOutputMatchesFixture()
{
$firewallNames = ['main', 'api'];
$contexts = $this->createMock(ContainerInterface::class);
$eventDispatchers = $this->createMock(ContainerInterface::class);

$command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, []);
$tester = new CommandTester($command);

$this->assertSame(0, $tester->execute([]));
$this->assertStringContainsString('Firewalls', $tester->getDisplay());
$this->assertStringContainsString('The following firewalls are defined:', $tester->getDisplay());
$this->assertStringContainsString('* main', $tester->getDisplay());
$this->assertStringContainsString('* api', $tester->getDisplay());
$this->assertStringContainsString('To view details of a specific firewall', $tester->getDisplay());
}

public function testFirewallNotFoundDisplaysError()
{
$firewallNames = ['main', 'api'];

$contexts = $this->createMock(ContainerInterface::class);
$contexts->method('has')->willReturn(false);

$eventDispatchers = $this->createMock(ContainerInterface::class);
$authenticators = [];

$command = new DebugFirewallCommand(
$firewallNames,
$contexts,
$eventDispatchers,
$authenticators
);

$tester = new CommandTester($command);

$this->assertSame(1, $tester->execute(['name' => 'admin']));
$this->assertStringContainsString('Firewall admin was not found.', $tester->getDisplay());
$this->assertStringContainsString('Available firewalls are: main, api', $tester->getDisplay());
}

public function testFirewallMainOutputMatchesFixture()
{
$firewallNames = ['main'];

$config = new FirewallConfig(
name: 'main',
userChecker: 'user_checker_service',
requestMatcher: null,
securityEnabled: true,
stateless: false,
provider: 'user_provider_service',
context: 'main',
entryPoint: 'entry_point_service',
accessDeniedHandler: 'access_denied_handler_service',
accessDeniedUrl: '/access-denied',
authenticators: [],
switchUser: null
);

$context = new FirewallContext([], config: $config);

$contexts = $this->createMock(ContainerInterface::class);
$contexts->method('has')->willReturn(true);
$contexts->method('get')->willReturn($context);

$eventDispatchers = $this->createMock(ContainerInterface::class);
$authenticator = new DummyAuthenticator();
$authenticators = ['main' => [$authenticator]];

$command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, $authenticators);
$tester = new CommandTester($command);

$this->assertSame(0, $tester->execute(['name' => 'main', '--events' => true]));
$this->assertEquals($this->getFixtureOutput('firewall_main_output.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay())));
}

public function testFirewallWithEventsOutputMatchesFixture()
{
$firewallNames = ['main'];

$config = new FirewallConfig(
name: 'main',
userChecker: 'user_checker_service',
context: 'main',
stateless: false,
provider: 'user_provider_service',
entryPoint: 'entry_point_service',
accessDeniedHandler: 'access_denied_handler_service',
accessDeniedUrl: '/access-denied',
);

$context = new FirewallContext([], config: $config);

$contexts = $this->createMock(ContainerInterface::class);
$contexts->method('has')->willReturn(true);
$contexts->method('get')->willReturn($context);

$dispatcher = $this->createMock(EventDispatcherInterface::class);
$listener = fn () => null;
$listenerTwo = fn (int $number) => $number * 2;
$dispatcher->method('getListeners')->willReturn([
'security.event' => [$listener, $listenerTwo],
]);
$dispatcher->method('getListenerPriority')->willReturn(42);

$eventDispatchers = $this->createMock(ContainerInterface::class);
$eventDispatchers->method('has')->willReturn(true);
$eventDispatchers->method('get')->willReturn($dispatcher);

$authenticator = new DummyAuthenticator();
$authenticatorTwo = new DummyAuthenticator();
$authenticatorThree = new DummyAuthenticator();
$authenticators = ['main' => [$authenticator, $authenticatorTwo], 'api' => [$authenticatorThree]];

$command = new DebugFirewallCommand($firewallNames, $contexts, $eventDispatchers, $authenticators);
$tester = new CommandTester($command);

$this->assertSame(0, $tester->execute(['name' => 'main', '--events' => true]));
$this->assertEquals($this->getFixtureOutput('firewall_main_with_events_output.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay())));
}

public function testFirewallWithSwitchUserDisplaysSection()
{
$firewallNames = ['main'];

$switchUserConfig = [
'parameter' => '_switch_user_test',
'provider' => 'custom_provider_test',
'role' => 'ROLE_ALLOWED_TO_SWITCH',
];

$config = new FirewallConfig(
name: 'main',
userChecker: 'user_checker_service_test',
context: 'main',
stateless: false,
provider: 'user_provider_service_test',
entryPoint: 'entry_point_service_test',
accessDeniedHandler: 'access_denied_handler_service_test',
accessDeniedUrl: '/access-denied-test',
switchUser: $switchUserConfig,
);

$context = new FirewallContext([], config: $config);

$contexts = $this->createMock(ContainerInterface::class);
$contexts->method('has')->willReturn(true);
$contexts->method('get')->willReturn($context);

$eventDispatchers = $this->createMock(ContainerInterface::class);
$authenticator = new DummyAuthenticator();
$authenticatorTwo = $this->createMock(AuthenticatorInterface::class);
$authenticators = ['main' => [$authenticator], 'api' => [$authenticatorTwo]];

$command = new DebugFirewallCommand(
$firewallNames,
$contexts,
$eventDispatchers,
$authenticators
);
$tester = new CommandTester($command);

$this->assertSame(0, $tester->execute(['name' => 'main']));
$this->assertEquals($this->getFixtureOutput('firewall_main_with_switch_user.txt'), trim(str_replace(\PHP_EOL, "\n", $tester->getDisplay())));
}

private function getFixtureOutput(string $file): string
{
return trim(file_get_contents(__DIR__.'/../Fixtures/Descriptor/'.$file));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Firewall "main"
===============

----------------------- -------------------------------
Option Value
----------------------- -------------------------------
Name main
Context main
Lazy No
Stateless No
User Checker user_checker_service
Provider user_provider_service
Entry Point entry_point_service
Access Denied URL /access-denied
Access Denied Handler access_denied_handler_service
----------------------- -------------------------------

Event listeners for firewall "main"
===================================

No event dispatcher has been registered for this firewall.

Authenticators for firewall "main"
==================================

-----------------------------------------------------------------
Classname
-----------------------------------------------------------------
Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator
-----------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Firewall "main"
===============

----------------------- -------------------------------
Option Value
----------------------- -------------------------------
Name main
Context main
Lazy No
Stateless No
User Checker user_checker_service
Provider user_provider_service
Entry Point entry_point_service
Access Denied URL /access-denied
Access Denied Handler access_denied_handler_service
----------------------- -------------------------------

Event listeners for firewall "main"
===================================

"security.event" event
----------------------

------- ----------- ----------
Order Callable Priority
------- ----------- ----------
#1 Closure() 42
#2 Closure() 42
------- ----------- ----------

Authenticators for firewall "main"
==================================

-----------------------------------------------------------------
Classname
-----------------------------------------------------------------
Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator
Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator
-----------------------------------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would inline those outputs and newline at end of file missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks so much for your suggestion! 😊
I believe the change has been made, please let me know if you'd like me to adjust anything else ❤️

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Firewall "main"
===============

----------------------- ------------------------------------
Option Value
----------------------- ------------------------------------
Name main
Context main
Lazy No
Stateless No
User Checker user_checker_service_test
Provider user_provider_service_test
Entry Point entry_point_service_test
Access Denied URL /access-denied-test
Access Denied Handler access_denied_handler_service_test
----------------------- ------------------------------------

User switching
--------------

----------- ------------------------
Option Value
----------- ------------------------
Parameter _switch_user_test
Provider custom_provider_test
User Role ROLE_ALLOWED_TO_SWITCH
----------- ------------------------

Authenticators for firewall "main"
==================================

-----------------------------------------------------------------
Classname
-----------------------------------------------------------------
Symfony\Bundle\SecurityBundle\Tests\Fixtures\DummyAuthenticator
-----------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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 Symfony\Bundle\SecurityBundle\Tests\Fixtures;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;

class DummyAuthenticator implements AuthenticatorInterface
{
public function supports(Request $request): ?bool
{
return null;
}

public function authenticate(Request $request): Passport
{
}

public function createToken(Passport $passport, string $firewallName): TokenInterface
{
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return null;
}

public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return null;
}

public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
}
}
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy