Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
17 changes: 17 additions & 0 deletions src/Codeception/Module/Symfony.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Codeception\Module\Symfony\LoggerAssertionsTrait;
use Codeception\Module\Symfony\MailerAssertionsTrait;
use Codeception\Module\Symfony\MimeAssertionsTrait;
use Codeception\Module\Symfony\NotifierAssertionsTrait;
use Codeception\Module\Symfony\ParameterAssertionsTrait;
use Codeception\Module\Symfony\RouterAssertionsTrait;
use Codeception\Module\Symfony\SecurityAssertionsTrait;
Expand Down Expand Up @@ -52,6 +53,7 @@
use Symfony\Component\HttpKernel\Profiler\Profile;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\Mailer\DataCollector\MessageDataCollector;
use Symfony\Component\Notifier\DataCollector\NotificationDataCollector;
use Symfony\Component\Translation\DataCollector\TranslationDataCollector;
use Symfony\Component\VarDumper\Cloner\Data;

Expand Down Expand Up @@ -156,6 +158,7 @@
use LoggerAssertionsTrait;
use MailerAssertionsTrait;
use MimeAssertionsTrait;
use NotifierAssertionsTrait;
use ParameterAssertionsTrait;
use RouterAssertionsTrait;
use SecurityAssertionsTrait;
Expand Down Expand Up @@ -402,7 +405,7 @@
/**
* Grab a Symfony Data Collector from the current profile.
*
* @phpstan-return (

Check failure on line 408 in src/Codeception/Module/Symfony.php

View workflow job for this annotation

GitHub Actions / tests (8.2, 7.3.*)

PHPDoc tag `@phpstan-return` has invalid value (( $collector is DataCollectorName::EVENTS ? EventDataCollector : ($collector is DataCollectorName::FORM ? FormDataCollector : ($collector is DataCollectorName::HTTP_CLIENT ? HttpClientDataCollector : ($collector is DataCollectorName::LOGGER ? LoggerDataCollector : ($collector is DataCollectorName::TIME ? TimeDataCollector : ($collector is DataCollectorName::TRANSLATION ? TranslationDataCollector : ($collector is DataCollectorName::TWIG ? TwigDataCollector : ($collector is DataCollectorName::SECURITY ? SecurityDataCollector : ($collector is DataCollectorName::MAILER ? MessageDataCollector : ($collector is DataCollectorName::NOTIFIER ? NotificationDataCollector : DataCollectorInterface )))))))) )): Unexpected token "@throws", expected ')' at offset 955 on line 19

Check failure on line 408 in src/Codeception/Module/Symfony.php

View workflow job for this annotation

GitHub Actions / tests (8.3, 7.3.*)

PHPDoc tag `@phpstan-return` has invalid value (( $collector is DataCollectorName::EVENTS ? EventDataCollector : ($collector is DataCollectorName::FORM ? FormDataCollector : ($collector is DataCollectorName::HTTP_CLIENT ? HttpClientDataCollector : ($collector is DataCollectorName::LOGGER ? LoggerDataCollector : ($collector is DataCollectorName::TIME ? TimeDataCollector : ($collector is DataCollectorName::TRANSLATION ? TranslationDataCollector : ($collector is DataCollectorName::TWIG ? TwigDataCollector : ($collector is DataCollectorName::SECURITY ? SecurityDataCollector : ($collector is DataCollectorName::MAILER ? MessageDataCollector : ($collector is DataCollectorName::NOTIFIER ? NotificationDataCollector : DataCollectorInterface )))))))) )): Unexpected token "@throws", expected ')' at offset 955 on line 19

Check failure on line 408 in src/Codeception/Module/Symfony.php

View workflow job for this annotation

GitHub Actions / tests (8.4, 7.3.*)

PHPDoc tag `@phpstan-return` has invalid value (( $collector is DataCollectorName::EVENTS ? EventDataCollector : ($collector is DataCollectorName::FORM ? FormDataCollector : ($collector is DataCollectorName::HTTP_CLIENT ? HttpClientDataCollector : ($collector is DataCollectorName::LOGGER ? LoggerDataCollector : ($collector is DataCollectorName::TIME ? TimeDataCollector : ($collector is DataCollectorName::TRANSLATION ? TranslationDataCollector : ($collector is DataCollectorName::TWIG ? TwigDataCollector : ($collector is DataCollectorName::SECURITY ? SecurityDataCollector : ($collector is DataCollectorName::MAILER ? MessageDataCollector : ($collector is DataCollectorName::NOTIFIER ? NotificationDataCollector : DataCollectorInterface )))))))) )): Unexpected token "@throws", expected ')' at offset 955 on line 19
* $collector is DataCollectorName::EVENTS ? EventDataCollector :
* ($collector is DataCollectorName::FORM ? FormDataCollector :
* ($collector is DataCollectorName::HTTP_CLIENT ? HttpClientDataCollector :
Expand All @@ -412,6 +415,7 @@
* ($collector is DataCollectorName::TWIG ? TwigDataCollector :
* ($collector is DataCollectorName::SECURITY ? SecurityDataCollector :
* ($collector is DataCollectorName::MAILER ? MessageDataCollector :
* ($collector is DataCollectorName::NOTIFIER ? NotificationDataCollector :
* DataCollectorInterface
* ))))))))
* )
Expand Down Expand Up @@ -465,6 +469,13 @@
}
}

if ($profile->hasCollector(DataCollectorName::NOTIFIER->value)) {
$notifierCollector = $profile->getCollector(DataCollectorName::NOTIFIER->value);
if ($notifierCollector instanceof NotificationDataCollector) {
$this->debugNotifierData($notifierCollector);
}
}

if ($profile->hasCollector(DataCollectorName::TIME->value)) {
$timeCollector = $profile->getCollector(DataCollectorName::TIME->value);
if ($timeCollector instanceof TimeDataCollector) {
Expand Down Expand Up @@ -543,6 +554,12 @@
$this->debugSection('Emails', sprintf('%d sent', $count));
}

private function debugNotifierData(NotificationDataCollector $notificationCollector): void
{
$count = count($notificationCollector->getEvents()->getMessages());
$this->debugSection('Notifications', sprintf('%d sent', $count));
}

private function debugTimeData(TimeDataCollector $timeCollector): void
{
$this->debugSection('Time', sprintf('%.2f ms', $timeCollector->getDuration()));
Expand Down
1 change: 1 addition & 0 deletions src/Codeception/Module/Symfony/DataCollectorName.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ enum DataCollectorName: string
case TWIG = 'twig';
case SECURITY = 'security';
case MAILER = 'mailer';
case NOTIFIER = 'notifier';
}
257 changes: 257 additions & 0 deletions src/Codeception/Module/Symfony/NotifierAssertionsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?php

declare(strict_types=1);

namespace Codeception\Module\Symfony;

use PHPUnit\Framework\Assert;
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\Notifier\Event\MessageEvent;
use Symfony\Component\Notifier\Event\NotificationEvents;
use Symfony\Component\Notifier\EventListener\NotificationLoggerListener;
use Symfony\Component\Notifier\Message\MessageInterface;
use Symfony\Component\Notifier\Test\Constraint as NotifierConstraint;
use Symfony\Component\HttpKernel\Kernel;

trait NotifierAssertionsTrait
{
/**
* Asserts that the expected number of notifications was sent.
*
* ```php
* <?php
* $I->assertNotificationCount(2, 'smtp');
* ```
*/
public function assertNotificationCount(int $count, ?string $transportName = null, string $message = ''): void
{
$this->assertThat($this->getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName), $message);
}

/**
* Asserts that the given notifier event is not queued.
* Use `getNotifierEvent(int $index = 0, ?string $transportName = null)` to retrieve a notifier event by index.
*
* ```php
* <?php
* $event = $I->getNotifierEvent();
* $I->asserNotificationIsNotQueued($event);
* ```
*/
public function assertNotificationIsNotQueued(MessageEvent $event, string $message = ''): void
{
$this->assertThat($event, new LogicalNot(new NotifierConstraint\NotificationIsQueued()), $message);
}

/**
* Asserts that the given notifier event is queued.
* Use `getNotifierEvent(int $index = 0, ?string $transportName = null)` to retrieve a notifier event by index.
*
* ```php
* <?php
* $event = $I->getNotifierEvent();
* $I->assertNotificationlIsQueued($event);
* ```
*/
public function assertNotificationIsQueued(MessageEvent $event, string $message = ''): void
{
$this->assertThat($event, new NotifierConstraint\NotificationIsQueued(), $message);
}

/**
* Asserts that the given notification contains given subject.
* Use `getNotifierMessage(int $index = 0, ?string $transportName = null)` to retrieve a notification by index.
*
* ```php
* <?php
* $notification = $I->getNotifierMessage();
* $I->assertNotificationSubjectContains($notification, 'Subject');
* ```
*/
public function assertNotificationSubjectContains(MessageInterface $notification, string $text, string $message = ''): void
{
$this->assertThat($notification, new NotifierConstraint\NotificationSubjectContains($text), $message);
}

/**
* Asserts that the given notification does not contain given subject.
* Use `getNotifierMessage(int $index = 0, ?string $transportName = null)` to retrieve a notification by index.
*
* ```php
* <?php
* $notification = $I->getNotifierMessage();
* $I->assertNotificationSubjectNotContains($notification, 'Subject');
* ```
*/
public function assertNotificationSubjectNotContains(MessageInterface $notification, string $text, string $message = ''): void
{
$this->assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationSubjectContains($text)), $message);
}

/**
* Asserts that the given notification uses given transport.
* Use `getNotifierMessage(int $index = 0, ?string $transportName = null)` to retrieve a notification by index.
*
* ```php
* <?php
* $notification = $I->getNotifierMessage();
* $I->assertNotificationTransportIsEqual($notification, 'chat');
* ```
*/
public function assertNotificationTransportIsEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void
{
$this->assertThat($notification, new NotifierConstraint\NotificationTransportIsEqual($transportName), $message);
}

/**
* Asserts that the given notification does not use given transport.
* Use `getNotifierMessage(int $index = 0, ?string $transportName = null)` to retrieve a notification by index.
*
* ```php
* <?php
* $notification = $I->getNotifierMessage();
* $I->assertNotificationTransportIsNotEqual($notification, 'transport');
* ```
*/
public function assertNotificationTransportIsNotEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void
{
$this->assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationTransportIsEqual($transportName)), $message);
}

/**
* Asserts that the expected number of notifications was queued (e.g. using the Notifier component).
*
* ```php
* <?php
* $I->assertQueuedNotificationCount(1, 'smtp');
* ```
*/
public function assertQueuedNotificationCount(int $count, ?string $transportName = null, string $message = ''): void
{
$this->assertThat($this->getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName, true), $message);
}

/**
* Checks that no notification was sent.
* The check is based on `\Symfony\Component\Notifier\EventListener\NotificationLoggerListener`, which means:
* If your app performs an HTTP redirect, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first; otherwise this check will *always* pass.
*
* ```php
* <?php
* $I->dontSeeNotificationIsSent();
* ```
*/
public function dontSeeNotificationIsSent(): void
{
$this->assertThat($this->getNotificationEvents(), new NotifierConstraint\NotificationCount(0));
}

/**
* Returns the last sent notification.
* The check is based on `\Symfony\Component\Notifier\EventListener\NotificationLoggerListener`, which means:
* If your app performs an HTTP redirect after sending the notification, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
* See also: [grabSentNotifications()](https://codeception.com/docs/modules/Symfony#grabSentNotifications)
*
* ```php
* <?php
* $message = $I->grabLastSentNotification();
* $I->assertSame('Subject', $message->getSubject());
* ```
*/
public function grabLastSentNotification(): ?MessageInterface
{
$notification = $this->getNotifierMessages();
$lastNotification = end($notification);

return $lastNotification ?: null;
}


/**
* Returns an array of all sent notifications.
* The check is based on `\Symfony\Component\Notifier\EventListener\NotificationLoggerListener`, which means:
* If your app performs an HTTP redirect after sending the notification, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
* See also: [grabLastSentNotification()](https://codeception.com/docs/modules/Symfony#grabLastSentNotification)
*
* ```php
* <?php
* $notifications = $I->grabSentNotifications();
* ```
*
* @return MessageEvent[]
*/
public function grabSentNotifications(): array
{
return $this->getNotifierMessages();
}

/**
* Checks if the given number of notifications was sent (default `$expectedCount`: 1).
* The check is based on `\Symfony\Component\Notifier\EventListener\NotificationLoggerListener`, which means:
* If your app performs an HTTP redirect after sending the notification, you need to suppress it using [stopFollowingRedirects()](#stopFollowingRedirects) first.
*
* ```php
* <?php
* $I->seeNotificatoinIsSent(2);
* ```
*
* @param int $expectedCount The expected number of notifications sent
*/
public function seeNotificationIsSent(int $expectedCount = 1): void
{
$this->assertThat($this->getNotificationEvents(), new NotifierConstraint\NotificationCount($expectedCount));
}

public function getNotifierEvents(?string $transportName = null): array
{
return $this->getNotificationEvents()->getEvents($transportName);
}

/**
* Returns the notifier event at the specified index.
*
* ```php
* <?php
* $event = $I->getNotifierEvent();
* ```
*/
public function getNotifierEvent(int $index = 0, ?string $transportName = null): ?MessageEvent
{
return $this->getNotifierEvents($transportName)[$index] ?? null;
}

public function getNotifierMessages(?string $transportName = null): array
{
return $this->getNotificationEvents()->getMessages($transportName);
}

/**
* Returns the notifier message at the specified index.
*
* ```php
* <?php
* $message = $I->getNotifierMessage();
* ```
*/
public function getNotifierMessage(int $index = 0, ?string $transportName = null): ?MessageInterface
{
return $this->getNotifierMessages($transportName)[$index] ?? null;
}

protected function getNotificationEvents(): NotificationEvents
{
if (version_compare(Kernel::VERSION, '6.2', '<')) {
Assert::fail('Notifier assertions require Symfony 6.2 or higher.');
}

$notifier = $this->getService('notifier.notification_logger_listener');
if ($notifier instanceof NotificationLoggerListener) {
return $notifier->getEvents();
}
$notifier = $this->getService('notifier.logger_notification_listener');
if ($notifier instanceof NotificationLoggerListener) {
return $notifier->getEvents();
}
Assert::fail("Notifications can't be tested without Symfony Notifier service.");
}
}
Loading