<?php | |
use Illuminate\Foundation\Testing\WithoutMiddleware; | |
use Illuminate\Foundation\Testing\DatabaseMigrations; | |
use Illuminate\Foundation\Testing\DatabaseTransactions; | |
class ExampleTest extends TestCase | |
{ | |
use MailTracking; | |
/** | |
* A basic functional test example. | |
* | |
* @return void | |
*/ | |
public function testBasicExample() | |
{ | |
$this->visit('/route-that-sends-an-email') | |
->seeEmailWasSent() | |
->seeEmailSubject('Hello World') | |
->seeEmailTo('foo@bar.com') | |
->seeEmailEquals('Click here to buy this jewelry.') | |
->seeEmailContains('Click here'); | |
} | |
} |
<?php | |
trait MailTracking | |
{ | |
/** | |
* Delivered emails. | |
*/ | |
protected $emails = []; | |
/** | |
* Register a listener for new emails. | |
* | |
* @before | |
*/ | |
public function setUpMailTracking() | |
{ | |
Mail::getSwiftMailer() | |
->registerPlugin(new TestingMailEventListener($this)); | |
} | |
/** | |
* Assert that at least one email was sent. | |
*/ | |
protected function seeEmailWasSent() | |
{ | |
$this->assertNotEmpty( | |
$this->emails, 'No emails have been sent.' | |
); | |
return $this; | |
} | |
/** | |
* Assert that no emails were sent. | |
*/ | |
protected function seeEmailWasNotSent() | |
{ | |
$this->assertEmpty( | |
$this->emails, 'Did not expect any emails to have been sent.' | |
); | |
return $this; | |
} | |
/** | |
* Assert that the given number of emails were sent. | |
* | |
* @param integer $count | |
*/ | |
protected function seeEmailsSent($count) | |
{ | |
$emailsSent = count($this->emails); | |
$this->assertCount( | |
$count, $this->emails, | |
"Expected $count emails to have been sent, but $emailsSent were." | |
); | |
return $this; | |
} | |
/** | |
* Assert that the last email's body equals the given text. | |
* | |
* @param string $body | |
* @param Swift_Message $message | |
*/ | |
protected function seeEmailEquals($body, Swift_Message $message = null) | |
{ | |
$this->assertEquals( | |
$body, $this->getEmail($message)->getBody(), | |
"No email with the provided body was sent." | |
); | |
return $this; | |
} | |
/** | |
* Assert that the last email's body contains the given text. | |
* | |
* @param string $excerpt | |
* @param Swift_Message $message | |
*/ | |
protected function seeEmailContains($excerpt, Swift_Message $message = null) | |
{ | |
$this->assertContains( | |
$excerpt, $this->getEmail($message)->getBody(), | |
"No email containing the provided body was found." | |
); | |
return $this; | |
} | |
/** | |
* Assert that the last email's subject matches the given string. | |
* | |
* @param string $subject | |
* @param Swift_Message $message | |
*/ | |
protected function seeEmailSubject($subject, Swift_Message $message = null) | |
{ | |
$this->assertEquals( | |
$subject, $this->getEmail($message)->getSubject(), | |
"No email with a subject of $subject was found." | |
); | |
return $this; | |
} | |
/** | |
* Assert that the last email was sent to the given recipient. | |
* | |
* @param string $recipient | |
* @param Swift_Message $message | |
*/ | |
protected function seeEmailTo($recipient, Swift_Message $message = null) | |
{ | |
$this->assertArrayHasKey( | |
$recipient, (array) $this->getEmail($message)->getTo(), | |
"No email was sent to $recipient." | |
); | |
return $this; | |
} | |
/** | |
* Assert that the last email was delivered by the given address. | |
* | |
* @param string $sender | |
* @param Swift_Message $message | |
*/ | |
protected function seeEmailFrom($sender, Swift_Message $message = null) | |
{ | |
$this->assertArrayHasKey( | |
$sender, (array) $this->getEmail($message)->getFrom(), | |
"No email was sent from $sender." | |
); | |
return $this; | |
} | |
/** | |
* Store a new swift message. | |
* | |
* @param Swift_Message $email | |
*/ | |
public function addEmail(Swift_Message $email) | |
{ | |
$this->emails[] = $email; | |
} | |
/** | |
* Retrieve the appropriate swift message. | |
* | |
* @param Swift_Message $message | |
*/ | |
protected function getEmail(Swift_Message $message = null) | |
{ | |
$this->seeEmailWasSent(); | |
return $message ?: $this->lastEmail(); | |
} | |
/** | |
* Retrieve the mostly recently sent swift message. | |
*/ | |
protected function lastEmail() | |
{ | |
return end($this->emails); | |
} | |
} | |
class TestingMailEventListener implements Swift_Events_EventListener | |
{ | |
protected $test; | |
public function __construct($test) | |
{ | |
$this->test = $test; | |
} | |
public function beforeSendPerformed($event) | |
{ | |
$this->test->addEmail($event->getMessage()); | |
} | |
} |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Updated. Thanks! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
sebdesign
Jan 22, 2016
tests/phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit ...>
...
<php>
...
<env name="MAIL_DRIVER" value="log"/>
</php>
</phpunit>
sebdesign
commented
Jan 22, 2016
tests/phpunit.xml <?xml version="1.0" encoding="UTF-8"?>
<phpunit ...>
...
<php>
...
<env name="MAIL_DRIVER" value="log"/>
</php>
</phpunit> |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
mattkoch614
commented
Jan 22, 2016
@sebdesign Awwww yeah, I was just wondering how to do that. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
suth
Feb 12, 2016
The getBody() method used on Swift_Message didn't seem to be working (always returned null) when using Mail::raw() and plain text, so the seeEmailEquals and seeEmailContains assertions were always failing. Tried making an HTML view and using Mail::send() and everything worked beautifully.
suth
commented
Feb 12, 2016
The getBody() method used on Swift_Message didn't seem to be working (always returned null) when using Mail::raw() and plain text, so the seeEmailEquals and seeEmailContains assertions were always failing. Tried making an HTML view and using Mail::send() and everything worked beautifully. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
sebdesign
Apr 13, 2016
I added a method that asserts the message was BCC'd to the given recipients array.
/**
* Assert that the last email was sent to the given recipients.
*
* @param array $recipients
* @param Swift_Message $message
*/
protected function seeEmailBcc(array $recipients, Swift_Message $message = null)
{
$bcc = array_keys((array) $this->getEmail($message)->getBcc());
sort($recipients);
sort($bcc);
$this->assertArraySubset(
$recipients, $bcc,
'',
'No email was BCC\'d to: '.implode(', ', $recipients)
);
return $this;
}
sebdesign
commented
Apr 13, 2016
I added a method that asserts the message was BCC'd to the given recipients array. /**
* Assert that the last email was sent to the given recipients.
*
* @param array $recipients
* @param Swift_Message $message
*/
protected function seeEmailBcc(array $recipients, Swift_Message $message = null)
{
$bcc = array_keys((array) $this->getEmail($message)->getBcc());
sort($recipients);
sort($bcc);
$this->assertArraySubset(
$recipients, $bcc,
'',
'No email was BCC\'d to: '.implode(', ', $recipients)
);
return $this;
} |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Tjoosten
commented
Jun 29, 2016
But how does the |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
helmut
commented
Jul 21, 2016
Jeffrey can you see this being added to the core? It's pretty dang useful... |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Oldenborg
Sep 7, 2016
This breaks down after I switched to 5.3, does any one have a patched version that works with 5.3 Mailables
Oldenborg
commented
Sep 7, 2016
This breaks down after I switched to 5.3, does any one have a patched version that works with 5.3 Mailables |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
duartealexf
Sep 8, 2016
@olde86 It worked for me, using the 5.3 Mailables. Only thing I did was separate the event listener to its own file.
duartealexf
commented
Sep 8, 2016
@olde86 It worked for me, using the 5.3 Mailables. Only thing I did was separate the event listener to its own file. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dericlima
May 9, 2017
Looks like an amazing solution, I'm trying to implement this trait to use with Selenium, should be simple but I'm stuck.
Basically, I just moved the Email listener to a class itself and use the trait.
use Illuminate\Support\Facades\Mail;
class BasicFunctionalitiesTest extends PHPUnit_Extensions_Selenium2TestCase
{
use MailTracking;
// Code
But I'm getting this error:
A facade root has not been set.
So I tried to create a container to solve:
$app = new Container();
$app->singleton('app', 'Illuminate\Container\Container');
/**
* Set $app as FacadeApplication handler
*/
Facade::setFacadeApplication($app);
But no luck so far. Now I'm getting:
Class mailer does not exist
Some Idea? Thanks
dericlima
commented
May 9, 2017
Looks like an amazing solution, I'm trying to implement this trait to use with Selenium, should be simple but I'm stuck.
But I'm getting this error:
So I tried to create a container to solve:
But no luck so far. Now I'm getting:
Some Idea? Thanks |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dericlima
May 10, 2017
I solved! The application instance contains all Classes that I need, I could use Facades but I was looking for the Mail Class that is instantiated during the boot.
So, the solution was to retrieve the app instance:
$app = require __DIR__.'/../../bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
$request = Request::capture()
);
And to use the Mail:
$mailer = App::make('mailer');
$mailer->getSwiftMailer()
->registerPlugin(new TestMailEventListener($this));
dericlima
commented
May 10, 2017
I solved! The application instance contains all Classes that I need, I could use Facades but I was looking for the Mail Class that is instantiated during the boot.
And to use the Mail:
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
mgodinez98
Jun 28, 2017
@suth i have the same problem, when i send an email as raw the method getBody() always returns me null, so i made a function based on this post https://stackoverflow.com/questions/39926766/message-getbody-null-when-listening-on-mailer-sending-event
/**
* Assert that the last email's body equals the given text.
*
* @param string $body
* @param Swift_Message $message
* @return $this
*/
protected function getMessageBody(Swift_Message $message)
{
if($htmlBody = $message->getBody()){
return $htmlBody;
}
$children = $message->getChildren();
if (isset($children[0]) && $children[0] instanceof \Swift_MimePart) {
return $children[0]->getBody();
}
return null;
}
and inside the seeEmailEquals i call this function
/**
* Assert that the last email's body equals the given text.
*
* @param string $body
* @param Swift_Message $message
* @return $this
*/
protected function seeEmailEquals($body, Swift_Message $message = null)
{
$this->assertEquals(
$body, $this->getMessageBody($this->getEmail($message)),
"No email with the provided body was sent."
);
return $this;
}
I know this is not the best approach but it works for me :)
mgodinez98
commented
Jun 28, 2017
@suth i have the same problem, when i send an email as raw the method getBody() always returns me null, so i made a function based on this post https://stackoverflow.com/questions/39926766/message-getbody-null-when-listening-on-mailer-sending-event
and inside the seeEmailEquals i call this function
I know this is not the best approach but it works for me :) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Organizm238
Jul 20, 2017
How to make this working for Laravel 5.4? I was getting error
A facade root has not been set.
I fixed it by putting $this->createApplication();
in setUpMailTracking
method:
public function setUpMailTracking()
{
$this->createApplication();
Mail::getSwiftMailer()->registerPlugin(new TestingMailEventListener($this));
}
But now my beforeSendPerformed
is not executed. What adjustments i need to do?
UPD: Just do the following and everything will work:
public function setUpMailTracking()
{
parent::setUp();
Mail::getSwiftMailer()->registerPlugin(new TestingMailEventListener($this));
}
Organizm238
commented
Jul 20, 2017
•
edited
edited
How to make this working for Laravel 5.4? I was getting error
But now my UPD: Just do the following and everything will work:
|
This comment has been minimized.
Show comment Hide commentdanijeelJan 21, 2016
danijeel commentedJan 21, 2016