Skip to content

Commit 0311b9d

Browse files
authored
Merge branch 'main' into fix-kernel-boot
2 parents 0ef200a + d8a8943 commit 0311b9d

11 files changed

+95
-76
lines changed

composer.json

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
{
22
"name": "codeception/module-symfony",
33
"description": "Codeception module for Symfony framework",
4-
"license": "MIT",
54
"type": "library",
5+
"license": "MIT",
66
"keywords": [
77
"codeception",
88
"functional testing",
99
"symfony"
1010
],
11+
"homepage": "https://codeception.com/",
12+
"support": {
13+
"docs": "https://codeception.com/docs/modules/Symfony"
14+
},
1115
"authors": [
1216
{
1317
"name": "Michael Bodnarchuk"
@@ -17,17 +21,16 @@
1721
"homepage": "https://medium.com/@ganieves"
1822
}
1923
],
20-
"homepage": "https://codeception.com/",
2124
"require": {
22-
"php": "^8.1",
25+
"php": "^8.2",
2326
"ext-json": "*",
24-
"codeception/codeception": "^5.0.8",
25-
"codeception/lib-innerbrowser": "^3.1.1 | ^4.0"
27+
"codeception/codeception": "^5.3",
28+
"codeception/lib-innerbrowser": "^3.1 | ^4.0"
2629
},
2730
"require-dev": {
2831
"codeception/module-asserts": "^3.0",
2932
"codeception/module-doctrine": "^3.1",
30-
"doctrine/orm": "^2.10",
33+
"doctrine/orm": "^2.20",
3134
"symfony/browser-kit": "^5.4 | ^6.4 | ^7.2",
3235
"symfony/cache": "^5.4 | ^6.4 | ^7.2",
3336
"symfony/config": "^5.4 | ^6.4 | ^7.2",
@@ -62,12 +65,12 @@
6265
"codeception/module-asserts": "Include traditional PHPUnit assertions in your tests",
6366
"symfony/web-profiler-bundle": "Tool that gives information about the execution of requests"
6467
},
65-
"minimum-stability": "RC",
6668
"autoload": {
6769
"classmap": ["src/"]
6870
},
6971
"config": {
7072
"classmap-authoritative": true,
7173
"sort-packages": true
72-
}
74+
},
75+
"minimum-stability": "RC"
7376
}

src/Codeception/Module/Symfony.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ protected function getKernelClass(): string
321321
throw new ModuleRequireException(
322322
self::class,
323323
"Kernel class was not found.\n"
324-
. 'Specify directory where file with Kernel class for your application is located with `app_path` parameter.'
324+
. 'Specify directory where file with Kernel class for your application is located with `kernel_class` parameter.'
325325
);
326326
}
327327

