Completed
Push — master ( 9e37cd...4f56cc )
by Stephen
07:33 queued 04:55
created

MailTracking   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 355
Duplicated Lines 0 %

Test Coverage

Coverage 89.89%

Importance

Changes 25
Bugs 1 Features 0
Metric Value
wmc 23
eloc 68
c 25
b 1
f 0
dl 0
loc 355
ccs 80
cts 89
cp 0.8989
rs 10

22 Methods

Rating   Name   Duplication   Size   Complexity  
A seeEmailDoesNotContain() 0 7 1
A seeEmailPriorityEquals() 0 9 1
A seeEmailSubjectEquals() 0 7 1
A seeEmailWasSent() 0 5 1
A seeEmailContains() 0 6 1
A seeEmailContentTypeEquals() 0 7 1
A lastEmail() 0 3 1
A seeEmailEquals() 0 6 1
A seeEmailSubjectDoesNotContain() 0 7 1
A seeEmailSubject() 0 3 1
A seeEmailCountEquals() 0 7 1
A seeEmailWasNotSent() 0 7 1
A seeEmailCc() 0 6 1
A seeEmailTo() 0 6 1
A seeEmailSubjectContains() 0 7 1
A recordMail() 0 3 1
A seeEmailBcc() 0 6 1
A seeEmailReplyTo() 0 7 1
A getEmail() 0 5 2
A seeEmailFrom() 0 7 1
A setUpMailTracking() 0 9 1
A seeEmailsSent() 0 3 1
1
<?php
2
3
namespace Spinen\MailAssertions;
4
5
use Illuminate\Support\Facades\Mail;
6
use Swift_Message;
7
8
/**
9
 * Trait MailTracking
10
 *
11
 * Trait to mixin to your test to allow for custom assertions when using PHPUnit with Laravel. This trait assumes
12
 * you are using it from the PHPUnit TestCase class (or a child class of it).
13
 *
14
 * This originally started out as a copy & paste from a video series that Jeffrey 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 the initial
17
 * assertions.
18
 *
19
 * I WANT IT CLEAR THAT THIS WOULD NOT HAVE HAPPENED WITHOUT THE INITIAL WORK OF JEFFREY 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 header
30
    // TODO: Add check for message type
31
    // TODO: Allow checking specific message not just most recent one
32
33
    /**
34
     * Delivered emails.
35
     *
36
     * @var array
37
     */
38
    protected $emails = [];
39
40
    /**
41
     * Register a listener for new emails.
42
     *
43
     * This calls our PHPUnit before each test it runs. It registers the MailRecorder "plugin" with Swift, so that we
44
     * can get a copy of each email that is sent during that test.
45
     *
46
     * @before
47
     */
48
    public function setUpMailTracking()
