Skip to content

Commit

Permalink
[feature] add more SentEmails collection filters
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Oct 8, 2021
1 parent edc7922 commit 58d2f7e
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/Bridge/Zenstruck/Browser/MailerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait MailerExtension
{
use SentEmailMixin;

public function sentEmails(): SentEmails
private function sentEmails(): SentEmails
{
return (new MailerComponent($this))->sentEmails();
}
Expand Down
25 changes: 8 additions & 17 deletions src/SentEmailMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

namespace Zenstruck\Mailer\Test;

use Symfony\Component\Mime\Address;
use Zenstruck\Assert;

/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
Expand Down Expand Up @@ -42,21 +39,15 @@ public function assertEmailSentTo(string $expectedTo, $callback): self
$callback = static fn(TestEmail $message) => $message->assertSubject($callback);
}

$foundToAddresses = [];

foreach ($this->sentEmails()->ensureSome() as $email) {
$toAddresses = \array_map(static fn(Address $address) => $address->getAddress(), $email->getTo());
$foundToAddresses[] = $toAddresses;

if (\in_array($expectedTo, $toAddresses, true)) {
// address matches
$email->call($callback);
$this->sentEmails()
->ensureSome('No emails have been sent.')
->whereTo($expectedTo)
->ensureSome('No email was sent to "{expected}".', ['expected' => $expectedTo])
->first()
->call($callback)
;

return $this;
}
}

Assert::fail(\sprintf('Email sent, but "%s" is not among to-addresses: %s', $expectedTo, \implode(', ', \array_merge(...$foundToAddresses))));
return $this;
}

abstract public function sentEmails(): SentEmails;
Expand Down
48 changes: 44 additions & 4 deletions src/SentEmails.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mailer\Event\MessageEvents;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\RawMessage;
use Zenstruck\Assert;
Expand Down Expand Up @@ -60,7 +61,7 @@ public static function fromEvents(MessageEvents $events): self
*
* @return T
*/
public function first(string $class = TestEmail::class): self
public function first(string $class = TestEmail::class): TestEmail
{
return $this->ensureSome()->all($class)[\array_key_first($this->emails)];
}
Expand All @@ -74,7 +75,7 @@ public function first(string $class = TestEmail::class): self
*
* @return T
*/
public function last(string $class = TestEmail::class): self
public function last(string $class = TestEmail::class): TestEmail
{
return $this->ensureSome()->all($class)[\array_key_last($this->emails)];
}
Expand Down Expand Up @@ -118,6 +119,31 @@ public function whereTag(string $tag): self
return $this->where(fn(TestEmail $email) => $email->tag() === $tag);
}

public function whereFrom(string $email): self
{
return $this->where(fn(Email $message) => self::emailsContain($message->getFrom(), $email));
}

public function whereTo(string $email): self
{
return $this->where(fn(Email $message) => self::emailsContain($message->getTo(), $email));
}

public function whereCc(string $email): self
{
return $this->where(fn(Email $message) => self::emailsContain($message->getCc(), $email));
}

public function whereBcc(string $email): self
{
return $this->where(fn(Email $message) => self::emailsContain($message->getBcc(), $email));
}

public function whereReplyTo(string $email): self
{
return $this->where(fn(Email $message) => self::emailsContain($message->getReplyTo(), $email));
}

public function dump(): self
{
\call_user_func(\function_exists('dump') ? 'dump' : 'var_dump', $this->raw());
Expand Down Expand Up @@ -168,10 +194,10 @@ public function assertNone(): self
return $this->assertCount(0);
}

public function ensureSome(): self
public function ensureSome(string $message = 'No emails.', array $context = []): self
{
if (0 === \count($this->emails)) {
Assert::fail('No emails have been sent.');
Assert::fail($message, $context);
}

return $this;
Expand All @@ -189,4 +215,18 @@ public function count(): int
{
return \count($this->emails);
}

/**
* @param Address[] $addresses
*/
private static function emailsContain(array $addresses, string $needle): bool
{
foreach ($addresses as $address) {
if ($address->getAddress() === $needle) {
return true;
}
}

return false;
}
}
2 changes: 1 addition & 1 deletion tests/InteractsWithMailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function assert_email_sent_to_fail(string $environment): void
self::$container->get('mailer')->send(new Email1());

$this->expectException(AssertionFailedError::class);
$this->expectExceptionMessage('Email sent, but "jim@example.com" is not among to-addresses: kevin@example.com');
$this->expectExceptionMessage('No email was sent to "jim@example.com".');

$this->mailer()->assertEmailSentTo('jim@example.com', 'subject');
}
Expand Down

0 comments on commit 58d2f7e

Please sign in to comment.