Passed
Pull Request — develop (#56)
by Stephen
03:00
created

MailTracking::seeEmailWasNotSent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
c 2
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 0
crap 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->assertStringContainsString($excerpt, $this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertStringContainsString() 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
               assertStringContainsString($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->assertStringNotContainsString($excerpt, $this->getEmail($message)
0 ignored issues
show
Bug introduced by
It seems like assertStringNotContainsString() 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
               assertStringNotContainsString($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->assertStringContainsString($excerpt, $this->getEmail($message)
301 1
                                                         ->getSubject(), "The last email sent did not contain the provided subject.");
302
303 1
        return $this;
304
    }
305
306
    /**
307
     * Assert that the last email's subject does not contain the given string.
308
     *
309
     * @param string             $excerpt
310
     * @param Swift_Message|null $message
311
     *
312
     * @return $this
313
     */
314 1
    protected function seeEmailSubjectDoesNotContain($excerpt, Swift_Message $message = null)
315
    {
316 1
        $this->assertStringNotContainsString($excerpt, $this->getEmail($message)
317 1
                                                            ->getSubject(), "The last email sent contained the provided text in its subject.");
318
319 1
        return $this;
320
    }
321
322
    /**
323
     * Assert that the last email's subject matches the given string.
324
     *
325
     * @param string             $subject
326
     * @param Swift_Message|null $message
327
     *
328
     * @return $this
329
     */
330 1
    protected function seeEmailSubjectEquals($subject, Swift_Message $message = null)
331
    {
332 1
        $this->assertEquals($subject, $this->getEmail($message)
333 1
                                           ->getSubject(), "The last email sent did not contain a subject of $subject.");
334
335 1
        return $this;
336
    }
337
338
    /**
339
     * Assert that the last email was sent to the given recipient.
340
     *
341
     * @param string             $recipient
342
     * @param Swift_Message|null $message
343
     *
344
     * @return $this
345
     */
346 1
    protected function seeEmailTo($recipient, Swift_Message $message = null)
347
    {
348 1
        $this->assertArrayHasKey($recipient, (array)$this->getEmail($message)
349 1
                                                         ->getTo(), "The last email sent was not sent to $recipient.");
350
351 1
        return $this;
352
    }
353
354
    /**
355
     * Assert that no emails were sent.
356
     *
357
     * @return $this
358
     */
359 1
    protected function seeEmailWasNotSent()
360
    {
361 1
        $emailsSent = count($this->emails);
362
363 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

363
        $this->/** @scrutinizer ignore-call */ 
364
               assertEmpty($this->emails, "Did not expect any emails to have been sent, but found $emailsSent");
Loading history...
364
365 1
        return $this;
366
    }
367
368
    /**
369
     * Assert that at least one email was sent.
370
     *
371
     * @return $this
372
     */
373 14
    protected function seeEmailWasSent()
374
    {
375 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

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