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

Commit 4bbafd9

Browse files
committed
Pulling in the orginal assertions & building test around them
1 parent f6ba106 commit 4bbafd9

10 files changed

+641
-1
lines changed

composer.json

+2-1
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

+42
Original file line numberDiff line numberDiff line change
@@ -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

+42
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

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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+
/**
29+
* Delivered emails.
30+
*
31+
* @var array
32+
*/
33+
protected $emails = [];
34+
35+
/**
36+
* Register a listener for new emails.
37+
*
38+
* Called my PHPUnit before each test it run. It registers the MailRecorder "plugin" with Swift, so that we can
39+
* get a copy of each email that is sent during that test.
40+
*
41+
* @before
42+
*/
43+
public function setUpMailTracking()
44+
{
45+
Mail::getSwiftMailer()
46+
->registerPlugin(new MailRecorder($this));
47+
}
48+
49+
/**
50+
* Retrieve the appropriate swift message.
51+
*
52+
* @param Swift_Message $message
53+
*
54+
* @return Swift_Message
55+
*/
56+
protected function getEmail(Swift_Message $message = null)
57+
{
58+
$this->seeEmailWasSent();
59+
60+
return $message ?: $this->lastEmail();
61+
}
62+
63+
/**
64+
* Retrieve the mostly recently sent swift message.
65+
*/
66+
protected function lastEmail()
67+
{
68+
return end($this->emails);
69+
}
70+
71+
/**
72+
* Store a new swift message.
73+
*
74+
* Collection of emails that were received by the MailRecorder plugin during a test.
75+
*
76+
* @param Swift_Message $email
77+
*/
78+
public function recordMail(Swift_Message $email)
79+
{
80+
$this->emails[] = $email;
81+
}
82+
83+
/**
84+
* Assert that the last email's body contains the given text.
85+
*
86+
* @param string $excerpt
87+
* @param Swift_Message $message
88+
*
89+
* @return PHPUnit_Framework_TestCase $this
90+
*/
91+
protected function seeEmailContains($excerpt, Swift_Message $message = null)
92+
{
93+
$this->assertContains($excerpt, $this->getEmail($message)
94+
->getBody(), "No email containing the provided body was found.");
95+
96+
return $this;
97+
}
98+
99+
/**
100+
* Assert that the last email's body equals the given text.
101+
*
102+
* @param string $body
103+
* @param Swift_Message $message
104+
*
105+
* @return PHPUnit_Framework_TestCase $this
106+
*/
107+
protected function seeEmailEquals($body, Swift_Message $message = null)
108+
{
109+
$this->assertEquals($body, $this->getEmail($message)
110+
->getBody(), "No email with the provided body was sent.");
111+
112+
return $this;
113+
}
114+
115+
/**
116+
* Assert that the last email was delivered by the given address.
117+
*
118+
* @param string $sender
119+
* @param Swift_Message $message
120+
*
121+
* @return PHPUnit_Framework_TestCase $this
122+
*/
123+
protected function seeEmailFrom($sender, Swift_Message $message = null)
124+
{
125+
// TODO: Allow from to be an array to check email & name
126+
$this->assertArrayHasKey($sender, (array)$this->getEmail($message)
127+
->getFrom(), "No email was sent from $sender.");
128+
129+
return $this;
130+
}
131+
132+
/**
133+
* Assert that the given number of emails were sent.
134+
*
135+
* @param integer $count
136+
*
137+
* @return PHPUnit_Framework_TestCase $this
138+
*/
139+
protected function seeEmailsSent($count)
140+
{
141+
$emailsSent = count($this->emails);
142+
143+
$this->assertCount($count, $this->emails, "Expected $count emails to have been sent, but $emailsSent were.");
144+
145+
return $this;
146+
}
147+
148+
/**
149+
* Assert that the last email's subject matches the given string.
150+
*
151+
* @param string $subject
152+
* @param Swift_Message $message
153+
*
154+
* @return PHPUnit_Framework_TestCase $this
155+
*/
156+
protected function seeEmailSubject($subject, Swift_Message $message = null)
157+
{
158+
// TODO: Consider a subject contains like the message contains
159+
$this->assertEquals($subject, $this->getEmail($message)
160+
->getSubject(), "No email with a subject of $subject was found.");
161+
162+
return $this;
163+
}
164+
165+
/**
166+
* Assert that the last email was sent to the given recipient.
167+
*
168+
* @param string $recipient
169+
* @param Swift_Message $message
170+
*
171+
* @return PHPUnit_Framework_TestCase $this
172+
*/
173+
protected function seeEmailTo($recipient, Swift_Message $message = null)
174+
{
175+
$this->assertArrayHasKey($recipient, (array)$this->getEmail($message)
176+
->getTo(), "No email was sent to $recipient.");
177+
178+
return $this;
179+
}
180+
181+
/**
182+
* Assert that no emails were sent.
183+
*
184+
* @return PHPUnit_Framework_TestCase $this
185+
*/
186+
protected function seeEmailWasNotSent()
187+
{
188+
$this->assertEmpty($this->emails, 'Did not expect any emails to have been sent.');
189+
190+
return $this;
191+
}
192+
193+
/**
194+
* Assert that at least one email was sent.
195+
*
196+
* @return PHPUnit_Framework_TestCase $this
197+
*/
198+
protected function seeEmailWasSent()
199+
{
200+
$this->assertNotEmpty($this->emails, 'No emails have been sent.');
201+
202+
return $this;
203+
}
204+
}

tests/.gitkeep

Whitespace-only changes.

tests/MailRecorderTest.php

+72
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)