Passed
Pull Request — develop (#56)
by Stephen
01:49
created

MailTracking::seeEmailSubjectContains()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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

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

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

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