Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TestEmail tag/metadata access/assertions #10

Merged
merged 1 commit into from
Sep 30, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
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+');
}
}
}