Completed
Push — master ( 64f98e...11f175 )
by Jimmy
03:19 queued 01:21
created

MailTracking::setUpMailTracking()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace Spinen\MailAssertions;
4
5
use Illuminate\Support\Facades\Mail;
6
use PHPUnit_Framework_TestCase;
7
use Swift_Message;
8
9
/**
10
 * Class MailTracking
11
 *
12
 * Trait to mixin to your test to allow for custom assertions when using PHPUnit with Laravel.
13
 *
14
 * This originally started out as a copy & paste from a video series that Jeffery 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 initial
17
 * assertions.
18
 *
19
 * I WANT IT CLEAR THAT THIS WOULD NOT HAVE HAPPENED WITHOUT THE INITIAL WORK OF JEFFERY 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 BCC
30
    // TODO: Add check for CC
31
    // TODO: Add check for header
32
    // TODO: Add check for message type
33
    // TODO: Add check for Priority
34
    // TODO: Add check for ReplyTo
35
    // TODO: Allow checking specific message not just most recent one
36
37
    /**
38
     * Delivered emails.
39
     *
40
     * @var array
41
     */
42
    protected $emails = [];
43
44
    /**
45
     * Register a listener for new emails.
46
     *
47
     * Called my PHPUnit before each test it run.  It registers the MailRecorder "plugin" with Swift, so that we can
48
     * get a copy of each email that is sent during that test.
49
     *
50
     * @before
51
     */
52
    public function setUpMailTracking()
53
    {
54
        Mail::getSwiftMailer()
55
            ->registerPlugin(new MailRecorder($this));
56
    }
57
58
    /**
59
     * Retrieve the appropriate swift message.
60
     *
61
     * @param Swift_Message $message
62
     *
63
     * @return Swift_Message
64
     */
65
    protected function getEmail(Swift_Message $message = null)
66
    {
67
        $this->seeEmailWasSent();
68
69
        return $message ?: $this->lastEmail();
70
    }
71
72
    /**
73
     * Retrieve the mostly recently sent swift message.
74
     */
75
    protected function lastEmail()
76
    {
77
        return end($this->emails);
78
    }
79
80
    /**
81
     * Store a new swift message.
82
     *
83
     * Collection of emails that were received by the MailRecorder plugin during a test.
84
     *
85
     * @param Swift_Message $email
86
     */
87
    public function recordMail(Swift_Message $email)
88
    {
89
        $this->emails[] = $email;
90
    }
91
92
    /**
93
     * Assert that the last email's body contains the given text.
94
     *
95
     * @param string        $excerpt
96
     * @param Swift_Message $message
97
     *
98
     * @return PHPUnit_Framework_TestCase $this
99
     */
100
    protected function seeEmailContains($excerpt, Swift_Message $message = null)
101
    {
102
        $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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
103
                                             ->getBody(), "No email containing the provided body was found.");
104
105
        return $this;
106
    }
107
108
    /**
109
     * Assert that the last email's body equals the given text.
110
     *
111
     * @param string        $body
112
     * @param Swift_Message $message
113
     *
114
     * @return PHPUnit_Framework_TestCase $this
115
     */
116
    protected function seeEmailEquals($body, Swift_Message $message = null)
117
    {
118
        $this->assertEquals($body, $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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
119
                                        ->getBody(), "No email with the provided body was sent.");
120
121
        return $this;
122
    }
123
124
    /**
125
     * Assert that the last email was delivered by the given address.
126
     *
127
     * @param string        $sender
128
     * @param Swift_Message $message
129
     *
130
     * @return PHPUnit_Framework_TestCase $this
131
     */
132
    protected function seeEmailFrom($sender, Swift_Message $message = null)
133
    {
134
        // TODO: Allow from to be an array to check email & name
135
        $this->assertArrayHasKey($sender, (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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
136
                                                      ->getFrom(), "No email was sent from $sender.");
137
138
        return $this;
139
    }
140
141
    /**
142
     * Assert that the given number of emails were sent.
143
     *
144
     * @param integer $count
145
     *
146
     * @return PHPUnit_Framework_TestCase $this
147
     */
148
    protected function seeEmailsSent($count)
149
    {
150
        $emailsSent = count($this->emails);
151
152
        $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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
153
154
        return $this;
155
    }
156
157
    /**
158
     * Assert that the last email's subject matches the given string.
159
     *
160
     * @param string        $subject
161
     * @param Swift_Message $message
162
     *
163
     * @return PHPUnit_Framework_TestCase $this
164
     */
165
    protected function seeEmailSubject($subject, Swift_Message $message = null)
166
    {
167
        // TODO: Consider a subject contains like the message contains
168
        $this->assertEquals($subject, $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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
169
                                           ->getSubject(), "No email with a subject of $subject was found.");
170
171
        return $this;
172
    }
173
174
    /**
175
     * Assert that the last email was sent to the given recipient.
176
     *
177
     * @param string        $recipient
178
     * @param Swift_Message $message
179
     *
180
     * @return PHPUnit_Framework_TestCase $this
181
     */
182
    protected function seeEmailTo($recipient, Swift_Message $message = null)
183
    {
184
        $this->assertArrayHasKey($recipient, (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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
185
                                                         ->getTo(), "No email was sent to $recipient.");
186
187
        return $this;
188
    }
189
190
    /**
191
     * Assert that no emails were sent.
192
     *
193
     * @return PHPUnit_Framework_TestCase $this
194
     */
195
    protected function seeEmailWasNotSent()
196
    {
197
        $this->assertEmpty($this->emails, 'Did not expect any emails to have been sent.');
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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
198
199
        return $this;
200
    }
201
202
    /**
203
     * Assert that at least one email was sent.
204
     *
205
     * @return PHPUnit_Framework_TestCase $this
206
     */
207
    protected function seeEmailWasSent()
208
    {
209
        $this->assertNotEmpty($this->emails, 'No emails have been sent.');
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?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
210
211
        return $this;
212
    }
213
}
214