Passed
Pull Request — develop (#56)
by Stephen
02:09
created

MailTracking::resolveMailer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Spinen\MailAssertions;
4
5
use Illuminate\Container\Container;
6
use Illuminate\Contracts\Container\BindingResolutionException;
7
use Illuminate\Contracts\Mail\Mailer;
8
use Swift_Message;
9
10
/**
11
 * Trait MailTracking
12
 *
13
 * Trait to mixin to your test to allow for custom assertions when using PHPUnit with Laravel. This trait assumes
14
 * you are using it from the PHPUnit TestCase class (or a child class of it).
15
 *
16
 * This originally started out as a copy & paste from a video series that Jeffrey Way did on laracasts.com. If you do
17
 * not have an account on Laracasts, you should get one. It is an amazing resource to learn from. We used that
18
 * example & converted it to a package so that it would be easy to install. We have also expanded on the initial
19
 * assertions.
20
 *
21
 * I WANT IT CLEAR THAT THIS WOULD NOT HAVE HAPPENED WITHOUT THE INITIAL WORK OF JEFFREY WAY. WE ARE NOT CLAIMING TO
22
 * BE THE CREATORS OF THE CONCEPT.
23
 *
24
 * @package Spinen\MailAssertions
25
 * @see     https://gist.github.com/JeffreyWay/b501c53d958b07b8a332
26
 * @tutorial https://laracasts.com/series/phpunit-testing-in-laravel/episodes/12
27
 */
28
trait MailTracking
29
{
30
    // TODO: Add check for attachments (number of & name)
31
    // TODO: Add check for header
32
    // TODO: Add check for message type
33
    // TODO: Allow checking specific message not just most recent one
34
35
    /**
36
     * Delivered emails.
37
     *
38
     * @var array
39
     */
40
    protected $emails = [];
41
42
    /**
43
     * Register a listener for new emails.
44
     *
45
     * This calls our PHPUnit before each test it runs. It registers the MailRecorder "plugin" with Swift, so that we
46
     * can get a copy of each email that is sent during that test.
47
     *
48
     * @before
49
     */
50
    public function setUpMailTracking()
51
    {
52
        $register_plugin = function () {
53
            $this->resolveMailer()
54
                 ->getSwiftMailer()
55
                 ->registerPlugin(new MailRecorder($this));
56
        };
57
58
        $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

58
        $this->/** @scrutinizer ignore-call */ 
59
               afterApplicationCreated(function () use ($register_plugin) {
Loading history...
59
            $register_plugin();
60
        });
61
    }
62
63
    /**
64
     * Resolve the mailer from the IoC
65
     *
66
     * We are staying away from the Mail facade, so that we can support PHP 7.4 with Laravel 5.x
67
     *
68
     * @return Mailer
69
     * @throws BindingResolutionException
70
     */
71
    protected function resolveMailer()
72
    {
73
        return Container::getInstance()
74
                        ->make(Mailer::class);
75
    }
76
77
    /**
78
     * Retrieve the appropriate Swift message.
79
     *
80
     * @param Swift_Message|null $message
81
     *
82
     * @return Swift_Message
83
     */
84 13
    protected function getEmail(Swift_Message $message = null)
85
    {
86 13
        $this->seeEmailWasSent();
87
88 13
        return $message ?: $this->lastEmail();
89
    }
90
91
    /**
92
     * Retrieve the mostly recently sent Swift message.
93
     */
94 13
    protected function lastEmail()
95
    {
96 13
        return end($this->emails);
97
    }
98
99
    /**
100
     * Store a new Swift message.
101
     *
102
     * Collection of emails that were received by the MailRecorder plugin during a test.
103
     *
104
     * @param Swift_Message $email
105
     */
106 16
    public function recordMail(Swift_Message $email)
107
    {
108 16
        $this->emails[] = $email;
109
    }
110
111
    /**
112
     * Assert that the last email was bcc'ed to the given address.
113
     *
114
     * @param string             $bcc
115
     * @param Swift_Message|null $message
116
     *
117
     * @return $this
118
     */
119 1
    protected function seeEmailBcc($bcc, Swift_Message $message = null)
120
    {
121 1
        $this->assertArrayHasKey(
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

121
        $this->/** @scrutinizer ignore-call */ 
122
               assertArrayHasKey(
Loading history...
122 1
            $bcc,
123 1
            (array)$this->getEmail($message)
124 1
                        ->getBcc(),
125 1
            "The last email sent was not bcc'ed to $bcc."
126
        );
127
128 1
        return $this;
129
    }
130
131
    /**
132
     * Assert that the last email was cc'ed to the given address.
133
     *
134
     * @param string             $cc
135
     * @param Swift_Message|null $message
136
     *
137
     * @return $this
138
     */
139 1
    protected function seeEmailCc($cc, Swift_Message $message = null)
140
    {
141 1
        $this->assertArrayHasKey(
142 1
            $cc,
143 1
            (array)$this->getEmail($message)
144 1
                        ->getCc(),
145 1
            "The last email sent was not cc'ed to $cc."
146
        );
147
148 1
        return $this;
149
    }
150
151
    /**
152
     * Assert that the last email's body contains the given text.
153
     *
154
     * @param string             $excerpt
155
     * @param Swift_Message|null $message
156
     *
157
     * @return $this
158
     */
159 1
    protected function seeEmailContains($excerpt, Swift_Message $message = null)
160
    {
161 1
        $this->assertStringContainsString(
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

161
        $this->/** @scrutinizer ignore-call */ 
162
               assertStringContainsString(
Loading history...
162 1
            $excerpt,
163 1
            $this->getEmail($message)
164 1
                 ->getBody(),
165 1
            "The last email sent did not contain the provided body."
166
        );
167
168 1
        return $this;
169
    }
170
171
    /**
172
     * Assert that the last email's content type equals the given text.
173
     * For example, "text/plain" and "text/html" are valid content types for an email.
174
     *
175
     * @param string             $content_type
176
     * @param Swift_Message|null $message
177
     *
178
     * @return $this
179
     */
180 1
    protected function seeEmailContentTypeEquals($content_type, Swift_Message $message = null)
181
    {
182 1
        $this->assertEquals(
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

182
        $this->/** @scrutinizer ignore-call */ 
183
               assertEquals(
Loading history...
183 1
            $content_type,
184 1
            $this->getEmail($message)
185 1
                 ->getContentType(),
186 1
            "The last email sent did not contain the provided body."
187
        );
188
189 1
        return $this;
190
    }
191
192
    /**
193
     * Assert that the last email's body does not contain the given text.
194
     *
195
     * @param string             $excerpt
196
     * @param Swift_Message|null $message
197
     *
198
     * @return $this
199
     */
200 1
    protected function seeEmailDoesNotContain($excerpt, Swift_Message $message = null)
201
    {
202 1
        $this->assertStringNotContainsString(
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

202
        $this->/** @scrutinizer ignore-call */ 
203
               assertStringNotContainsString(
Loading history...
203 1
            $excerpt,
204 1
            $this->getEmail($message)
205 1
                 ->getBody(),
206 1
            "The last email sent contained the provided text in its body."
207
        );
208
209 1
        return $this;
210
    }
211
212
    /**
213
     * Assert that the last email's body equals the given text.
214
     *
215
     * @param string             $body
216
     * @param Swift_Message|null $message
217
     *
218
     * @return $this
219
     */
220 1
    protected function seeEmailEquals($body, Swift_Message $message = null)
221
    {
222 1
        $this->assertEquals(
223 1
            $body,
224 1
            $this->getEmail($message)
225 1
                 ->getBody(),
226 1
            "The last email sent did not match the given email."
227
        );
228
229 1
        return $this;
230
    }
231
232
    /**
233
     * Assert that the last email was delivered by the given address.
234
     *
235
     * @param string             $sender
236
     * @param Swift_Message|null $message
237
     *
238
     * @return $this
239
     */
240 1
    protected function seeEmailFrom($sender, Swift_Message $message = null)
241
    {
242
        // TODO: Allow from to be an array to check email & name
243 1
        $this->assertArrayHasKey(
244 1
            $sender,
245 1
            (array)$this->getEmail($message)
246 1
                        ->getFrom(),
247 1
            "The last email sent was not sent from $sender."
248
        );
249
250 1
        return $this;
251
    }
252
253
    /**
254
     * Assert that the last email had the given priority level.
255
     * The value is an integer where 1 is the highest priority and 5 is the lowest.
256
     *
257
     * @param integer            $priority
258
     * @param Swift_Message|null $message
259
     *
260
     * @return $this
261
     */
262 1
    protected function seeEmailPriorityEquals($priority, Swift_Message $message = null)
263
    {
264 1
        $actual_priority = $this->getEmail($message)
265 1
                                ->getPriority();
266
267 1
        $this->assertEquals(
268 1
            $priority,
269 1
            $actual_priority,
270 1
            "The last email sent had a priority of $actual_priority but expected $priority."
271
        );
272
273 1
        return $this;
274
    }
275
276
    /**
277
     * Assert that the last email was set to reply to the given address.
278
     *
279
     * @param string             $reply_to
280
     * @param Swift_Message|null $message
281
     *
282
     * @return $this
283
     */
284 1
    protected function seeEmailReplyTo($reply_to, Swift_Message $message = null)
285
    {
286 1
        $this->assertArrayHasKey(
287 1
            $reply_to,
288 1
            (array)$this->getEmail($message)
289 1
                        ->getReplyTo(),
290 1
            "The last email sent was not set to reply to $reply_to."
291
        );
292
293 1
        return $this;
294
    }
295
296
    /**
297
     * Assert that the given number of emails were sent.
298
     *
299
     * @param integer $count
300
     *
301
     * @return MailTracking $this
302
     * @deprecated in favor of seeEmailCountEquals
303
     */
304 1
    protected function seeEmailsSent($count)
305
    {
306 1
        return $this->seeEmailCountEquals($count);
307
    }
308
309
    /**
310
     * Assert that the given number of emails were sent.
311
     *
312
     * @param integer $count
313
     *
314
     * @return $this
315
     */
316 1
    protected function seeEmailCountEquals($count)
317
    {
318 1
        $emailsSent = count($this->emails);
319
320 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

320
        $this->/** @scrutinizer ignore-call */ 
321
               assertCount($count, $this->emails, "Expected $count emails to have been sent, but $emailsSent were.");
Loading history...
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 MailTracking $this
332
     * @deprecated in favor of seeEmailSubjectEquals
333
     */
334
    protected function seeEmailSubject($subject, Swift_Message $message = null)
335
    {
336
        return $this->seeEmailSubjectEquals($subject, $message);
337
    }
338
339
    /**
340
     * Assert that the last email's subject contains the given string.
341
     *
342
     * @param string             $excerpt
343
     * @param Swift_Message|null $message
344
     *
345
     * @return $this
346
     */
347 1
    protected function seeEmailSubjectContains($excerpt, Swift_Message $message = null)
348
    {
349 1
        $this->assertStringContainsString(
350 1
            $excerpt,
351 1
            $this->getEmail($message)
352 1
                 ->getSubject(),
353 1
            "The last email sent did not contain the provided subject."
354
        );
355
356 1
        return $this;
357
    }
358
359
    /**
360
     * Assert that the last email's subject does not contain the given string.
361
     *
362
     * @param string             $excerpt
363
     * @param Swift_Message|null $message
364
     *
365
     * @return $this
366
     */
367 1
    protected function seeEmailSubjectDoesNotContain($excerpt, Swift_Message $message = null)
368
    {
369 1
        $this->assertStringNotContainsString(
370 1
            $excerpt,
371 1
            $this->getEmail($message)
372 1
                 ->getSubject(),
373 1
            "The last email sent contained the provided text in its subject."
374
        );
375
376 1
        return $this;
377
    }
378
379
    /**
380
     * Assert that the last email's subject matches the given string.
381
     *
382
     * @param string             $subject
383
     * @param Swift_Message|null $message
384
     *
385
     * @return $this
386
     */
387 1
    protected function seeEmailSubjectEquals($subject, Swift_Message $message = null)
388
    {
389 1
        $this->assertEquals(
390 1
            $subject,
391 1
            $this->getEmail($message)
392 1
                 ->getSubject(),
393 1
            "The last email sent did not contain a subject of $subject."
394
        );
395
396 1
        return $this;
397
    }
398
399
    /**
400
     * Assert that the last email was sent to the given recipient.
401
     *
402
     * @param string             $recipient
403
     * @param Swift_Message|null $message
404
     *
405
     * @return $this
406
     */
407 1
    protected function seeEmailTo($recipient, Swift_Message $message = null)
408
    {
409 1
        $this->assertArrayHasKey(
410 1
            $recipient,
411 1
            (array)$this->getEmail($message)
412 1
                        ->getTo(),
413 1
            "The last email sent was not sent to $recipient."
414
        );
415
416 1
        return $this;
417
    }
418
419
    /**
420
     * Assert that no emails were sent.
421
     *
422
     * @return $this
423
     */
424 1
    protected function seeEmailWasNotSent()
425
    {
426 1
        $emailsSent = count($this->emails);
427
428 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

428
        $this->/** @scrutinizer ignore-call */ 
429
               assertEmpty($this->emails, "Did not expect any emails to have been sent, but found $emailsSent");
Loading history...
429
430 1
        return $this;
431
    }
432
433
    /**
434
     * Assert that at least one email was sent.
435
     *
436
     * @return $this
437
     */
438 14
    protected function seeEmailWasSent()
439
    {
440 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

440
        $this->/** @scrutinizer ignore-call */ 
441
               assertNotEmpty($this->emails, 'Expected at least one email to be sent, but found none.');
Loading history...
441
442 14
        return $this;
443
    }
444
}
445