Skip to content

Commit e3548ff

Browse files
authored
Merge pull request #3 from eliashaeussler/feature/attachments
Add support for email attachments
2 parents d1b474b + d4c153a commit e3548ff

File tree

4 files changed

+265
-3
lines changed

4 files changed

+265
-3
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ Filters emails to only keep those that are received by the provided address
4646
openNextUnreadEmail()
4747
```
4848
Pops the most recent unread email and assigns it as the email to conduct tests on
49+
```
50+
openNextAttachmentInOpenedEmail()
51+
```
52+
Pops the next attachment and assigns it as the attachment to conduct tests on
4953

5054
### Example Test
5155
Here is a simple scenario where we test the content of an email. For a detailed list of all available test methods, please refer to the [Codeception Email Testing Framework][CodeceptionEmailTestingFramework].
@@ -82,5 +86,17 @@ $I->seeInOpenedEmailSubject('Your Password Reset Link');
8286
$I->seeInOpenedEmailTextBody('Follow this link to reset your password');
8387
$I->seeInOpenedEmailHtmlBody('<a href="https://www.example.org/">Follow this link to reset your password</a>');
8488
$I->seeInOpenedEmailRecipients('[email protected]');
89+
90+
// Validate if email has attachments
91+
$I->haveAttachmentsInOpenedEmail();
92+
93+
// Open next attachment
94+
$I->openNextAttachmentInOpenedEmail();
95+
96+
// Validate metadata of the attachment
97+
$I->seeInFilenameOfOpenedAttachment();
98+
$I->grabFilenameFromOpenedAttachment();
99+
$I->grabContentTypeFromOpenedAttachment();
100+
$I->grabSizeFromOpenedAttachment();
85101
```
86102

src/Mailpit.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ class Mailpit extends Module
5252
*/
5353
protected mixed $openedEmail;
5454

55+
/**
56+
* Contains the currently open attachment on the currently opened email.
57+
*/
58+
protected mixed $openedAttachment;
59+
5560
public function _initialize(): void
5661
{
5762
$url = trim($this->config['url'], '/') . ':' . $this->config['port'];
@@ -201,6 +206,16 @@ public function openNextUnreadEmail(): void
201206
$this->openedEmail = $this->getMostRecentUnreadEmail();
202207
}
203208

