Skip to content

Commit 58aa938

Browse files
committed
RateLimitedCampaignMailerTest
1 parent 2f911ca commit 58aa938

File tree

2 files changed

+144
-2
lines changed

2 files changed

+144
-2
lines changed

src/Domain/Messaging/Service/RateLimitedCampaignMailer.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,16 @@ public function __construct(MailerInterface $mailer, SendRateLimiter $limiter)
2222

2323
public function composeEmail(Message $processed, Subscriber $subscriber): Email
2424
{
25-
return (new Email())
26-
25+
$email = new Email();
26+
if ($processed->getOptions()->getFromField() !== '') {
27+
$email->from($processed->getOptions()->getFromField());
28+
}
29+
30+
if ($processed->getOptions()->getReplyTo() !== '') {
31+
$email->replyTo($processed->getOptions()->getReplyTo());
32+
}
33+
34+
return $email
2735
->to($subscriber->getEmail())
2836
->subject($processed->getContent()->getSubject())
2937
->text($processed->getContent()->getTextMessage())
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Tests\Unit\Domain\Messaging\Service;
6+
7+
use PhpList\Core\Domain\Messaging\Model\Message;
8+
use PhpList\Core\Domain\Messaging\Model\Message\MessageContent;
9+
use PhpList\Core\Domain\Messaging\Model\Message\MessageFormat;
10+
use PhpList\Core\Domain\Messaging\Model\Message\MessageMetadata;
11+
use PhpList\Core\Domain\Messaging\Model\Message\MessageOptions;
12+
use PhpList\Core\Domain\Messaging\Model\Message\MessageSchedule;
13+
use PhpList\Core\Domain\Messaging\Service\RateLimitedCampaignMailer;
14+
use PhpList\Core\Domain\Messaging\Service\SendRateLimiter;
15+
use PhpList\Core\Domain\Subscription\Model\Subscriber;
16+
use PHPUnit\Framework\MockObject\MockObject;
17+
use PHPUnit\Framework\TestCase;
18+
use ReflectionProperty;
19+
use Symfony\Component\Mailer\MailerInterface;
20+
use Symfony\Component\Mime\Email;
21+
22+
class RateLimitedCampaignMailerTest extends TestCase
23+
{
24+
private MailerInterface|MockObject $mailer;
25+
private SendRateLimiter|MockObject $limiter;
26+
27+
private RateLimitedCampaignMailer $sut;
28+
29+
protected function setUp(): void
30+
{
31+
$this->mailer = $this->createMock(MailerInterface::class);
32+
$this->limiter = $this->createMock(SendRateLimiter::class);
33+
$this->sut = new RateLimitedCampaignMailer($this->mailer, $this->limiter);
34+
}
35+
36+
public function testComposeEmailSetsHeadersAndBody(): void
37+
{
38+
$message = $this->buildMessage(
39+
subject: 'Subject',
40+
textBody: 'Plain text',
41+
htmlBody: '<p>HTML</p>',
42+
43+
replyTo: '[email protected]'
44+
);
45+
46+
$subscriber = new Subscriber();
47+
$this->setSubscriberEmail($subscriber, '[email protected]');
48+
49+
$email = $this->sut->composeEmail($message, $subscriber);
50+
51+
$this->assertInstanceOf(Email::class, $email);
52+
$this->assertSame('[email protected]', $email->getTo()[0]->getAddress());
53+
$this->assertSame('Subject', $email->getSubject());
54+
$this->assertSame('[email protected]', $email->getFrom()[0]->getAddress());
55+
$this->assertSame('[email protected]', $email->getReplyTo()[0]->getAddress());
56+
$this->assertSame('Plain text', $email->getTextBody());
57+
$this->assertSame('<p>HTML</p>', $email->getHtmlBody());
58+
}
59+
60+
public function testComposeEmailWithoutOptionalHeaders(): void
61+
{
62+
$message = $this->buildMessage(
63+
subject: 'No headers',
64+
textBody: 'text',
65+
htmlBody: '<b>h</b>',
66+
from: '',
67+
replyTo: ''
68+
);
69+
70+
$subscriber = new Subscriber();
71+
$this->setSubscriberEmail($subscriber, '[email protected]');
72+
73+
$email = $this->sut->composeEmail($message, $subscriber);
74+
75+
$this->assertSame('[email protected]', $email->getTo()[0]->getAddress());
76+
$this->assertSame('No headers', $email->getSubject());
77+
$this->assertSame([], $email->getFrom());
78+
$this->assertSame([], $email->getReplyTo());
79+
}
80+
81+
public function testSendUsesLimiterAroundMailer(): void
82+
{
83+
$email = (new Email())->to('[email protected]');
84+
85+
$this->limiter->expects($this->once())->method('awaitTurn');
86+
$this->mailer
87+
->expects($this->once())
88+
->method('send')
89+
->with($this->isInstanceOf(Email::class));
90+
$this->limiter->expects($this->once())->method('afterSend');
91+
92+
$this->sut->send($email);
93+
}
94+
95+
private function buildMessage(
96+
string $subject,
97+
string $textBody,
98+
string $htmlBody,
99+
string $from,
100+
string $replyTo
101+
): Message {
102+
$content = new MessageContent(
103+
subject: $subject,
104+
text: $htmlBody,
105+
textMessage: $textBody,
106+
footer: null,
107+
);
108+
$format = new MessageFormat(
109+
htmlFormatted: true,
110+
sendFormat: MessageFormat::FORMAT_HTML,
111+
formatOptions: [MessageFormat::FORMAT_HTML]
112+
);
113+
$schedule = new MessageSchedule(
114+
repeatInterval: 0,
115+
repeatUntil: null,
116+
requeueInterval: 0,
117+
requeueUntil: null,
118+
embargo: null
119+
);
120+
$metadata = new MessageMetadata();
121+
$options = new MessageOptions(fromField: $from, toField: '', replyTo: $replyTo);
122+
123+
return new Message($format, $schedule, $metadata, $content, $options, null, null);
124+
}
125+
126+
/**
127+
* Subscriber has no public setter for email, so we use reflection.
128+
*/
129+
private function setSubscriberEmail(Subscriber $subscriber, string $email): void
130+
{
131+
$ref = new ReflectionProperty($subscriber, 'email');
132+
$ref->setValue($subscriber, $email);
133+
}
134+
}

0 commit comments

Comments
 (0)