49
    {
50
        $register_plugin = function () {
51
            Mail::getSwiftMailer()
52
                ->registerPlugin(new MailRecorder($this));
53
        };
54
55
        $this->afterApplicationCreated(function () use ($register_plugin) {
0 ignored issues
show
Bug introduced by
It seems like afterApplicationCreated() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

55
        $this->/** @scrutinizer ignore-call */ 
56
               afterApplicationCreated(function () use ($register_plugin) {
Loading history...
56
            $register_plugin();
57
        });
58
    }
59
60
    /**
61
     * Retrieve the appropriate Swift message.
62
     *
63
     * @param Swift_Message|null $message
64
     *
65
     * @return Swift_Message
66
     */
67 13
    protected function getEmail(Swift_Message $message = null)
68
    {
69 13
        $this->seeEmailWasSent();
70
71 13
        return $message ?: $this->lastEmail();
72
    }
73
74
    /**
75
     * Retrieve the mostly recently sent Swift message.
76
     */
77 13
    protected function lastEmail()
78
    {
79 13
        return end($this->emails);
80
    }
81
82
    /**
83
     * Store a new Swift message.
84
     *
85
     * Collection of emails that were received by the MailRecorder plugin during a test.
86
     *
87
     * @param Swift_Message $email
88
     */
89 16
    public function recordMail(Swift_Message $email)
90
    {
91 16
        $this->emails[] = $email;
92
    }
93
94
    /**
95
     * Assert that the last email was bcc'ed to the given address.
96
     *
97
     * @param string             $bcc
98
     * @param Swift_Message|null $message
99
     *
100
     * @return $this
101
     */
102 1
    protected function seeEmailBcc($bcc, Swift_Message $message = null)
103
    {
104 1
        $this->assertArrayHasKey($bcc, (array)$this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertArrayHasKey() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

104
        $this->/** @scrutinizer ignore-call */ 
105
               assertArrayHasKey($bcc, (array)$this->getEmail($message)
Loading history...
105 1
                                                   ->getBcc(), "The last email sent was not bcc'ed to $bcc.");
106
107 1
        return $this;
108
    }
109
110
    /**
111
     * Assert that the last email was cc'ed to the given address.
112
     *
113
     * @param string             $cc
114
     * @param Swift_Message|null $message
115
     *
116
     * @return $this
117
     */
118 1
    protected function seeEmailCc($cc, Swift_Message $message = null)
119
    {
120 1
        $this->assertArrayHasKey($cc, (array)$this->getEmail($message)
121 1
                                                  ->getCc(), "The last email sent was not cc'ed to $cc.");
122
123 1
        return $this;
124
    }
125
126
    /**
127
     * Assert that the last email's body contains the given text.
128
     *
129
     * @param string             $excerpt
130
     * @param Swift_Message|null $message
131
     *
132
     * @return $this
133
     */
134 1
    protected function seeEmailContains($excerpt, Swift_Message $message = null)
135
    {
136 1
        $this->assertContains($excerpt, $this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertContains() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

136
        $this->/** @scrutinizer ignore-call */ 
137
               assertContains($excerpt, $this->getEmail($message)
Loading history...
137 1
                                             ->getBody(), "The last email sent did not contain the provided body.");
138
139 1
        return $this;
140
    }
141
142
    /**
143
     * Assert that the last email's content type equals the given text.
144
     * For example, "text/plain" and "text/html" are valid content types for an email.
145
     *
146
     * @param string             $content_type
147
     * @param Swift_Message|null $message
148
     *
149
     * @return $this
150
     */
151 1
    protected function seeEmailContentTypeEquals($content_type, Swift_Message $message = null)
152
    {
153 1
        $this->assertEquals($content_type, $this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

153
        $this->/** @scrutinizer ignore-call */ 
154
               assertEquals($content_type, $this->getEmail($message)
Loading history...
154 1
                                                ->getContentType(),
155 1
            "The last email sent did not contain the provided body.");
156
157 1
        return $this;
158
    }
159
160
    /**
161
     * Assert that the last email's body does not contain the given text.
162
     *
163
     * @param string             $excerpt
164
     * @param Swift_Message|null $message
165
     *
166
     * @return $this
167
     */
168 1
    protected function seeEmailDoesNotContain($excerpt, Swift_Message $message = null)
169
    {
170 1
        $this->assertNotContains($excerpt, $this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertNotContains() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

170
        $this->/** @scrutinizer ignore-call */ 
171
               assertNotContains($excerpt, $this->getEmail($message)
Loading history...
171 1
                                                ->getBody(),
172 1
                                 "The last email sent contained the provided text in its body.");
173
174 1
        return $this;
175
    }
176
177
    /**
178
     * Assert that the last email's body equals the given text.
179
     *
180
     * @param string             $body
181
     * @param Swift_Message|null $message
182
     *
183
     * @return $this
184
     */
185 1
    protected function seeEmailEquals($body, Swift_Message $message = null)
186
    {
187 1
        $this->assertEquals($body, $this->getEmail($message)
188 1
                                        ->getBody(), "The last email sent did not match the given email.");
189
190 1
        return $this;
191
    }
192
193
    /**
194
     * Assert that the last email was delivered by the given address.
195
     *
196
     * @param string             $sender
197
     * @param Swift_Message|null $message
198
     *
199
     * @return $this
200
     */
201 1
    protected function seeEmailFrom($sender, Swift_Message $message = null)
202
    {
203
        // TODO: Allow from to be an array to check email & name
204 1
        $this->assertArrayHasKey($sender, (array)$this->getEmail($message)
205 1
                                                      ->getFrom(), "The last email sent was not sent from $sender.");
206
207 1
        return $this;
208
    }
209
210
    /**
211
     * Assert that the last email had the given priority level.
212
     * The value is an integer where 1 is the highest priority and 5 is the lowest.
213
     *
214
     * @param integer            $priority
215
     * @param Swift_Message|null $message
216
     *
217
     * @return $this
218
     */
219 1
    protected function seeEmailPriorityEquals($priority, Swift_Message $message = null)
220
    {
221 1
        $actual_priority = $this->getEmail($message)
222 1
                                ->getPriority();
223
224 1
        $this->assertEquals($priority, $actual_priority,
225 1
            "The last email sent had a priority of $actual_priority but expected $priority.");
226
227 1
        return $this;
228
    }
229
230
    /**
231
     * Assert that the last email was set to reply to the given address.
232
     *
233
     * @param string             $reply_to
234
     * @param Swift_Message|null $message
235
     *
236
     * @return $this
237
     */
238 1
    protected function seeEmailReplyTo($reply_to, Swift_Message $message = null)
239
    {
240 1
        $this->assertArrayHasKey($reply_to, (array)$this->getEmail($message)
241 1
                                                        ->getReplyTo(),
242 1
                                 "The last email sent was not set to reply to $reply_to.");
243
244 1
        return $this;
245
    }
246
247
    /**
248
     * Assert that the given number of emails were sent.
249
     *
250
     * @param integer $count
251
     *
252
     * @return MailTracking $this
253
     * @deprecated in favor of seeEmailCountEquals
254
     */
255 1
    protected function seeEmailsSent($count)
256
    {
257 1
        return $this->seeEmailCountEquals($count);
258
    }
259
260
    /**
261
     * Assert that the given number of emails were sent.
262
     *
263
     * @param integer $count
264
     *
265
     * @return $this
266
     */
267 1
    protected function seeEmailCountEquals($count)
268
    {
269 1
        $emailsSent = count($this->emails);
270
271 1
        $this->assertCount($count, $this->emails, "Expected $count emails to have been sent, but $emailsSent were.");
0 ignored issues
show
Bug introduced by
It seems like assertCount() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

271
        $this->/** @scrutinizer ignore-call */ 
272
               assertCount($count, $this->emails, "Expected $count emails to have been sent, but $emailsSent were.");
Loading history...
272
273 1
        return $this;
274
    }
275
276
    /**
277
     * Assert that the last email's subject matches the given string.
278
     *
279
     * @param string             $subject
280
     * @param Swift_Message|null $message
281
     *
282
     * @return MailTracking $this
283
     * @deprecated in favor of seeEmailSubjectEquals
284
     */
285
    protected function seeEmailSubject($subject, Swift_Message $message = null)
286
    {
287
        return $this->seeEmailSubjectEquals($subject, $message);
288
    }
289
290
    /**
291
     * Assert that the last email's subject contains the given string.
292
     *
293
     * @param string             $excerpt
294
     * @param Swift_Message|null $message
295
     *
296
     * @return $this
297
     */
298 1
    protected function seeEmailSubjectContains($excerpt, Swift_Message $message = null)
299
    {
300 1
        $this->assertContains($excerpt, $this->getEmail($message)
301 1
                                             ->getSubject(),
302 1
                              "The last email sent did not contain the provided subject.");
303
304 1
        return $this;
305
    }
306
307
    /**
308
     * Assert that the last email's subject does not contain the given string.
309
     *
310
     * @param string             $excerpt
311
     * @param Swift_Message|null $message
312
     *
313
     * @return $this
314
     */
315 1
    protected function seeEmailSubjectDoesNotContain($excerpt, Swift_Message $message = null)
316
    {
317 1
        $this->assertNotContains($excerpt, $this->getEmail($message)
318 1
                                                ->getSubject(),
319 1
                                 "The last email sent contained the provided text in its subject.");
320
321 1
        return $this;
322
    }
323
324
    /**
325
     * Assert that the last email's subject matches the given string.
326
     *
327
     * @param string             $subject
328
     * @param Swift_Message|null $message
329
     *
330
     * @return $this
331
     */
332 1
    protected function seeEmailSubjectEquals($subject, Swift_Message $message = null)
333
    {
334 1
        $this->assertEquals($subject, $this->getEmail($message)
335 1
                                           ->getSubject(),
336 1
                            "The last email sent did not contain a subject of $subject.");
337
338 1
        return $this;
339
    }
340
341
    /**
342
     * Assert that the last email was sent to the given recipient.
343
     *
344
     * @param string             $recipient
345
     * @param Swift_Message|null $message
346
     *
347
     * @return $this
348
     */
349 1
    protected function seeEmailTo($recipient, Swift_Message $message = null)
350
    {
351 1
        $this->assertArrayHasKey($recipient, (array)$this->getEmail($message)
352 1
                                                         ->getTo(), "The last email sent was not sent to $recipient.");
353
354 1
        return $this;
355
    }
356
357
    /**
358
     * Assert that no emails were sent.
359
     *
360
     * @return $this
361
     */
362 1
    protected function seeEmailWasNotSent()
363
    {
364 1
        $emailsSent = count($this->emails);
365
366 1
        $this->assertEmpty($this->emails, "Did not expect any emails to have been sent, but found $emailsSent");
0 ignored issues
show
Bug introduced by
It seems like assertEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

366
        $this->/** @scrutinizer ignore-call */ 
367
               assertEmpty($this->emails, "Did not expect any emails to have been sent, but found $emailsSent");
Loading history...
367
368 1
        return $this;
369
    }
370
371
    /**
372
     * Assert that at least one email was sent.
373
     *
374
     * @return $this
375
     */
376 14
    protected function seeEmailWasSent()
377
    {
378 14
        $this->assertNotEmpty($this->emails, 'Expected at least one email to be sent, but found none.');
0 ignored issues
show
Bug introduced by
It seems like assertNotEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

378
        $this->/** @scrutinizer ignore-call */ 
379
               assertNotEmpty($this->emails, 'Expected at least one email to be sent, but found none.');
Loading history...
379
380 14
        return $this;
381
    }
382
}
383