Completed
Push — master ( afa575...b04272 )
by Jimmy
11:18 queued 08:06
created

MailTracking::seeEmailFrom()   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 2
crap 1
1
<?php
2
3
namespace Spinen\MailAssertions;
4
5
use Illuminate\Support\Facades\Mail;
6
use Swift_Message;
7
8
/**
9
 * Class 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 extending from the PHPUnit TestCase class (or a child 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: Add check for Priority
32
    // TODO: Allow checking specific message not just most recent one
33
34
    /**
35
     * Delivered emails.
36
     *
37
     * @var array
38
     */
39
    protected $emails = [];
40
41
    /**
42
     * Register a listener for new emails.
43
     *
44
     * This calls my PHPUnit before each test it runs. It registers the MailRecorder "plugin" with Swift, so that we
45
     * can get a copy of each email that is sent during that test.
46
     *
47
     * @before
48
     */
49
    public function setUpMailTracking()
50
    {
51
        $register_plugin = function () {
52
            Mail::getSwiftMailer()
53
                ->registerPlugin(new MailRecorder($this));
54
        };
55
56
        $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

56
        $this->/** @scrutinizer ignore-call */ 
57
               afterApplicationCreated(function () use ($register_plugin) {
Loading history...
57
            $register_plugin();
58
        });
59
    }
60
61
    /**
62
     * Retrieve the appropriate Swift message.
63
     *
64
     * @param Swift_Message|null $message
65
     *
66
     * @return Swift_Message
67
     */
68 13
    protected function getEmail(Swift_Message $message = null)
69
    {
70 13
        $this->seeEmailWasSent();
71
72 13
        return $message ?: $this->lastEmail();
73
    }
74
75
    /**
76
     * Retrieve the mostly recently sent Swift message.
77
     */
78 13
    protected function lastEmail()
79
    {
80 13
        return end($this->emails);
81
    }
82
83
    /**
84
     * Store a new Swift message.
85
     *
86
     * Collection of emails that were received by the MailRecorder plugin during a test.
87
     *
88
     * @param Swift_Message $email
89
     */
90 16
    public function recordMail(Swift_Message $email)
91
    {
92 16
        $this->emails[] = $email;
93
    }
94
95
    /**
96
     * Assert that the last email was bcc'ed to the given address.
97
     *
98
     * @param string             $bcc
99
     * @param Swift_Message|null $message
100
     *
101
     * @return $this
102
     */
103 1
    protected function seeEmailBcc($bcc, Swift_Message $message = null)
104
    {
105 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

105
        $this->/** @scrutinizer ignore-call */ 
106
               assertArrayHasKey($bcc, (array)$this->getEmail($message)
Loading history...
106 1
                                                   ->getBcc(), "The last email sent was not bcc'ed to $bcc.");
107
108 1
        return $this;
109
    }
110
111
    /**
112
     * Assert that the last email was cc'ed to the given address.
113
     *
114
     * @param string             $cc
115
     * @param Swift_Message|null $message
116
     *
117
     * @return $this
118
     */
119 1
    protected function seeEmailCc($cc, Swift_Message $message = null)
120
    {
121 1
        $this->assertArrayHasKey($cc, (array)$this->getEmail($message)
122 1
                                                  ->getCc(), "The last email sent was not cc'ed to $cc.");
123
124 1
        return $this;
125
    }
126
127
    /**
128
     * Assert that the last email's body contains the given text.
129
     *
130
     * @param string             $excerpt
131
     * @param Swift_Message|null $message
132
     *
133
     * @return $this
134
     */
135 1
    protected function seeEmailContains($excerpt, Swift_Message $message = null)
136
    {
137 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

137
        $this->/** @scrutinizer ignore-call */ 
138
               assertContains($excerpt, $this->getEmail($message)
Loading history...
138 1
                                             ->getBody(), "The last email sent did not contain the provided body.");
139
140 1
        return $this;
141
    }
142
143
    /**
144
     * Assert that the last email's content type equals the given text.
145
     * For example, "text/plain" and "text/html" are valid content types for an email.
146
     *
147
     * @param string             $content_type
148
     * @param Swift_Message|null $message
149
     *
150
     * @return $this
151
     */
152 1
    protected function seeEmailContentTypeEquals($content_type, Swift_Message $message = null)
153
    {
154 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

154
        $this->/** @scrutinizer ignore-call */ 
155
               assertEquals($content_type, $this->getEmail($message)
Loading history...
155 1
                                                ->getContentType(),
156 1
            "The last email sent did not contain the provided body.");
157
158 1
        return $this;
159
    }
160
161
    /**
162
     * Assert that the last email's body does not contain the given text.
163
     *
164
     * @param string             $excerpt
165
     * @param Swift_Message|null $message
166
     *
167
     * @return $this
168
     */
169 1
    protected function seeEmailDoesNotContain($excerpt, Swift_Message $message = null)
170
    {
171 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

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

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

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

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