209+
/**
210+
* Open next attachment in opened email.
211+
*
212+
* Pops the next attachment and assigns it as the attachment to conduct tests on
213+
*/
214+
public function openNextAttachmentInOpenedEmail(): void
215+
{
216+
$this->openedAttachment = $this->getNextAttachmentInOpenedEmail();
217+
}
218+
204219
/**
205220
* Load headers, if not done yet and return the requested header
206221
*
@@ -267,6 +282,15 @@ protected function getOpenedEmail($fetchNextUnread = false)
267282
return $this->openedEmail;
268283
}
269284

285+
protected function getOpenedAttachment(bool $fetchNextAttachment = false): mixed
286+
{
287+
if ($fetchNextAttachment || $this->openedAttachment === null) {
288+
$this->openNextAttachmentInOpenedEmail();
289+
}
290+
291+
return $this->openedAttachment;
292+
}
293+
270294
/**
271295
* Get Most Recent Unread Email.
272296
*
@@ -485,6 +509,18 @@ protected function getUnreadInbox(): array
485509
return $this->unreadInbox;
486510
}
487511

512+
protected function getNextAttachmentInOpenedEmail(): mixed
513+
{
514+
if ($this->openedEmail === null) {
515+
$this->fail('No email is opened');
516+
}
517+
if ($this->openedEmail->Attachments === []) {
518+
$this->fail('No attachments in opened email');
519+
}
520+
521+
return array_shift($this->openedEmail->Attachments);
522+
}
523+
488524
/**
489525
* Sort Emails.
490526
*

src/TestsEmails.php

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
// todo:
66
// text & html content
7-
// attachments
87

98
trait TestsEmails
109
{
@@ -578,6 +577,122 @@ public function grabHeaderFromOpenedEmail(string $header): array
578577
$email = $this->getOpenedEmail();
579578
return $this->getHeader($email, $header);
580579
}
581-
}
582580

583-
;
581+
/**
582+
* Assert opened email does not have attachments.
583+
*/
584+
public function dontHaveAttachmentsInOpenedEmail(): void
585+
{
586+
$email = $this->getOpenedEmail();
587+
$this->assertSame([], $email->Attachments ?? []);
588+
}
589+
590+
/**
591+
* Assert opened email has attachments.
592+
*/
593+
public function haveAttachmentsInOpenedEmail(): void
594+
{
595+
$email = $this->getOpenedEmail();
596+
$this->assertNotEmpty($email->Attachments ?? []);
597+
}
598+
599+
/**
600+
* Assert number of attachments in opened email matches expected size.
601+
*/
602+
public function haveNumberOfAttachmentsInOpenedEmail(int $expected): void
603+
{
604+
$email = $this->getOpenedEmail();
605+
$this->assertCount($expected, $email->Attachments ?? []);
606+
}
607+
608+
/**
609+
* Assert given JSON-decoded email does not have attachments.
610+
*/
611+
public function dontHaveAttachmentsInEmail(mixed $email): void
612+
{
613+
$this->assertSame([], $email->Attachments ?? []);
614+
}
615+
616+
/**
617+
* Assert given JSON-decoded email has attachments.
618+
*/
619+
public function haveAttachmentsInEmail(mixed $email): void
620+
{
621+
$this->assertNotEmpty($email->Attachments ?? []);
622+
}
623+
624+
/**
625+
* Assert number of attachments in given JSON-decoded email matches expected size.
626+
*/
627+
public function haveNumberOfAttachmentsInEmail(mixed $email, int $expected): void
628+
{
629+
$this->assertCount($expected, $email->Attachments ?? []);
630+
}
631+
632+
/**
633+
* Assert filename of currently opened attachment in opened email contains $expected.
634+
*/
635+
public function seeInFilenameOfOpenedAttachment(string $expected): void
636+
{
637+
$this->assertStringContainsString($expected, $this->grabFilenameFromOpenedAttachment());
638+
}
639+
640+
/**
641+
* Assert filename of given JSON-decoded attachment contains $expected.
642+
*/
643+
public function seeInFilenameOfAttachment(mixed $attachment, string $expected): void
644+
{
645+
$this->assertStringContainsString($expected, $this->grabFilenameFromAttachment($attachment));
646+
}
647+
648+
/**
649+
* Return filename of currently opened attachment in opened email.
650+
*/
651+
public function grabFilenameFromOpenedAttachment(): string
652+
{
653+
$attachment = $this->getOpenedAttachment();
654+
return $attachment->FileName;
655+
}
656+
657+
/**
658+
* Return content-type of currently opened attachment in opened email.
659+
*/
660+
public function grabContentTypeFromOpenedAttachment(): string
661+
{
662+
$attachment = $this->getOpenedAttachment();
663+
return $attachment->ContentType;
664+
}
665+
666+
/**
667+
* Return size of currently opened attachment in opened email.
668+
*/
669+
public function grabSizeFromOpenedAttachment(): int
670+
{
671+
$attachment = $this->getOpenedAttachment();
672+
return $attachment->Size;
673+
}
674+
675+
/**
676+
* Return filename of given JSON-decoded attachment.
677+
*/
678+
public function grabFilenameFromAttachment(mixed $attachment): string
679+
{
680+
return $attachment->FileName;
681+
}
682+
683+
/**
684+
* Return content-type of given JSON-decoded attachment.
685+
*/
686+
public function grabContentTypeFromAttachment(mixed $attachment): string
687+
{
688+
return $attachment->ContentType;
689+
}
690+
691+
/**
692+
* Return size of given JSON-decoded attachment.
693+
*/
694+
public function grabSizeFromAttachment(mixed $attachment): int
695+
{
696+
return $attachment->Size;
697+
}
698+
}

tests/MailpitTest.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,59 @@ class MailpitTest extends TestCase
6363
JSON;
6464

