Skip to content

Commit 59f9ca7

Browse files
feat: support Symfony 8.1+ runCommand via conditional class aliasing (#676)
* feat: support Symfony 8.1+ runCommand via conditional class aliasing - Created LegacyWebTestCase and ModernWebTestCase to house version-compatible runCommand signatures. - Configured dynamic class aliasing in WebTestCase - Added active instance tracking to WebTestCase to support static context delegation. - Updated command tests to support both CommandTester and ExecutionResult. --------- Co-authored-by: Gemini 3.5 Flash <218195315+gemini-cli@users.noreply.github.com>
1 parent 7b456ec commit 59f9ca7

5 files changed

Lines changed: 188 additions & 70 deletions

File tree

src/Test/LegacyWebTestCase.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Liip/FunctionalTestBundle
7+
*
8+
* (c) Lukas Kahwe Smith <smith@pooteeweet.org>
9+
*
10+
* This source file is subject to the MIT license that is bundled
11+
* with this source code in the file LICENSE.
12+
*/
13+
14+
namespace Liip\FunctionalTestBundle\Test;
15+
16+
use Symfony\Bundle\FrameworkBundle\Console\Application;
17+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as SymfonyWebTestCase;
18+
use Symfony\Component\Console\Tester\CommandTester;
19+
20+
abstract class LegacyWebTestCase extends SymfonyWebTestCase
21+
{
22+
/**
23+
* Runs a command and returns a CommandTester.
24+
*/
25+
protected function runCommand(string $name, array $params = [], bool $reuseKernel = false): CommandTester
26+
{
27+
if (!$reuseKernel) {
28+
if (null !== static::$kernel) {
29+
static::ensureKernelShutdown();
30+
}
31+
32+
$kernel = static::$kernel = static::createKernel(['environment' => $this->environment ?? static::$env]);
33+
$kernel->boot();
34+
} else {
35+
$kernel = $this->getContainer()->get('kernel');
36+
}
37+
38+
$application = new Application($kernel);
39+
40+
$options = [
41+
'interactive' => false,
42+
'decorated' => $this->getDecorated(),
43+
'verbosity' => $this->getVerbosityLevel(),
44+
];
45+
46+
$command = $application->find($name);
47+
$commandTester = new CommandTester($command);
48+
49+
if (null !== $inputs = $this->getInputs()) {
50+
$commandTester->setInputs($inputs);
51+
$options['interactive'] = true;
52+
$this->inputs = null;
53+
}
54+
55+
$commandTester->execute(
56+
array_merge(['command' => $command->getName()], $params),
57+
$options
58+
);
59+
60+
return $commandTester;
61+
}
62+
}

src/Test/ModernWebTestCase.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Liip/FunctionalTestBundle
7+
*
8+
* (c) Lukas Kahwe Smith <smith@pooteeweet.org>
9+
*
10+
* This source file is subject to the MIT license that is bundled
11+
* with this source code in the file LICENSE.
12+
*/
13+
14+
namespace Liip\FunctionalTestBundle\Test;
15+
16+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as SymfonyWebTestCase;
17+
use Symfony\Component\Console\Tester\ExecutionResult;
18+
19+
abstract class ModernWebTestCase extends SymfonyWebTestCase
20+
{
21+
/**
22+
* Runs a console command and returns the execution result.
23+
*/
24+
public static function runCommand(
25+
string $name,
26+
array $input = [],
27+
mixed $interactiveInputs = [],
28+
?bool $interactive = null,
29+
?bool $decorated = null,
30+
?int $verbosity = null,
31+
array $normalizers = []
32+
): ExecutionResult {
33+
if (\is_bool($interactiveInputs)) {
34+
$reuseKernel = $interactiveInputs;
35+
if (!$reuseKernel) {
36+
static::ensureKernelShutdown();
37+
}
38+
$interactiveInputs = [];
39+
}
40+
41+
// Retrieve properties from the active test instance if not explicitly provided
42+
if (null === $decorated && WebTestCase::$activeInstance) {
43+
$decorated = WebTestCase::$activeInstance->getDecorated();
44+
}
45+
if (null === $verbosity && WebTestCase::$activeInstance) {
46+
$verbosity = WebTestCase::$activeInstance->getVerbosityLevel();
47+
}
48+
if (empty($interactiveInputs) && WebTestCase::$activeInstance) {
49+
$interactiveInputs = WebTestCase::$activeInstance->getInputs() ?? [];
50+
WebTestCase::$activeInstance->inputs = null;
51+
}
52+
53+
return parent::runCommand($name, $input, $interactiveInputs, $interactive, $decorated, $verbosity, $normalizers);
54+
}
55+
}

src/Test/WebTestCase.php

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@
1616
use Liip\FunctionalTestBundle\Utils\HttpAssertions;
1717
use PHPUnit\Framework\MockObject\MockBuilder;
1818
use Symfony\Bundle\FrameworkBundle\Client;
19-
use Symfony\Bundle\FrameworkBundle\Console\Application;
2019
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
21-
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase;
2220
use Symfony\Component\BrowserKit\Cookie;
23-
use Symfony\Component\Console\Tester\CommandTester;
2421
use Symfony\Component\DependencyInjection\ContainerInterface;
2522
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
2623
use Symfony\Component\DomCrawler\Crawler;
@@ -40,6 +37,16 @@
4037
class_alias(KernelBrowser::class, Client::class);
4138
}
4239