src/Codeception/Module/Symfony/BrowserAssertionsTrait.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,16 @@ public function assertResponseStatusCodeSame(int $expectedCode, string $message
258258
* <?php
259259
* $I->assertRouteSame('profile', ['id' => 123]);
260260
* ```
261+
*
262+
* @param array<string, bool|float|int|null|string> $parameters
261263
*/
262-
public function assertRouteSame(string $expectedRoute, array $parameters = [], string $message = ''): void {
264+
public function assertRouteSame(string $expectedRoute, array $parameters = [], string $message = ''): void
265+
{
263266
$request = $this->getClient()->getRequest();
264267
$this->assertThat($request, new RequestAttributeValueSame('_route', $expectedRoute));
265268

266269
foreach ($parameters as $key => $value) {
267-
$this->assertThat($request, new RequestAttributeValueSame($key, $value), $message);
270+
$this->assertThat($request, new RequestAttributeValueSame($key, (string)$value), $message);
268271
}
269272
}
270273

@@ -349,7 +352,7 @@ public function seePageRedirectsTo(string $page, string $redirectsTo): void
349352
* ]);
350353
* ```
351354
*
352-
* @param string $name The `name` attribute of the `<form>`. You cannot use an array as a selector here.
355+
* @param string $name The `name` attribute of the `<form>`. You cannot use an array as a selector here.
353356
* @param array<string, mixed> $fields The form fields to submit.
354357
*/
355358
public function submitSymfonyForm(string $name, array $fields): void

src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use Symfony\Component\Console\Tester\CommandTester;
1010
use Symfony\Component\HttpKernel\KernelInterface;
1111

12+
use function in_array;
13+
use function sprintf;
14+
1215
trait ConsoleAssertionsTrait
1316
{
1417
/**
@@ -20,40 +23,42 @@ trait ConsoleAssertionsTrait
2023
* $result = $I->runSymfonyConsoleCommand('hello:world', ['arg' => 'argValue', 'opt1' => 'optValue'], ['input']);
2124
* ```
2225
*
23-
* @param string $command The console command to execute
24-
* @param array $parameters Parameters (arguments and options) to pass to the command
25-
* @param array $consoleInputs Console inputs (e.g. used for interactive questions)
26-
* @param int $expectedExitCode The expected exit code of the command
27-
* @return string Returns the console output of the command
26+
* @param string $command The console command to execute.
27+
* @param array<string, int|string> $parameters Arguments and options passed to the command
28+
* @param list<string> $consoleInputs Inputs for interactive questions.
29+
* @param int $expectedExitCode Expected exit code.
30+
* @return string Console output (stdout).
2831
*/
29-
public function runSymfonyConsoleCommand(string $command, array $parameters = [], array $consoleInputs = [], int $expectedExitCode = 0): string
30-
{
31-
$kernel = $this->grabKernelService();
32-
$application = new Application($kernel);
33-
$consoleCommand = $application->find($command);
34-
$commandTester = new CommandTester($consoleCommand);
32+
public function runSymfonyConsoleCommand(
33+
string $command,
34+
array $parameters = [],
35+
array $consoleInputs = [],
36+
int $expectedExitCode = 0
37+
): string {
38+
$kernel = $this->grabKernelService();
39+
$application = new Application($kernel);
40+
$consoleCommand = $application->find($command);
41+
$commandTester = new CommandTester($consoleCommand);
3542
$commandTester->setInputs($consoleInputs);
3643

37-
$input = ['command' => $command] + $parameters;
38-
$options = $this->configureOptions($parameters);
39-
44+
$input = ['command' => $command] + $parameters;
45+
$options = $this->configureOptions($parameters);
4046
$exitCode = $commandTester->execute($input, $options);
41-
$output = $commandTester->getDisplay();
47+
$output = $commandTester->getDisplay();
4248

4349
$this->assertSame(
4450
$expectedExitCode,
4551
$exitCode,
46-
sprintf(
47-
'Command did not exit with code %d but with %d: %s',
48-
$expectedExitCode,
49-
$exitCode,
50-
$output
51-
)
52+
sprintf('Command exited with %d instead of expected %d. Output: %s', $exitCode, $expectedExitCode, $output)
5253
);
5354

5455
return $output;
5556
}
5657

58+
/**
59+
* @param array<string, int|string|bool> $parameters
60+
* @return array<string, mixed> Options array supported by CommandTester.
61+
*/
5762
private function configureOptions(array $parameters): array
5863
{
5964
$options = [];
@@ -69,27 +74,24 @@ private function configureOptions(array $parameters): array
6974
}
7075

7176
if (in_array('--quiet', $parameters, true) || in_array('-q', $parameters, true)) {
72-
$options['verbosity'] = OutputInterface::VERBOSITY_QUIET;
77+
$options['verbosity'] = OutputInterface::VERBOSITY_QUIET;
7378
$options['interactive'] = false;
7479
}
7580

76-
if (
77-
in_array('-vvv', $parameters, true) ||
78-
in_array('--verbose=3', $parameters, true) ||
79-
(isset($parameters["--verbose"]) && $parameters["--verbose"] === 3)
81+
if (in_array('-vvv', $parameters, true)
82+
|| in_array('--verbose=3', $parameters, true)
83+
|| (isset($parameters['--verbose']) && $parameters['--verbose'] === 3)
8084
) {
8185
$options['verbosity'] = OutputInterface::VERBOSITY_DEBUG;
82-
} elseif (
83-
in_array('-vv', $parameters, true) ||
84-
in_array('--verbose=2', $parameters, true) ||
85-
(isset($parameters["--verbose"]) && $parameters["--verbose"] === 2)
86+
} elseif (in_array('-vv', $parameters, true)
87+
|| in_array('--verbose=2', $parameters, true)
88+
|| (isset($parameters['--verbose']) && $parameters['--verbose'] === 2)
8689
) {
8790
$options['verbosity'] = OutputInterface::VERBOSITY_VERY_VERBOSE;
88-
} elseif (
89-
in_array('-v', $parameters, true) ||
90-
in_array('--verbose=1', $parameters, true) ||
91-
in_array('--verbose', $parameters, true) ||
92-
(isset($parameters["--verbose"]) && $parameters["--verbose"] === 1)
91+
} elseif (in_array('-v', $parameters, true)
92+
|| in_array('--verbose=1', $parameters, true)
93+
|| in_array('--verbose', $parameters, true)
94+
|| (isset($parameters['--verbose']) && $parameters['--verbose'] === 1)
9395
) {
9496
$options['verbosity'] = OutputInterface::VERBOSITY_VERBOSE;
9597
}
@@ -101,4 +103,4 @@ protected function grabKernelService(): KernelInterface
101103
{
102104
return $this->grabService('kernel');
103105
}
104-
}
106+
}

src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ public function assertCheckboxChecked(string $fieldName, string $message = ''):
3636
*/
3737
public function assertCheckboxNotChecked(string $fieldName, string $message = ''): void
3838
{
39-
$this->assertThatCrawler(new LogicalNot(
40-
new CrawlerSelectorExists("input[name=\"$fieldName\"]:checked")
41-
), $message);
39+
$this->assertThatCrawler(
40+
new LogicalNot(
41+
new CrawlerSelectorExists("input[name=\"$fieldName\"]:checked")
42+
), $message
43+
);
4244
}
4345

4446
/**
@@ -52,9 +54,11 @@ public function assertCheckboxNotChecked(string $fieldName, string $message = ''
5254
public function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void
5355
{
5456
$this->assertThatCrawler(new CrawlerSelectorExists("input[name=\"$fieldName\"]"), $message);
55-
$this->assertThatCrawler(new LogicalNot(
56-
new CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)
57-
), $message);
57+
$this->assertThatCrawler(
58+
new LogicalNot(
59+
new CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)
60+
), $message
61+
);
5862
}
5963

6064
/**

src/Codeception/Module/Symfony/MailerAssertionsTrait.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ public function assertQueuedEmailCount(int $count, ?string $transport = null, st
7272
/**
7373
* Checks that no email was sent.
7474
* The check is based on `\Symfony\Component\Mailer\EventListener\MessageLoggerListener`, which means:
75-
* If your app performs an HTTP redirect, you need to suppress it using [stopFollowingRedirects()](https://codeception.com/docs/modules/Symfony#stopFollowingRedirects) first;
76-
* otherwise this check will *always* pass.
75+
* If your app performs an HTTP redirect, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first; otherwise this check will *always* pass.
7776
*
7877
* ```php
7978
* <?php
@@ -88,7 +87,7 @@ public function dontSeeEmailIsSent(): void
8887
/**
8988
* Returns the last sent email.
9089
* The function is based on `\Symfony\Component\Mailer\EventListener\MessageLoggerListener`, which means:
91-
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](https://codeception.com/docs/modules/Symfony#stopFollowingRedirects) first.
90+
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
9291
* See also: [grabSentEmails()](https://codeception.com/docs/modules/Symfony#grabSentEmails)
9392
*
9493
* ```php
@@ -110,7 +109,7 @@ public function grabLastSentEmail(): ?Email
110109
/**
111110
* Returns an array of all sent emails.
112111
* The function is based on `\Symfony\Component\Mailer\EventListener\MessageLoggerListener`, which means:
113-
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](https://codeception.com/docs/modules/Symfony#stopFollowingRedirects) first.
112+
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
114113
* See also: [grabLastSentEmail()](https://codeception.com/docs/modules/Symfony#grabLastSentEmail)
115114
*
116115
* ```php
@@ -128,7 +127,12 @@ public function grabSentEmails(): array
128127
/**
129128
* Checks if the given number of emails was sent (default `$expectedCount`: 1).
130129
* The check is based on `\Symfony\Component\Mailer\EventListener\MessageLoggerListener`, which means:
131-
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](https://codeception.com/docs/modules/Symfony#stopFollowingRedirects) first.
130+
* If your app performs an HTTP redirect after sending the email, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
131+
*
132+
* Limitation:
133+
* If your mail is sent in a Symfony console command and you start that command in your test with [$I->runShellCommand()](https://codeception.com/docs/modules/Cli#runShellCommand),
134+
* Codeception will not notice it.
135+
* As a more professional alternative, we recommend Mailpit (see [Addons](https://codeception.com/addons)), which also lets you test the content of the mail.
132136
*
133137
* ```php
134138
* <?php

src/Codeception/Module/Symfony/MimeAssertionsTrait.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace Codeception\Module\Symfony;
66

7+
use PHPUnit\Framework\Assert;
78
use PHPUnit\Framework\Constraint\LogicalNot;
89
use Symfony\Component\Mime\Email;
9-
use Symfony\Component\Mime\RawMessage;
1010
use Symfony\Component\Mime\Test\Constraint as MimeConstraint;
1111

1212
trait MimeAssertionsTrait
@@ -171,8 +171,8 @@ private function verifyEmailObject(?Email $email, string $function): Email
171171
{
172172
$email = $email ?: $this->grabLastSentEmail();
173173
$errorMsgTemplate = "There is no email to verify. An Email object was not specified when invoking '%s' and the application has not sent one.";
174-
return $email ?: $this->fail(
174+
return $email ?? Assert::fail(
175175
sprintf($errorMsgTemplate, $function)
176176
);
177177
}
178-
}
178+
}

src/Codeception/Module/Symfony/ServicesAssertionsTrait.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
namespace Codeception\Module\Symfony;
66

77
use Codeception\Lib\Connector\Symfony as SymfonyConnector;
8+
use PHPUnit\Framework\Assert;
89

910
trait ServicesAssertionsTrait
1011
{
1112
/**
1213
* Grabs a service from the Symfony dependency injection container (DIC).
13-
* In "test" environment, Symfony uses a special `test.service_container`.
14+
* In the "test" environment, Symfony uses a special `test.service_container`.
1415
* See the "[Public Versus Private Services](https://symfony.com/doc/current/service_container/alias_private.html#marking-services-as-public-private)" documentation.
15-
* Services that aren't injected somewhere into your app, need to be defined as `public` to be accessible by Codeception.
16+
* Services that aren't injected anywhere in your app, need to be defined as `public` to be accessible by Codeception.
1617
*
1718
* ```php
1819
* <?php
@@ -24,8 +25,10 @@ trait ServicesAssertionsTrait
2425
public function grabService(string $serviceId): object
2526
{
2627
if (!$service = $this->getService($serviceId)) {
27-
$this->fail("Service `{$serviceId}` is required by Codeception, but not loaded by Symfony since you're not using it anywhere in your app.\n
28-
Recommended solution: Set it to `public` in your `config/services_test.php`/`.yaml`, see https://symfony.com/doc/current/service_container/alias_private.html#marking-services-as-public-private");
28+
Assert::fail("Service `{$serviceId}` is required by Codeception, but not loaded by Symfony. Possible solutions:\n
29+
In your `config/packages/framework.php`/`.yaml`, set `test` to `true` (when in test environment), see https://symfony.com/doc/current/reference/configuration/framework.html#test\n
30+
If you're still getting this message, you're not using that service in your app, so Symfony isn't loading it at all.\n
31+
Solution: Set it to `public` in your `config/services.php`/`.yaml`, see https://symfony.com/doc/current/service_container/alias_private.html#marking-services-as-public-private\n");
2932
}
3033

3134
return $service;

src/Codeception/Module/Symfony/TranslationAssertionsTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function seeDefaultLocaleIs(string $expectedLocale): void
109109
* $I->seeFallbackLocalesAre(['es', 'fr']);
110110
* ```
111111
*
112-
* @param array $expectedLocales The expected fallback locales
112+
* @param string[] $expectedLocales The expected fallback locales
113113
*/
114114
public function seeFallbackLocalesAre(array $expectedLocales): void
115115
{

src/Codeception/Module/Symfony/TwigAssertionsTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,4 @@ protected function grabTwigCollector(string $function): TwigDataCollector
7979
{
8080
return $this->grabCollector('twig', $function);
8181
}
82-
}
82+
}

0 commit comments

Comments
 (0)