Skip to content
This repository was archived by the owner on Apr 8, 2024. It is now read-only.

Commit 11f1758

Browse files
committed
Merge branch 'release/0.0.1'
2 parents 64f98ee + 7a6341a commit 11f1758

File tree

11 files changed

+652
-3
lines changed

11 files changed

+652
-3
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.0
1+
0.0.1

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": ">=5.5.0",
20-
"illuminate/support": "~5.1.10|5.2.*"
20+
"illuminate/support": "~5.1.10|5.2.*",
21+
"swiftmailer/swiftmailer": "~5.1"
2122
},
2223
"require-dev": {
2324
"mockery/mockery": "~0.9.1",

readme.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPINEN's Laravel Mail Assertions
22

3-
NOTE: This is based off a video titled ["Testing Email With Custom Assertions"](https://laracasts.com/series/phpunit-testing-in-laravel/episodes/12) that Jeffery Way did on [Laracasts.com}(https://laracasts.com). If you do not have an account on that site, then you should. It is an amazing resource. We have just take that example & made it in an easy to install package. Thanks Jeffery!
3+
NOTE: This is based off a video titled ["Testing Email With Custom Assertions"](https://laracasts.com/series/phpunit-testing-in-laravel/episodes/12) that Jeffery Way did on [Laracasts.com](https://laracasts.com). If you do not have an account on that site, then you should. It is an amazing resource. We have just take that example & made it in an easy to install package. Thanks Jeffery!
44

55
[![Latest Stable Version](https://poser.pugx.org/spinen/laravel-mail-assertions/v/stable)](https://packagist.org/packages/spinen/laravel-mail-assertions)
66
[![Total Downloads](https://poser.pugx.org/spinen/laravel-mail-assertions/downloads)](https://packagist.org/packages/spinen/laravel-mail-assertions)
@@ -27,3 +27,45 @@ Install Garbage Man:
2727

2828
## Using
2929

30+
You mixin the assertions with the ```Spinen\MailAssertions\MailTracking``` trait. You get the following assertions...
31+
32+
* seeEmailContains
33+
* seeEmailEquals
34+
* seeEmailFrom
35+
* seeEmailSubject
36+
* seeEmailTo
37+
* seeEmailWasNotSent
38+
* seeEmailWasSent
39+
* seeEmailsSent
40+
41+
NOTE: If there was more than 1 email sent, then the assertions look at the last email.
42+
43+
## Example
44+
45+
```php
46+
<?php
47+
use Illuminate\Foundation\Testing\WithoutMiddleware;
48+
use Illuminate\Foundation\Testing\DatabaseMigrations;
49+
use Illuminate\Foundation\Testing\DatabaseTransactions;
50+
use Spinen\MailAssertions\MailTracking;
51+
52+
class ExampleTest extends TestCase
53+
{
54+
use MailTracking;
55+
56+
/**
57+
* A basic functional test example.
58+
*
59+
* @return void
60+
*/
61+
public function testBasicExample()
62+
{
63+
$this->visit('/route-that-sends-an-email')
64+
->seeEmailWasSent()
65+
->seeEmailSubject('Hello World')
66+
->seeEmailTo('foo@bar.com')
67+
->seeEmailEquals('Click here to buy this jewelry.')
68+
->seeEmailContains('Click here');
69+
}
70+
}
71+
```

src/.gitkeep

Whitespace-only changes.

src/MailRecorder.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Spinen\MailAssertions;
4+
5+
use PHPUnit_Framework_TestCase;
6+
use Swift_Events_EventListener;
7+
use Swift_Events_SendEvent;
8+
9+
/**
10+
* Class MailRecorder
11+
*
12+
* @package Spinen\MailAssertions
13+
*/
14+
class MailRecorder implements Swift_Events_EventListener
15+
{
16+
/**
17+
* @var PHPUnit_Framework_TestCase
18+
*/
19+
protected $test;
20+
21+
/**
22+
* MailRecorder constructor.
23+
*
24+
* @param PHPUnit_Framework_TestCase $test
25+
*/
26+
public function __construct(PHPUnit_Framework_TestCase $test)
27+
{
28+
$this->test = $test;
29+
}
30+
31+
/**
32+
* Called by Laravel before email is given to the transporter.
33+
*
34+
* Passes the email to the test, so that assertions can be ran against the messages.
35+
*
36+
* @param Swift_Events_SendEvent $event
37+
*/
38+
public function beforeSendPerformed(Swift_Events_SendEvent $event)
39+
{
40+
$this->test->recordMail($event->getMessage());
41+
}
42+
}

src/MailTracking.php

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<?php
2+
3+
namespace Spinen\MailAssertions;
4+
5+
use Illuminate\Support\Facades\Mail;
6+
use PHPUnit_Framework_TestCase;
7+
use Swift_Message;
8+
9+
/**
10+
* Class MailTracking
11+
*
12+
* Trait to mixin to your test to allow for custom assertions when using PHPUnit with Laravel.
13+
*
14+
* This originally started out as a copy & paste from a video series that Jeffery Way did on laracasts.com. If you do
15+
* not have an account on Laracasts, you should get one. It is an amazing resource to learn from. We used that
16+
* example & converted it to a package so that it would be easy to install. We have also expanded on initial
17+
* assertions.
18+
*
19+
* I WANT IT CLEAR THAT THIS WOULD NOT HAVE HAPPENED WITHOUT THE INITIAL WORK OF JEFFERY WAY. WE ARE NOT CLAIMING TO
20+
* BE THE CREATORS OF THE CONCEPT.
21+
*
22+
* @package Spinen\MailAssertions
23+
* @see https://gist.github.com/JeffreyWay/b501c53d958b07b8a332
24+
* @tutorial https://laracasts.com/series/phpunit-testing-in-laravel/episodes/12
25+
*/
26+
trait MailTracking
27+
{
28+
// TODO: Add check for attachments (number of & name)
29+
// TODO: Add check for BCC
30+
// TODO: Add check for CC
31+
// TODO: Add check for header
32+
// TODO: Add check for message type
33+
// TODO: Add check for Priority
34+
// TODO: Add check for ReplyTo
35+
// TODO: Allow checking specific message not just most recent one
36+
37+
/**
38+
* Delivered emails.
39+
*
40+
* @var array
41+
*/
42+
protected $emails = [];
43+
44+
/**
45+
* Register a listener for new emails.
46+
*
47+
* Called my PHPUnit before each test it run. It registers the MailRecorder "plugin" with Swift, so that we can
48+
* get a copy of each email that is sent during that test.
49+
*
50+
* @before
51+
*/
52+
public function setUpMailTracking()
53+
{
54+
Mail::getSwiftMailer()
55+
->registerPlugin(new MailRecorder($this));
56+
}
57+
58+
/**
59+
* Retrieve the appropriate swift message.
60+
*
61+
* @param Swift_Message $message
62+
*
63+
* @return Swift_Message
64+
*/
65+
protected function getEmail(Swift_Message $message = null)
66+
{
67+
$this->seeEmailWasSent();
68+
69+
return $message ?: $this->lastEmail();
70+
}
71+
72+
/**
73+
* Retrieve the mostly recently sent swift message.
74+
*/
75+
protected function lastEmail()
76+
{
77+
return end($this->emails);
78+
}
79+
80+
/**
81+
* Store a new swift message.
82+
*
83+
* Collection of emails that were received by the MailRecorder plugin during a test.
84+
*
85+
* @param Swift_Message $email
86+
*/
87+
public function recordMail(Swift_Message $email)
88+
{
89+
$this->emails[] = $email;
90+
}
91+
92+
/**
93+
* Assert that the last email's body contains the given text.
94+
*
95+
* @param string $excerpt
96+
* @param Swift_Message $message
97+
*
98+
* @return PHPUnit_Framework_TestCase $this
99+
*/
100+
protected function seeEmailContains($excerpt, Swift_Message $message = null)
101+
{
102+
$this->assertContains($excerpt, $this->getEmail($message)
103+
->getBody(), "No email containing the provided body was found.");
104+
105+
return $this;
106+
}
107+
108+
/**
109+
* Assert that the last email's body equals the given text.
110+
*
111+
* @param string $body
112+
* @param Swift_Message $message
113+
*
114+
* @return PHPUnit_Framework_TestCase $this
115+
*/
116+
protected function seeEmailEquals($body, Swift_Message $message = null)
117+
{
118+
$this->assertEquals($body, $this->getEmail($message)
119+
->getBody(), "No email with the provided body was sent.");
120+
121+
return $this;
122+
}
123+
124+
/**
125+
* Assert that the last email was delivered by the given address.
126+
*
127+
* @param string $sender
128+
* @param Swift_Message $message
129+
*
130+
* @return PHPUnit_Framework_TestCase $this
131+
*/
132+
protected function seeEmailFrom($sender, Swift_Message $message = null)
133+
{
134+
// TODO: Allow from to be an array to check email & name
135+
$this->assertArrayHasKey($sender, (array)$this->getEmail($message)
136+
->getFrom(), "No email was sent from $sender.");
137+
138+
return $this;
139+
}
140+
141+
/**
142+
* Assert that the given number of emails were sent.
143+
*
144+
* @param integer $count
145+
*
146+
* @return PHPUnit_Framework_TestCase $this
147+
*/
148+
protected function seeEmailsSent($count)
149+
{
150+
$emailsSent = count($this->emails);
151+
152+
$this->assertCount($count, $this->emails, "Expected $count emails to have been sent, but $emailsSent were.");
153+
154+
return $this;
155+
}
156+
157+
/**
158+
* Assert that the last email's subject matches the given string.
159+
*
160+
* @param string $subject
161+
* @param Swift_Message $message
162+
*
163+
* @return PHPUnit_Framework_TestCase $this
164+
*/
165+
protected function seeEmailSubject($subject, Swift_Message $message = null)
166+
{
167+
// TODO: Consider a subject contains like the message contains
168+
$this->assertEquals($subject, $this->getEmail($message)
169+
->getSubject(), "No email with a subject of $subject was found.");
170+
171+
return $this;
172+
}
173+
174+
/**
175+
* Assert that the last email was sent to the given recipient.
176+
*
177+
* @param string $recipient
178+
* @param Swift_Message $message
179+
*
180+
* @return PHPUnit_Framework_TestCase $this
181+
*/
182+
protected function seeEmailTo($recipient, Swift_Message $message = null)
183+
{
184+
$this->assertArrayHasKey($recipient, (array)$this->getEmail($message)
185+
->getTo(), "No email was sent to $recipient.");
186+
187+
return $this;
188+
}
189+
190+
/**
191+
* Assert that no emails were sent.
192+
*
193+
* @return PHPUnit_Framework_TestCase $this
194+
*/
195+
protected function seeEmailWasNotSent()
196+
{
197+
$this->assertEmpty($this->emails, 'Did not expect any emails to have been sent.');
198+
199+
return $this;
200+
}
201+
202+
/**
203+
* Assert that at least one email was sent.
204+
*
205+
* @return PHPUnit_Framework_TestCase $this
206+
*/
207+
protected function seeEmailWasSent()
208+
{
209+
$this->assertNotEmpty($this->emails, 'No emails have been sent.');
210+
211+
return $this;
212+
}
213+
}

tests/.gitkeep

Whitespace-only changes.

tests/MailRecorderTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Spinen\MailAssertions;
4+
5+
use Mockery;
6+
use PHPUnit_Framework_TestCase;
7+
use StdClass;
8+
use Swift_Events_SendEvent;
9+
10+
/**
11+
* Class MailRecorderTest
12+
*
13+
* @package Spinen\MailAssertions
14+
*/
15+
class MailRecorderTest extends TestCase
16+
{
17+
/**
18+
* @test
19+
* @group unit
20+
*/
21+
public function it_can_be_constructed()
22+
{
23+
$mail_recorder = new MailRecorder($this);
24+
25+
$this->assertInstanceOf(MailRecorder::class, $mail_recorder);
26+
}
27+
28+
/**
29+
* @test
30+
* @group unit
31+
* @expectedException PHPUnit_Framework_Error
32+
*/
33+
public function it_cannot_be_constructed_without_a_PHPUnit_Framework_TestCase()
34+
{
35+
new MailRecorder();
36+
}
37+
38+
/**
39+
* @test
40+
* @group unit
41+
* @expectedException PHPUnit_Framework_Error
42+
*/
43+
public function it_cannot_be_constructed_with_class_other_than_a_PHPUnit_Framework_TestCase()
44+
{
45+
new MailRecorder(new StdClass());
46+
}
47+
48+
/**
49+
* @test
50+
* @group
51+
*/
52+
public function it_records_the_message_on_the_test_by_calling_recordMail()
53+
{
54+
$test_mock = Mockery::mock(PHPUnit_Framework_TestCase::class);
55+
56+
$test_mock->shouldReceive('recordMail')
57+
->once()
58+
->with('message')
59+
->andReturnNull();
60+
61+
$swift_message_event_mock = Mockery::mock(Swift_Events_SendEvent::class);
62+
63+
$swift_message_event_mock->shouldReceive('getMessage')
64+
->once()
65+
->withNoArgs()
66+
->andReturn('message');
67+
68+
$mail_recorder = new MailRecorder($test_mock);
69+
70+
$this->assertNull($mail_recorder->beforeSendPerformed($swift_message_event_mock));
71+
}
72+
}

0 commit comments

Comments
 (0)