diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ab42b8c5..885dd616 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,12 +9,14 @@ jobs: strategy: matrix: php: [8.0, 8.1, 8.2] - symfony: ["4.4.*", "5.4.*", "6.0.*", "6.1.*", "6.2.*"] + symfony: ["4.4.*", "5.4.*", "6.0.*", "6.1.*", "6.2.*", "6.3.*"] exclude: - php: 8.0 symfony: "6.1.*" - php: 8.0 symfony: "6.2.*" + - php: 8.0 + symfony: "6.3.*" steps: - name: Checkout code @@ -68,6 +70,14 @@ jobs: path: framework-tests ref: "6.2" + - name: Checkout Symfony 6.3 Sample + if: "matrix.symfony == '6.3.*'" + uses: actions/checkout@v2 + with: + repository: Codeception/symfony-module-tests + path: framework-tests + ref: "6.3" + - name: Get composer cache directory id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" @@ -79,6 +89,10 @@ jobs: key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer- + - name: Install PHPUnit 9 for Symfony 4.4, 5.4 and 6.0 + if: "matrix.symfony == '4.4.*' || matrix.symfony == '5.4.*' || matrix.symfony == '6.0.*'" + run: composer require --dev --no-update "phpunit/phpunit=^9.0" + - name: Install dependencies run: | composer require symfony/finder=${{ matrix.symfony }} --no-update @@ -97,6 +111,11 @@ jobs: run: composer validate working-directory: framework-tests + - name: Install PHPUnit 10 in framework-tests for Symfony 6.1 and 6.2 + if: "matrix.symfony == '6.1.*' || matrix.symfony == '6.2.*' || matrix.symfony == '6.3.*'" + run: composer require --dev --no-update "phpunit/phpunit=^10.0" + working-directory: framework-tests + - name: Install Symfony Sample run: | composer remove codeception/codeception codeception/module-asserts codeception/module-doctrine2 codeception/lib-innerbrowser codeception/module-symfony --dev --no-update diff --git a/composer.json b/composer.json index 1e03edcd..24d5822d 100644 --- a/composer.json +++ b/composer.json @@ -20,20 +20,36 @@ "require": { "php": "^8.0", "ext-json": "*", - "codeception/codeception": "^5.0.0-RC3", + "codeception/codeception": "^5.0.8", "codeception/lib-innerbrowser": "^3.1.1 | ^4.0" }, "require-dev": { "codeception/module-asserts": "^3.0", "codeception/module-doctrine2": "^3.0", "doctrine/orm": "^2.10", + "symfony/browser-kit": "^4.4 | ^5.0 | ^6.0", + "symfony/cache": "^4.4 | ^5.0 | ^6.0", + "symfony/config": "^4.4 | ^5.0 | ^6.0", + "symfony/dependency-injection": "^4.4 | ^5.0 | ^6.0", + "symfony/dom-crawler": "^4.4 | ^5.0 | ^6.0", + "symfony/error-handler": "^4.4 | ^5.0 | ^6.0", + "symfony/filesystem": "^4.4 | ^5.0 | ^6.0", "symfony/form": "^4.4 | ^5.0 | ^6.0", "symfony/framework-bundle": "^4.4 | ^5.0 | ^6.0", + "symfony/http-foundation": "^4.4 | ^5.0 | ^6.0", "symfony/http-kernel": "^4.4 | ^5.0 | ^6.0", "symfony/mailer": "^4.4 | ^5.0 | ^6.0", + "symfony/mime": "^4.4 | ^5.0 | ^6.0", + "symfony/options-resolver": "^4.4 | ^5.0 | ^6.0", + "symfony/property-access": "^4.4 | ^5.0 | ^6.0", + "symfony/property-info": "^4.4 | ^5.0 | ^6.0", "symfony/routing": "^4.4 | ^5.0 | ^6.0", "symfony/security-bundle": "^4.4 | ^5.0 | ^6.0", + "symfony/security-core": "^4.4 | ^5.0 | ^6.0", + "symfony/security-csrf": "^4.4 | ^5.0 | ^6.0", + "symfony/security-http": "^4.4 | ^5.0 | ^6.0", "symfony/twig-bundle": "^4.4 | ^5.0 | ^6.0", + "symfony/var-exporter": "^4.4 | ^5.0 | ^6.0", "vlucas/phpdotenv": "^4.2 | ^5.4" }, "suggest": { diff --git a/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php b/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php index cabd34f2..67dc1ddb 100644 --- a/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php @@ -23,7 +23,6 @@ trait BrowserAssertionsTrait * // Perform other requests * * ``` - * */ public function rebootClientKernel(): void { diff --git a/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php b/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php index d54e2bfa..66edec9e 100644 --- a/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php @@ -40,8 +40,12 @@ public function runSymfonyConsoleCommand(string $command, array $parameters = [] $this->assertSame( $expectedExitCode, $exitCode, - 'Command did not exit with code ' . $expectedExitCode - . ' but with ' . $exitCode . ': ' . $output + sprintf( + 'Command did not exit with code %d but with %d: %s', + $expectedExitCode, + $exitCode, + $output + ) ); return $output; diff --git a/src/Codeception/Module/Symfony/DoctrineAssertionsTrait.php b/src/Codeception/Module/Symfony/DoctrineAssertionsTrait.php index 9aa4a054..6f9f0bc4 100644 --- a/src/Codeception/Module/Symfony/DoctrineAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/DoctrineAssertionsTrait.php @@ -6,7 +6,6 @@ use Doctrine\ORM\EntityRepository; use function class_exists; -use function get_class; use function interface_exists; use function is_object; use function is_string; @@ -66,6 +65,7 @@ public function grabRepository(object|string $mixed): ?EntityRepository $getRepo = function () use ($mixed, $entityRepoClass, $isNotARepo): ?EntityRepository { if (!$repo = $this->grabService($mixed)) return null; + /** @var EntityRepository $repo */ if (!$repo instanceof $entityRepoClass) { $isNotARepo(); return null; diff --git a/src/Codeception/Module/Symfony/EventsAssertionsTrait.php b/src/Codeception/Module/Symfony/EventsAssertionsTrait.php index f4b47b98..0ef1ee4c 100644 --- a/src/Codeception/Module/Symfony/EventsAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/EventsAssertionsTrait.php @@ -5,44 +5,48 @@ namespace Codeception\Module\Symfony; use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; -use Symfony\Component\VarDumper\Cloner\Data; -use function get_class; use function is_array; use function is_object; -use function strpos; trait EventsAssertionsTrait { /** - * Verifies that there were no orphan events during the test. + * Verifies that there were no events during the test. + * Both regular and orphan events are checked. * - * An orphan event is an event that was triggered by manually executing the - * [`dispatch()`](https://symfony.com/doc/current/components/event_dispatcher.html#dispatch-the-event) method - * of the EventDispatcher but was not handled by any listener after it was dispatched. + * ```php + * dontSeeEvent(); + * $I->dontSeeEvent('App\MyEvent'); + * $I->dontSeeEvent(['App\MyEvent', 'App\MyOtherEvent']); + * ``` + * + * @param string|string[]|null $expected + */ + public function dontSeeEvent(array|string $expected = null): void + { + $actualEvents = array_merge(array_column($this->getCalledListeners(), 'event')); + $actual = [$this->getOrphanedEvents(), $actualEvents]; + $this->assertEventTriggered(false, $expected, $actual); + } + + /** + * Verifies that one or more event listeners were not called during the test. * * ```php * dontSeeOrphanEvent(); - * $I->dontSeeOrphanEvent('App\MyEvent'); - * $I->dontSeeOrphanEvent(new App\Events\MyEvent()); - * $I->dontSeeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']); + * $I->dontSeeEventListenerIsCalled('App\MyEventListener'); + * $I->dontSeeEventListenerIsCalled(['App\MyEventListener', 'App\MyOtherEventListener']); + * $I->dontSeeEventListenerIsCalled('App\MyEventListener', 'my.event); + * $I->dontSeeEventListenerIsCalled('App\MyEventListener', ['my.event', 'my.other.event']); * ``` * - * @param object|string|string[] $expected + * @param class-string|class-string[] $expected + * @param string|string[] $events */ - public function dontSeeOrphanEvent(array|object|string $expected = null): void + public function dontSeeEventListenerIsCalled(array|object|string $expected, array|string $events = []): void { - $eventCollector = $this->grabEventCollector(__FUNCTION__); - - /** @var Data $data */ - $data = $eventCollector->getOrphanedEvents(); - $expected = is_array($expected) ? $expected : [$expected]; - - if ($expected === null) { - $this->assertSame(0, $data->count()); - } else { - $this->assertEventNotTriggered($data, $expected); - } + $this->assertListenerCalled(false, $expected, $events); } /** @@ -56,20 +60,19 @@ public function dontSeeOrphanEvent(array|object|string $expected = null): void * ``` * * @param object|string|string[] $expected + * @deprecated Use `dontSeeEventListenerIsCalled` instead. */ public function dontSeeEventTriggered(array|object|string $expected): void { - $eventCollector = $this->grabEventCollector(__FUNCTION__); - - /** @var Data $data */ - $data = $eventCollector->getCalledListeners(); - $expected = is_array($expected) ? $expected : [$expected]; - - $this->assertEventNotTriggered($data, $expected); + trigger_error( + 'dontSeeEventTriggered is deprecated, please use dontSeeEventListenerIsCalled instead', + E_USER_DEPRECATED + ); + $this->dontSeeEventListenerIsCalled($expected); } /** - * Verifies that one or more orphan events were dispatched during the test. + * Verifies that there were no orphan events during the test. * * An orphan event is an event that was triggered by manually executing the * [`dispatch()`](https://symfony.com/doc/current/components/event_dispatcher.html#dispatch-the-event) method @@ -77,22 +80,58 @@ public function dontSeeEventTriggered(array|object|string $expected): void * * ```php * seeOrphanEvent('App\MyEvent'); - * $I->seeOrphanEvent(new App\Events\MyEvent()); - * $I->seeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']); + * $I->dontSeeOrphanEvent(); + * $I->dontSeeOrphanEvent('App\MyEvent'); + * $I->dontSeeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']); * ``` * - * @param object|string|string[] $expected + * @param string|string[] $expected */ - public function seeOrphanEvent(array|object|string $expected): void + public function dontSeeOrphanEvent(array|string $expected = null): void { - $eventCollector = $this->grabEventCollector(__FUNCTION__); + $actual = [$this->getOrphanedEvents()]; + $this->assertEventTriggered(false, $expected, $actual); + } - /** @var Data $data */ - $data = $eventCollector->getOrphanedEvents(); - $expected = is_array($expected) ? $expected : [$expected]; + /** + * Verifies that one or more events were dispatched during the test. + * Both regular and orphan events are checked. + * + * If you need to verify that expected event is not orphan, + * add `dontSeeOrphanEvent` call. + * + * ```php + * seeEvent('App\MyEvent'); + * $I->seeEvent(['App\MyEvent', 'App\MyOtherEvent']); + * ``` + * + * @param string|string[] $expected + */ + public function seeEvent(array|string $expected): void + { + $actualEvents = array_merge(array_column($this->getCalledListeners(), 'event')); + $actual = [$this->getOrphanedEvents(), $actualEvents]; + $this->assertEventTriggered(true, $expected, $actual); + } - $this->assertEventTriggered($data, $expected); + /** + * Verifies that one or more event listeners were called during the test. + * + * ```php + * seeEventListenerIsCalled('App\MyEventListener'); + * $I->seeEventListenerIsCalled(['App\MyEventListener', 'App\MyOtherEventListener']); + * $I->seeEventListenerIsCalled('App\MyEventListener', 'my.event); + * $I->seeEventListenerIsCalled('App\MyEventListener', ['my.event', 'my.other.event']); + * ``` + * + * @param class-string|class-string[] $expected + * @param string|string[] $events + */ + public function seeEventListenerIsCalled(array|object|string $expected, array|string $events = []): void + { + $this->assertListenerCalled(true, $expected, $events); } /** @@ -106,68 +145,123 @@ public function seeOrphanEvent(array|object|string $expected): void * ``` * * @param object|string|string[] $expected + * @deprecated Use `seeEventListenerIsCalled` instead. */ public function seeEventTriggered(array|object|string $expected): void { - $eventCollector = $this->grabEventCollector(__FUNCTION__); + trigger_error( + 'seeEventTriggered is deprecated, please use seeEventListenerIsCalled instead', + E_USER_DEPRECATED + ); + $this->seeEventListenerIsCalled($expected); + } - /** @var Data $data */ - $data = $eventCollector->getCalledListeners(); - $expected = is_array($expected) ? $expected : [$expected]; + /** + * Verifies that one or more orphan events were dispatched during the test. + * + * An orphan event is an event that was triggered by manually executing the + * [`dispatch()`](https://symfony.com/doc/current/components/event_dispatcher.html#dispatch-the-event) method + * of the EventDispatcher but was not handled by any listener after it was dispatched. + * + * ```php + * seeOrphanEvent('App\MyEvent'); + * $I->seeOrphanEvent(['App\MyEvent', 'App\MyOtherEvent']); + * ``` + * + * @param string|string[] $expected + */ + public function seeOrphanEvent(array|string $expected): void + { + $actual = [$this->getOrphanedEvents()]; + $this->assertEventTriggered(true, $expected, $actual); + } - $this->assertEventTriggered($data, $expected); + protected function getCalledListeners(): array + { + $eventCollector = $this->grabEventCollector(__FUNCTION__); + $calledListeners = $eventCollector->getCalledListeners($this->getDefaultDispatcher()); + return [...$calledListeners->getValue(true)]; } - protected function assertEventNotTriggered(Data $data, array $expected): void + protected function getOrphanedEvents(): array { - $actual = $data->getValue(true); + $eventCollector = $this->grabEventCollector(__FUNCTION__); + $orphanedEvents = $eventCollector->getOrphanedEvents($this->getDefaultDispatcher()); + return [...$orphanedEvents->getValue(true)]; + } + + protected function assertEventTriggered(bool $assertTrue, array|object|string|null $expected, array $actual): void + { + $actualEvents = array_merge(...$actual); - foreach ($expected as $expectedEvent) { + if ($assertTrue) $this->assertNotEmpty($actualEvents, 'No event was triggered'); + if ($expected === null) { + $this->assertEmpty($actualEvents); + return; + } + + $expected = is_object($expected) ? $expected::class : $expected; + foreach ((array)$expected as $expectedEvent) { $expectedEvent = is_object($expectedEvent) ? $expectedEvent::class : $expectedEvent; - $this->assertFalse( - $this->eventWasTriggered($actual, (string)$expectedEvent), - "The '{$expectedEvent}' event triggered" - ); + $eventTriggered = in_array($expectedEvent, $actualEvents); + + $message = $assertTrue + ? "The '{$expectedEvent}' event did not trigger" + : "The '{$expectedEvent}' event triggered"; + $this->assertSame($assertTrue, $eventTriggered, $message); } } - protected function assertEventTriggered(Data $data, array $expected): void + protected function assertListenerCalled(bool $assertTrue, array|object|string $expectedListeners, array|object|string $expectedEvents): void { - if ($data->count() === 0) { - $this->fail('No event was triggered'); + $expectedListeners = is_array($expectedListeners) ? $expectedListeners : [$expectedListeners]; + $expectedEvents = is_array($expectedEvents) ? $expectedEvents : [$expectedEvents]; + + if (empty($expectedEvents)) { + $expectedEvents = [null]; + } elseif (count($expectedListeners) > 1) { + $this->fail('You cannot check for events when using multiple listeners. Make multiple assertions instead.'); } - $actual = $data->getValue(true); + $actualEvents = $this->getCalledListeners(); + if ($assertTrue && empty($actualEvents)) { + $this->fail('No event listener was called'); + } - foreach ($expected as $expectedEvent) { - $expectedEvent = is_object($expectedEvent) ? $expectedEvent::class : $expectedEvent; - $this->assertTrue( - $this->eventWasTriggered($actual, (string)$expectedEvent), - "The '{$expectedEvent}' event did not trigger" - ); + foreach ($expectedListeners as $expectedListener) { + $expectedListener = is_object($expectedListener) ? $expectedListener::class : $expectedListener; + + foreach ($expectedEvents as $expectedEvent) { + $listenerCalled = $this->listenerWasCalled($expectedListener, $expectedEvent, $actualEvents); + $message = "The '{$expectedListener}' listener was called" + . ($expectedEvent ? " for the '{$expectedEvent}' event" : ''); + $this->assertSame($assertTrue, $listenerCalled, $message); + } } } - protected function eventWasTriggered(array $actual, string $expectedEvent): bool + private function listenerWasCalled(string $expectedListener, ?string $expectedEvent, array $actualEvents): bool { - $triggered = false; - - foreach ($actual as $actualEvent) { - if (is_array($actualEvent)) { // Called Listeners - if (str_starts_with($actualEvent['pretty'], $expectedEvent)) { - $triggered = true; - } - } else { // Orphan Events - if ($actualEvent === $expectedEvent) { - $triggered = true; - } + foreach ($actualEvents as $actualEvent) { + if ( + isset($actualEvent['pretty'], $actualEvent['event']) + && str_starts_with($actualEvent['pretty'], $expectedListener) + && ($expectedEvent === null || $actualEvent['event'] === $expectedEvent) + ) { + return true; } } - return $triggered; + return false; + } + + protected function getDefaultDispatcher(): string + { + return 'event_dispatcher'; } protected function grabEventCollector(string $function): EventDataCollector { return $this->grabCollector('events', $function); } -} \ No newline at end of file +} diff --git a/src/Codeception/Module/Symfony/FormAssertionsTrait.php b/src/Codeception/Module/Symfony/FormAssertionsTrait.php index 8261ea9f..31940e15 100644 --- a/src/Codeception/Module/Symfony/FormAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/FormAssertionsTrait.php @@ -51,7 +51,7 @@ public function seeFormErrorMessage(string $field, string $message = null): void $formCollector = $this->grabFormCollector(__FUNCTION__); if (!$forms = $formCollector->getData()->getValue(true)['forms']) { - $this->fail('There are no forms on the current page.'); + $this->fail('No forms found on the current page.'); } $fields = []; @@ -73,7 +73,7 @@ public function seeFormErrorMessage(string $field, string $message = null): void } if (!in_array($field, $fields)) { - $this->fail("the field '{$field}' does not exist in the form."); + $this->fail("The field '{$field}' does not exist in the form."); } if (!array_key_exists($field, $errors)) { diff --git a/src/Codeception/Module/Symfony/MailerAssertionsTrait.php b/src/Codeception/Module/Symfony/MailerAssertionsTrait.php index cb82484a..4e61cb2d 100644 --- a/src/Codeception/Module/Symfony/MailerAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/MailerAssertionsTrait.php @@ -56,13 +56,11 @@ public function seeEmailIsSent(int $expectedCount = 1): void */ public function grabLastSentEmail(): ?Email { + /** @var Email[] $emails */ $emails = $this->getMessageMailerEvents()->getMessages(); - /** @var Email|false $lastEmail */ - if ($lastEmail = end($emails)) { - return $lastEmail; - } + $lastEmail = end($emails); - return null; + return $lastEmail ?: null; } /** diff --git a/src/Codeception/Module/Symfony/ParameterAssertionsTrait.php b/src/Codeception/Module/Symfony/ParameterAssertionsTrait.php index cb5bcad2..63231dd5 100644 --- a/src/Codeception/Module/Symfony/ParameterAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/ParameterAssertionsTrait.php @@ -16,13 +16,13 @@ trait ParameterAssertionsTrait * $I->grabParameter('app.business_name'); * ``` * - * @param string $name + * @param string $parameterName * @return array|bool|float|int|string|null */ - public function grabParameter(string $name) + public function grabParameter(string $parameterName) { $parameterBag = $this->grabParameterBagService(); - return $parameterBag->get($name); + return $parameterBag->get($parameterName); } protected function grabParameterBagService(): ParameterBagInterface diff --git a/src/Codeception/Module/Symfony/RouterAssertionsTrait.php b/src/Codeception/Module/Symfony/RouterAssertionsTrait.php index c023782f..e0bdeab0 100644 --- a/src/Codeception/Module/Symfony/RouterAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/RouterAssertionsTrait.php @@ -11,8 +11,6 @@ use function array_merge; use function explode; use function sprintf; -use function strlen; -use function substr_compare; trait RouterAssertionsTrait { @@ -32,7 +30,6 @@ trait RouterAssertionsTrait public function amOnAction(string $action, array $params = []): void { $router = $this->grabRouterService(); - $routes = $router->getRouteCollection()->getIterator(); foreach ($routes as $route) { @@ -66,7 +63,7 @@ public function amOnRoute(string $routeName, array $params = []): void { $router = $this->grabRouterService(); if ($router->getRouteCollection()->get($routeName) === null) { - $this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); + $this->fail(sprintf('Route with name "%s" does not exist.', $routeName)); } $url = $router->generate($routeName, $params); @@ -95,7 +92,6 @@ public function invalidateCachedRouter(): void public function seeCurrentActionIs(string $action): void { $router = $this->grabRouterService(); - $routes = $router->getRouteCollection()->getIterator(); foreach ($routes as $route) { @@ -128,7 +124,7 @@ public function seeCurrentRouteIs(string $routeName, array $params = []): void { $router = $this->grabRouterService(); if ($router->getRouteCollection()->get($routeName) === null) { - $this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); + $this->fail(sprintf('Route with name "%s" does not exist.', $routeName)); } $uri = explode('?', $this->grabFromCurrentUrl())[0]; @@ -160,7 +156,7 @@ public function seeInCurrentRoute(string $routeName): void { $router = $this->grabRouterService(); if ($router->getRouteCollection()->get($routeName) === null) { - $this->fail(sprintf('Route with name "%s" does not exists.', $routeName)); + $this->fail(sprintf('Route with name "%s" does not exist.', $routeName)); } $uri = explode('?', $this->grabFromCurrentUrl())[0]; diff --git a/src/Codeception/Module/Symfony/ServicesAssertionsTrait.php b/src/Codeception/Module/Symfony/ServicesAssertionsTrait.php index b53a72b8..bd9140c0 100644 --- a/src/Codeception/Module/Symfony/ServicesAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/ServicesAssertionsTrait.php @@ -20,7 +20,6 @@ trait ServicesAssertionsTrait * ``` * * @part services - * @param string $serviceId */ public function grabService(string $serviceId): object { @@ -69,15 +68,10 @@ public function persistPermanentService(string $serviceName): void */ public function unpersistService(string $serviceName): void { - if (isset($this->persistentServices[$serviceName])) { - unset($this->persistentServices[$serviceName]); - } - - if (isset($this->permanentServices[$serviceName])) { - unset($this->permanentServices[$serviceName]); - } + unset($this->persistentServices[$serviceName]); + unset($this->permanentServices[$serviceName]); - if ($this->client instanceof SymfonyConnector && isset($this->client->persistentServices[$serviceName])) { + if ($this->client instanceof SymfonyConnector) { unset($this->client->persistentServices[$serviceName]); } } diff --git a/src/Codeception/Module/Symfony/SessionAssertionsTrait.php b/src/Codeception/Module/Symfony/SessionAssertionsTrait.php index f6911303..a8b69afd 100644 --- a/src/Codeception/Module/Symfony/SessionAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/SessionAssertionsTrait.php @@ -29,37 +29,17 @@ trait SessionAssertionsTrait * ]); * $I->amLoggedInAs($user); * ``` - * - * @param UserInterface $user - * @param string $firewallName - * @param null $firewallContext */ - public function amLoggedInAs(UserInterface $user, string $firewallName = 'main', $firewallContext = null): void + public function amLoggedInAs(UserInterface $user, string $firewallName = 'main', string $firewallContext = null): void { $session = $this->getCurrentSession(); + $roles = $user->getRoles(); - if ($this->getSymfonyMajorVersion() < 6) { - if ($this->config['guard']) { - $token = new PostAuthenticationGuardToken($user, $firewallName, $user->getRoles()); - } else { - $token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles()); - } - } else { - if ($this->config['authenticator']) { - $token = new PostAuthenticationToken($user, $firewallName, $user->getRoles()); - } else { - $token = new UsernamePasswordToken($user, $firewallName, $user->getRoles()); - } - } - + $token = $this->createAuthenticationToken($user, $firewallName, $roles); $this->getTokenStorage()->setToken($token); - if ($firewallContext) { - $session->set('_security_' . $firewallContext, serialize($token)); - } else { - $session->set('_security_' . $firewallName, serialize($token)); - } - + $sessionKey = $firewallContext ? "_security_{$firewallContext}" : "_security_{$firewallName}"; + $session->set($sessionKey, serialize($token)); $session->save(); $cookie = new Cookie($session->getName(), $session->getId()); @@ -74,16 +54,13 @@ public function amLoggedInAs(UserInterface $user, string $firewallName = 'main', * $I->dontSeeInSession('attribute'); * $I->dontSeeInSession('attribute', 'value'); * ``` - * */ public function dontSeeInSession(string $attribute, mixed $value = null): void { $session = $this->getCurrentSession(); - if ($attributeExists = $session->has($attribute)) { - $this->fail("Session attribute with name '{$attribute}' does exist"); - } - $this->assertFalse($attributeExists); + $attributeExists = $session->has($attribute); + $this->assertFalse($attributeExists, "Session attribute '{$attribute}' exists."); if (null !== $value) { $this->assertNotSame($value, $session->get($attribute)); @@ -98,8 +75,7 @@ public function dontSeeInSession(string $attribute, mixed $value = null): void */ public function goToLogoutPath(): void { - $logoutUrlGenerator = $this->getLogoutUrlGenerator(); - $logoutPath = $logoutUrlGenerator->getLogoutPath(); + $logoutPath = $this->getLogoutUrlGenerator()->getLogoutPath(); $this->amOnPage($logoutPath); } @@ -132,17 +108,14 @@ public function logoutProgrammatically(): void } $session = $this->getCurrentSession(); - $sessionName = $session->getName(); $session->invalidate(); $cookieJar = $this->client->getCookieJar(); + $cookiesToExpire = ['MOCKSESSID', 'REMEMBERME', $sessionName]; foreach ($cookieJar->all() as $cookie) { $cookieName = $cookie->getName(); - if ($cookieName === 'MOCKSESSID' || - $cookieName === 'REMEMBERME' || - $cookieName === $sessionName - ) { + if (in_array($cookieName, $cookiesToExpire, true)) { $cookieJar->expire($cookieName); } } @@ -163,10 +136,8 @@ public function seeInSession(string $attribute, mixed $value = null): void { $session = $this->getCurrentSession(); - if (!$attributeExists = $session->has($attribute)) { - $this->fail("No session attribute with name '{$attribute}'"); - } - $this->assertTrue($attributeExists); + $attributeExists = $session->has($attribute); + $this->assertTrue($attributeExists, "No session attribute with name '{$attribute}'"); if (null !== $value) { $this->assertSame($value, $session->get($attribute)); @@ -181,8 +152,6 @@ public function seeInSession(string $attribute, mixed $value = null): void * $I->seeSessionHasValues(['key1', 'key2']); * $I->seeSessionHasValues(['key1' => 'value1', 'key2' => 'value2']); * ``` - * - * @param array $bindings */ public function seeSessionHasValues(array $bindings): void { @@ -227,4 +196,20 @@ protected function getSymfonyMajorVersion(): int { return $this->kernel::MAJOR_VERSION; } + + /** + * @return UsernamePasswordToken|PostAuthenticationGuardToken|PostAuthenticationToken + */ + protected function createAuthenticationToken(UserInterface $user, string $firewallName, array $roles) + { + if ($this->getSymfonyMajorVersion() < 6) { + return $this->config['guard'] + ? new PostAuthenticationGuardToken($user, $firewallName, $roles) + : new UsernamePasswordToken($user, null, $firewallName, $roles); + } + + return $this->config['authenticator'] + ? new PostAuthenticationToken($user, $firewallName, $roles) + : new UsernamePasswordToken($user, $firewallName, $roles); + } } diff --git a/src/Codeception/Module/Symfony/TimeAssertionsTrait.php b/src/Codeception/Module/Symfony/TimeAssertionsTrait.php index d48222eb..136bef25 100644 --- a/src/Codeception/Module/Symfony/TimeAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/TimeAssertionsTrait.php @@ -36,7 +36,7 @@ public function seeRequestTimeIsLessThan(int|float $expectedMilliseconds): void $expectedMilliseconds, $actualMilliseconds, sprintf( - 'The request was expected to last less than %d ms, but it actually lasted %d ms.', + 'The request duration was expected to be less than %d ms, but it was actually %d ms.', $expectedMilliseconds, $actualMilliseconds ) diff --git a/src/Codeception/Module/Symfony/TwigAssertionsTrait.php b/src/Codeception/Module/Symfony/TwigAssertionsTrait.php index 624b822e..52b02d0d 100644 --- a/src/Codeception/Module/Symfony/TwigAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/TwigAssertionsTrait.php @@ -16,8 +16,6 @@ trait TwigAssertionsTrait * dontSeeRenderedTemplate('home.html.twig'); * ``` - * - * @param string $template */ public function dontSeeRenderedTemplate(string $template): void { @@ -39,15 +37,13 @@ public function dontSeeRenderedTemplate(string $template): void * seeCurrentTemplateIs('home.html.twig'); * ``` - * - * @param string $expectedTemplate */ public function seeCurrentTemplateIs(string $expectedTemplate): void { $twigCollector = $this->grabTwigCollector(__FUNCTION__); $templates = (array)$twigCollector->getTemplates(); - $actualTemplate = (string)array_key_first($templates); + $actualTemplate = !empty($templates) ? (string) array_key_first($templates) : 'N/A'; $this->assertSame( $expectedTemplate, @@ -65,8 +61,6 @@ public function seeCurrentTemplateIs(string $expectedTemplate): void * $I->seeRenderedTemplate('home.html.twig'); * $I->seeRenderedTemplate('layout.html.twig'); * ``` - * - * @param string $template */ public function seeRenderedTemplate(string $template): void {
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: