8000 added PHPUnit constraints and assertions for the Mailer · symfony/symfony@9ea3b0e · GitHub
[go: up one dir, main page]

Skip to content

Commit 9ea3b0e

Browse files
committed
added PHPUnit constraints and assertions for the Mailer
1 parent fdaf0e0 commit 9ea3b0e

22 files changed

+677
-11
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
4.4.0
55
-----
66

7+
* Added `MailerAssertionsTrait`
78
* Deprecated support for `templating` engine in `TemplateController`, use Twig instead
89
* Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()`
910
* Deprecated the `controller_name_converter` and `resolve_controller_name_subscriber` services

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,10 +553,6 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $
553553
$loader->load('messenger_debug.xml');
554554
}
555555

556-
if (class_exists(Mailer::class)) {
557-
$loader->load('mailer_debug.xml');
558-
}
559-
560556
$container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
561557
$container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']);
562558

@@ -1969,6 +1965,9 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
19691965
}
19701966

19711967
$loader->load('mailer.xml');
1968+
if ($container->getParameter('kernel.debug')) {
1969+
$loader->load('mailer_debug.xml');
1970+
}
19721971
$loader->load('mailer_transports.xml');
19731972
$container->getDefinition('mailer.default_transport')->setArgument(0, $config['dsn']);
19741973

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Test;
13+
14+
use PHPUnit\Framework\Constraint\LogicalNot;
15+
use Symfony\Component\Mailer\Event\MessageEvent;
16+
use Symfony\Component\Mailer\Event\MessageEvents;
17+
use Symfony\Component\Mailer\Test\Constraint as MailerConstraint;
18+
use Symfony\Component\Mime\RawMessage;
19+
use Symfony\Component\Mime\Test\Constraint as MimeConstraint;
20+
21+
trait MailerAssertionsTrait
22+
{
23+
public static function assertEmailCount(int $count, string $transport = null, string $message = ''): void
24+
{
25+
self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport), $message);
26+
}
27+
28+
public static function assertEmailIsQueued(MessageEvent $event, string $message = ''): void
29+
{
30+
self::assertThat($event, new MailerConstraint\EmailIsQueued(), $message);
31+
}
32+
33+
public static function assertEmailIsNotQueued(MessageEvent $event, string $message = ''): void
34+
{
35+
self::assertThat($event, new LogicalNot(new MailerConstraint\EmailIsQueued()), $message);
36+
}
37+
38+
public static function assertEmailAttachementCount(RawMessage $email, int $count, string $message = ''): void
39+
{
40+
self::assertThat($email, new MimeConstraint\EmailAttachmentCount($count), $message);
41+
}
42+
43+
public static function assertEmailTextBodyContains(RawMessage $email, string $text, string $message = ''): void
44+
{
45+
self::assertThat($email, new MimeConstraint\EmailTextBodyContains($text), $message);
46+
}
47+
48+
public static function assertEmailTextBodyNotContains(RawMessage $email, string $text, string $message = ''): void
49+
{
50+
self::assertThat($email, new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)), $message);
51+
}
52+
53+
public static function assertEmailHtmlBodyContains(RawMessage $email, string $text, string $message = ''): void
54+
{
55+
self::assertThat($email, new MimeConstraint\EmailHtmlBodyContains($text), $message);
56+
}
57+
58+
public static function assertEmailHtmlBodyNotContains(RawMessage $email, string $text, string $message = ''): void
59+
{
60+
self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHtmlBodyContains($text)), $message);
61+
}
62+
63+
public static function assertEmailHasHeader(RawMessage $email, string $headerName, string $message = ''): void
64+
{
65+
self::assertThat($email, new MimeConstraint\EmailHasHeader($headerName), $message);
66+
}
67+
68+
public static function assertEmailNotHasHeader(RawMessage $email, string $headerName, string $message = ''): void
69+
{
70+
self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHasHeader($headerName)), $message);
71+
}
72+
73+
public static function assertEmailHeaderSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
74+
{
75+
self::assertThat($email, new MimeConstraint\EmailHeaderSame($headerName, $expectedValue), $message);
76+
}
77+
78+
public static function assertEmailHeaderNotSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
79+
{
80+
self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHeaderSame($headerName, $expectedValue)), $message);
81+
}
82+
83+
public static function assertEmailAddressContains(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void
84+
{
85+
self::assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue), $message);
86+
}
87+
88+
/**
89+
* @return MessageEvents[]
90+
*/
91+
public static function getMailerEvents(string $transport = null): array
92+
{
93+
return self::getMessageMailerEvents()->getEvents($transport);
94+
}
95+
96+
public static function getMailerEvent(int $index = 0, string $transport = null): ?MessageEvent
97+
{
98+
return self::getMailerEvents($transport)[$index] ?? null;
99+
}
100+
101+
/**
102+
* @return RawMessage[]
103+
*/
104+
public static function getMailerMessages(string $transport = null): array
105+
{
106+
return self::getMessageMailerEvents()->getMessages($transport);
107+
}
108+
109+
public static function getMailerMessage(int $index = 0, string $transport = null): ?RawMessage
110+
{
111+
return self::getMailerMessages($transport)[$index] ?? null;
112+
}
113+
114+
private static function getMessageMailerEvents(): MessageEvents
115+
{
116+
if (!self::getClient()->getRequest()) {
117+
static::fail('Unable to make email assertions. Did you forget to make an HTTP request?');
118+
}
119+
120+
if (!$logger = self::$container->get('mailer.logger_message_listener')) {
121+
static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?');
122+
}
123+
124+
return $logger->getEvents();
125+
}
126+
}

src/Symfony/Bundle/FrameworkBundle/Test/WebTestAssertionsTrait.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Test;
1313

14-
/**
15-
* Ideas borrowed from Laravel Dusk's assertions.
16-
*
17-
* @see https://laravel.com/docs/5.7/dusk#available-assertions
18-
*/
1914
trait WebTestAssertionsTrait
2015
{
2116
use BrowserKitAssertionsTrait;

src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ abstract class WebTestCase extends KernelTestCase
2323
{
2424
use ForwardCompatTestTrait;
2525
use WebTestAssertionsTrait;
26+
use MailerAssertionsTrait;
2627

2728
private function doTearDown()
2829
{
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Response;
15+
use Symfony\Component\Mailer\MailerInterface;
16+
use Symfony\Component\Mime\Email;
17+
use Symfony\Component\Mime\NamedAddress;
18+
19+
class EmailController
20+
{
21+
public function indexAction(MailerInterface $mailer)
22+
{
23+
$mailer->send((new Email())->to('fabien@symfony.com')->from('fabien@symfony.com')->subject('Foo')
24+
->addReplyTo('me@symfony.com')
25+
->addCc('cc@symfony.com')
26+
->text('Bar!')
27+
->html('<p>Foo</p>')
28+
->attach(file_get_contents(__FILE__), 'foobar.php')
29+
);
30+
31+
$mailer->send((new Email())->to('fabien@symfony.com', 'thomas@symfony.com')->from('fabien@symfony.com')->subject('Foo')
32+
->addReplyTo(new NamedAddress('me@symfony.com', 'Fabien Potencier'))
33+
->addCc('cc@symfony.com')
34+
->text('Bar!')
35+
->html('<p>Foo</p>')
36+
->attach(file_get_contents(__FILE__), 'foobar.php')
37+
);
38+
39+
return new Response();
40+
}
41+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,7 @@ fragment_inlined:
5252
array_controller:
5353
path: /array_controller
5454
defaults: { _controller: [ArrayController, someAction] }
55+
56+
send_email:
57+
path: /send_email
58+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\EmailController::indexAction }

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,28 @@ protected function doSend(SentMessage $message): void
6464

6565
$mailer->send($message);
6666
}
67+
68+
public function testMailerAssertions()
69+
{
70+
$client = $this->createClient(['test_case' => 'Mailer', 'root_config' => 'config.yml', 'debug' => true]);
71+
$client->request('GET', '/send_email');
72+
73+
$this->assertEmailCount(2);
74+
$this->assertEmailIsQueued($this->getMailerEvent(0));
75+
76+
$email = $this->getMailerMessage(0);
77+
$this->assertEmailHasHeader($email, 'To');
78+
$this->assertEmailHeaderSame($email, 'To', 'fabien@symfony.com');
79+
$this->assertEmailHeaderNotSame($email, 'To', 'helene@symfony.com');
80+
$this->assertEmailTextBodyContains($email, 'Bar');
81+
$this->assertEmailTextBodyNotContains($email, 'Foo');
82+
$this->assertEmailHtmlBodyContains($email, 'Foo');
83+
$this->assertEmailHtmlBodyNotContains($email, 'Bar');
84+
$this->assertEmailAttachementCount($email, 1);
85+
86+
$email = $this->getMailerMessage(1);
87+
$this->assertEmailAddressContains($email, 'To', 'fabien@symfony.com');
88+
$this->assertEmailAddressContains($email, 'To', 'thomas@symfony.com');
89+
$this->assertEmailAddressContains($email, 'Reply-To', 'me@symfony.com');
90+
}
6791
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Mailer/config.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
imports:
22
- { resource: ../config/default.yml }
3+
- { resource: services.yml }
34

45
framework:
56
mailer:
7+
dsn: 'smtp://null'
68
envelope:
79
sender: sender@example.org
810
recipients:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_emailtest_bundle:
2+
resource: '@TestBundle/Resources/config/routing.yml'
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
services:
2+
_defaults:
3+
public: true
4+
5+
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\EmailController:
6+
tags: ['controller.service_arguments']

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
"symfony/expression-language": "^3.4|^4.0|^5.0",
4343
"symfony/http-client": "^4.3|^5.0",
4444
"symfony/lock": "^4.4|^5.0",
45-
"symfony/mailer": "^4.3|^5.0",
45+
"symfony/mailer": "^4.4|^5.0",
4646
"symfony/messenger": "^4.3|^5.0",
47-
"symfony/mime": "^4.3|^5.0",
47+
"symfony/mime": "^4.4|^5.0",
4848
"symfony/process": "^3.4|^4.0|^5.0",
4949
"symfony/security-csrf": "^3.4|^4.0|^5.0",
5050
"symfony/security-http": "^3.4|^4.0|^5.0",
@@ -76,6 +76,7 @@
7676
"symfony/lock": "<4.4",
7777
"symfony/mailer": "<4.4",
7878
"symfony/messenger": "<4.3",
79+
"symfony/mime": "<4.4",
7980
"symfony/property-info": "<3.4",
8081
"symfony/serializer": "<4.2",
8182
"symfony/stopwatch": "<3.4",

src/Symfony/Component/Mailer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
4.4.0
55
-----
66

7+
* Added PHPUnit constraints
78
* Added `MessageDataCollector`
89
* Added `MessageEvents` and `MessageLoggerListener` to allow collecting sent emails
910
* [BC BREAK] `TransportInterface` has a new `getName()` method
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Mailer\Test\Constraint;
13+
14+
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\Mailer\Event\MessageEvents;
16+
17+
final class EmailCount extends Constraint
18+
{
19+
private $expectedValue;
20+
private $transport;
21+
22+
public function __construct(int $expectedValue, string $transport = null)
23+
{
24+
$this->expectedValue = $expectedValue;
25+
$this->transport = $transport;
26+
}
27+
28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function toString(): string
32+
{
33+
return sprintf('%shas sent "%d" emails', $this->transport ? $this->transport.' ' : '', $this->expectedValue);
34+
}
35+
36+
/**
37+
* @param MessageEvents $events
38+
*
39+
* {@inheritdoc}
40+
*/
41+
protected function matches($events): bool
42+
{
43+
return $this->expectedValue === \count($events->getEvents($this->transport));
44+
}
45+
46+
/**
47+
* @param MessageEvents $events
48+
*
49+
* {@inheritdoc}
50+
*/
51+
protected function failureDescription($events): string
52+
{
53+
return sprintf('the Transport %s (%d sent)', $this->toString(), \count($events->getEvents($this->transport)));
54+
}
55+
}

0 commit comments

Comments
 (0)
0