Skip to content

Commit

Permalink
[feature] add TestEmail tag/metadata access/assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Sep 30, 2021
1 parent 14a87b8 commit b39b4ea
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class MyTest extends KernelTestCase // or WebTestCase
->assertHtmlContains('some text')
->assertContains('some text') // asserts text and html both contain a value
->assertHasFile('file.txt', 'text/plain', 'Hello there!')

// tag/meta data assertions (https://symfony.com/doc/current/mailer.html#adding-tags-and-metadata-to-emails)
->assertHasTag('password-reset')
->assertHasMetadata('Color')
->assertHasMetadata('Color', 'blue')
;

// Any \Symfony\Component\Mime\Email methods can be used
Expand Down
74 changes: 74 additions & 0 deletions src/TestEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Zenstruck\Mailer\Test;

use Symfony\Component\Mailer\Header\MetadataHeader;
use Symfony\Component\Mailer\Header\TagHeader;
use Symfony\Component\Mime\Email;
use Zenstruck\Assert;

Expand All @@ -24,6 +26,54 @@ final public function __call($name, $arguments)
return $this->email->{$name}(...$arguments);
}

/**
* @return string|null The first {@see TagHeader} value found or null if none
*/
final public function tag(): ?string
{
return $this->tags()[0] ?? null;
}

/**
* @return string[] The {@see TagHeader} values
*/
final public function tags(): array
{
if (!\class_exists(TagHeader::class)) {
throw new \BadMethodCallException('Tags can only be used in symfony/mailer 5.1+.');
}

$tags = [];

foreach ($this->getHeaders()->all() as $header) {
if ($header instanceof TagHeader) {
$tags[] = $header->getValue();
}
}

return $tags;
}

/**
* @return array<string, string> The {@see MetadataHeader} keys/values
*/
final public function metadata(): array
{
if (!\class_exists(MetadataHeader::class)) {
throw new \BadMethodCallException('Metadata can only be used in symfony/mailer 5.1+.');
}

$metadata = [];

foreach ($this->getHeaders()->all() as $header) {
if ($header instanceof MetadataHeader) {
$metadata[$header->getKey()] = $header->getValue();
}
}

return $metadata;
}

final public function assertSubject(string $expected): self
{
Assert::that($this->email->getSubject())->is($expected);
Expand Down Expand Up @@ -157,4 +207,28 @@ final public function assertHasFile(string $expectedFilename, string $expectedCo

Assert::fail("Message does not include file with filename [{$expectedFilename}]");
}

final public function assertHasTag(string $expected): self
{
Assert::that($this->tags())
->isNotEmpty('No tags found.')
->contains($expected, 'Expected to have tag "{needle}".')
;

return $this;
}

final public function assertHasMetadata(string $expectedKey, ?string $expectedValue = null): self
{
Assert::that($metadata = $this->metadata())->isNotEmpty('No metadata found.');
Assert::that(\array_keys($metadata))->contains($expectedKey, 'Expected to have metadata key "{needle}".');

if (null !== $expectedValue) {
Assert::that($metadata[$expectedKey])->is($expectedValue, 'Expected metadata "{key}" to be "{expected}".', [
'key' => $expectedKey,
]);
}

return $this;
}
}
11 changes: 11 additions & 0 deletions tests/Fixture/Email1.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Zenstruck\Mailer\Test\Tests\Fixture;

use Symfony\Component\Mailer\Header\MetadataHeader;
use Symfony\Component\Mailer\Header\TagHeader;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;

Expand All @@ -25,5 +27,14 @@ public function __construct()
->html('html body')
->text('text body')
;

if (\class_exists(TagHeader::class)) {
$this->getHeaders()
->add(new TagHeader('foo'))
->add(new TagHeader('bar'))
->add(new MetadataHeader('color', 'blue'))
->add(new MetadataHeader('id', '5'))
;
}
}
}
101 changes: 101 additions & 0 deletions tests/TestEmailTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace Zenstruck\Mailer\Test\Tests;

use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mailer\Header\TagHeader;
use Symfony\Component\Mime\Email;
use Zenstruck\Assert;
use Zenstruck\Mailer\Test\TestEmail;
use Zenstruck\Mailer\Test\Tests\Fixture\Email1;

/**
* @author Kevin Bond <kevinbond@gmail.com>
*/
final class TestEmailTest extends TestCase
{
/**
* @test
*/
public function can_access_tags(): void
{
$this->requiresMailer51();

$noTags = new TestEmail(new Email());

$this->assertNull($noTags->tag());
$this->assertSame([], $noTags->tags());

$withTags = new TestEmail(new Email1());

$this->assertSame('foo', $withTags->tag());
$this->assertSame(['foo', 'bar'], $withTags->tags());
}

/**
* @test
*/
public function can_access_metadata(): void
{
$this->requiresMailer51();

$noMetadata = new TestEmail(new Email());

$this->assertSame([], $noMetadata->metadata());

$withMetadata = new TestEmail(new Email1());

$this->assertSame(['color' => 'blue', 'id' => '5'], $withMetadata->metadata());
}

/**
* @test
*/
public function can_assert_has_tag(): void
{
$this->requiresMailer51();

$withTags = new TestEmail(new Email1());

$withTags->assertHasTag('foo');
$withTags->assertHasTag('bar');

Assert::that(fn() => $withTags->assertHasTag('baz'))->throws(
AssertionFailedError::class, 'Expected to have tag "baz".'
);
Assert::that(fn() => (new TestEmail(new Email()))->assertHasTag('foo'))->throws(
AssertionFailedError::class, 'No tags found.'
);
}

/**
* @test
*/
public function can_assert_has_metadata(): void
{
$this->requiresMailer51();

$withMetadata = new TestEmail(new Email1());

$withMetadata->assertHasMetadata('color');
$withMetadata->assertHasMetadata('color', 'blue');

Assert::that(fn() => $withMetadata->assertHasMetadata('color', 'red'))->throws(
AssertionFailedError::class, 'Expected metadata "color" to be "red".'
);
Assert::that(fn() => $withMetadata->assertHasMetadata('foo'))->throws(
AssertionFailedError::class, 'Expected to have metadata key "foo"'
);
Assert::that(fn() => (new TestEmail(new Email()))->assertHasMetadata('foo'))->throws(
AssertionFailedError::class, 'No metadata found.'
);
}

private function requiresMailer51(): void
{
if (!\class_exists(TagHeader::class)) {
$this->markTestSkipped('Requires symfony/mailer 5.1+');
}
}
}

0 comments on commit b39b4ea

Please sign in to comment.