40+
if (!method_exists(\Symfony\Bundle\FrameworkBundle\Test\WebTestCase::class, 'runCommand')) {
41+
if (!class_exists(BaseWebTestCase::class, false)) {
42+
class_alias(LegacyWebTestCase::class, BaseWebTestCase::class);
43+
}
44+
} else {
45+
if (!class_exists(BaseWebTestCase::class, false)) {
46+
class_alias(ModernWebTestCase::class, BaseWebTestCase::class);
47+
}
48+
}
49+
4350
/**
4451
* @author Lea Haensenberger
4552
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
@@ -51,6 +58,8 @@ class_alias(KernelBrowser::class, Client::class);
5158
*/
5259
abstract class WebTestCase extends BaseWebTestCase
5360
{
61+
public static ?self $activeInstance = null;
62+
5463
protected static $env = 'test';
5564

5665
protected $containers;
@@ -66,7 +75,7 @@ abstract class WebTestCase extends BaseWebTestCase
6675
/**
6776
* @var array|null
6877
*/
69-
private $inputs;
78+
protected $inputs;
7079

7180
/**
7281
* @var array
@@ -103,47 +112,6 @@ protected function setServiceMock(
103112
}
104113
}
105114

106-
/**
107-
* Builds up the environment to run the given command.
108-
*/
109-
protected function runCommand(string $name, array $params = [], bool $reuseKernel = false): CommandTester
110-
{
111-
if (!$reuseKernel) {
112-
if (null !== static::$kernel) {
113-
static::ensureKernelShutdown();
114-
}
115-
116-
$kernel = static::bootKernel(['environment' => static::$env]);
117-
$kernel->boot();
118-
} else {
119-
$kernel = $this->getContainer()->get('kernel');
120-
}
121-
122-
$application = new Application($kernel);
123-
124-
$options = [
125-
'interactive' => false,
126-
'decorated' => $this->getDecorated(),
127-
'verbosity' => $this->getVerbosityLevel(),
128-
];
129-
130-
$command = $application->find($name);
131-
$commandTester = new CommandTester($command);
132-
133-
if (null !== $inputs = $this->getInputs()) {
134-
$commandTester->setInputs($inputs);
135-
$options['interactive'] = true;
136-
$this->inputs = null;
137-
}
138-
139-
$commandTester->execute(
140-
array_merge(['command' => $command->getName()], $params),
141-
$options
142-
);
143-
144-
return $commandTester;
145-
}
146-
147115
/**
148116
* Retrieves the output verbosity level.
149117
*
@@ -535,8 +503,17 @@ public static function assertValidationErrors(array $expected, ContainerInterfac
535503
HttpAssertions::assertValidationErrors($expected, $container);
536504
}
537505

506+
protected function setUp(): void
507+
{
508+
parent::setUp();
509+
510+
self::$activeInstance = $this;
511+
}
512+
538513
protected function tearDown(): void
539514
{
515+
self::$activeInstance = null;
516+
540517
if (null !== $this->containers) {
541518
foreach ($this->containers as $container) {
542519
if ($container instanceof ResettableContainerInterface) {

tests/Command/CommandConfigTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ public function testRunCommand(): void
4747
// Run command without options
4848
$this->commandTester = $this->runCommand('liipfunctionaltestbundle:test');
4949

50-
$this->assertInstanceOf(CommandTester::class, $this->commandTester);
50+
if ($this->commandTester instanceof CommandTester) {
51+
$this->assertInstanceOf(CommandTester::class, $this->commandTester);
52+
} else {
53+
$this->assertInstanceOf(\Symfony\Component\Console\Tester\ExecutionResult::class, $this->commandTester);
54+
}
5155

5256
// Test values from configuration
5357
$this->assertStringContainsString('Environment: test', $this->commandTester->getDisplay());

0 commit comments

Comments
 (0)