6565
private static $singleMessageJson = <<<JSON
66+
{
67+
"ID": "fc5666d2-b7f2-4c53-a213-75029127887a",
68+
"MessageID": "[email protected]",
69+
"Read": true,
70+
"From": {
71+
"Name": "Jane Smith",
72+
"Address": "[email protected]"
73+
},
74+
"To": [
75+
{
76+
"Name": "John Doe",
77+
"Address": "[email protected]"
78+
}
79+
],
80+
"Cc": [
81+
{
82+
"Name": "Carbon Copy",
83+
"Address": "[email protected]"
84+
}
85+
],
86+
"Bcc": [
87+
{
88+
"Name": "",
89+
"Address": "[email protected]"
90+
}
91+
],
92+
"ReplyTo": [
93+
{
94+
"Name": "Reply To",
95+
"Address": "[email protected]"
96+
}
97+
],
98+
"ReturnPath": "[email protected]",
99+
"Subject": "An email",
100+
"Date": "2023-09-16T19:18:33Z",
101+
"Tags": [],
102+
"Text": "Plain Text",
103+
"HTML": "\u003cbody\u003eHTML Text\u003c/body\u003e",
104+
"Size": 1886,
105+
"Inline": [],
106+
"Attachments": [
107+
{
108+
"PartID": "2",
109+
"FileName": "dummy.png",
110+
"ContentType": "image/png",
111+
"ContentID": "",
112+
"Size": 1575
113+
}
114+
]
115+
}
116+
JSON;
117+
118+
private static $singleMessageWithoutAttachmentsJson = <<<JSON
66119
{
67120
"ID": "fc5666d2-b7f2-4c53-a213-75029127887a",
68121
"MessageID": "[email protected]",
@@ -105,6 +158,16 @@ class MailpitTest extends TestCase
105158
"Inline": [],
106159
"Attachments": []
107160
}
161+
JSON;
162+
163+
private static $singleAttachmentJson = <<<JSON
164+
{
165+
"PartID": "2",
166+
"FileName": "dummy.png",
167+
"ContentType": "image/png",
168+
"ContentID": "",
169+
"Size": 1575
170+
}
108171
JSON;
109172

110173
private static $singleHeaderJson = <<<JSON
@@ -315,6 +378,28 @@ public function testOpenNextUnreadEmailNegative(): void
315378
$this->mailpit->openNextUnreadEmail();
316379
}
317380

381+
public function testOpenNextAttachmentInOpenedEmailPositive(): void
382+
{
383+
$client = $this->buildClient();
384+
$this->mailpit->setClient($client);
385+
$this->mailpit->fetchEmails();
386+
$this->mailpit->openNextUnreadEmail();
387+
388+
$this->mailpit->openNextAttachmentInOpenedEmail();
389+
390+
self::assertEquals(json_decode(self::$singleAttachmentJson, false), $this->mailpit->getPropOpenedAttachment());
391+
}
392+
393+
public function testOpenNextAttachmentInOpenedEmailNegative(): void
394+
{
395+
$this->mailpit->setOpenedEmail(json_decode(self::$singleMessageWithoutAttachmentsJson, false));
396+
397+
$this->expectException(AssertionFailedError::class);
398+
$this->expectExceptionMessage('No attachments in opened email');
399+
400+
$this->mailpit->openNextAttachmentInOpenedEmail();
401+
}
402+
318403
public function testGrabHeaderFromOpenedEmail()
319404
{
320405
$client = $this->buildClient();
@@ -365,10 +450,20 @@ public function setUnreadInbox($inbox): void
365450
$this->unreadInbox = $inbox;
366451
}
367452

453+
public function setOpenedEmail($openedEmail): void
454+
{
455+
$this->openedEmail = $openedEmail;
456+
}
457+
368458
public function getPropOpenedEmail()
369459
{
370460
return $this->openedEmail;
371461
}
462+
463+
public function getPropOpenedAttachment()
464+
{
465+
return $this->openedAttachment;
466+
}
372467
};
373468
$this->mailpit->_initialize();
374469
}

0 commit comments

Comments
 (0)