Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into 195-email-testing
  • Loading branch information
jhedstrom committed Mar 15, 2018
2 parents 3def21b + 5413e26 commit 2190203
Show file tree
Hide file tree
Showing 6 changed files with 620 additions and 0 deletions.
1 change: 1 addition & 0 deletions behat.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ drupal8:
- Drupal\DrupalExtension\Context\MinkContext
- Drupal\DrupalExtension\Context\MarkupContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\MailContext
filters:
tags: "@d8&&~@d8wip"
extensions:
Expand Down
91 changes: 91 additions & 0 deletions features/mail.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
@api @d8
Feature: MailContext
In order to prove the Mail context is working properly
As a developer
I need to use the step definitions of this context

Scenario: Mail is sent
When Drupal sends an email:
| to | fred@example.com |
| subject | test |
| body | test body |
And Drupal sends a mail:
| to | jane@example.com |
| subject | test |
| body | test body 2 |
Then mails have been sent:
| to | subject | body |
| fred | | test body |
| jane | test | body 2 |
When Drupal sends a mail:
| to | jack@example.com |
| subject | for jack |
| body | test body with many words |
Then new email is sent:
| to | body | body |
| jack | test | many words |
And a mail has been sent to "[email protected]"
And a mail has been sent to "[email protected]":
| subject |
| test |
And an email has been sent with the subject "test"
And emails have been sent with the subject "test":
| to |
| fred |
| jane |
And a mail has been sent to "fred" with the subject "test"
And emails have been sent to "fred" with the subject "test":
| body |
| test body |

Scenario: New mail is sent to someone
When Drupal sends a mail:
| to | fred@example.com |
| subject | test 1 |
And Drupal sends a mail:
| to | jane@example.com |
| subject | test 2 |
Then new mail is sent to fred:
| subject |
| test 1 |


Scenario: No mail is sent
Then no mail has been sent

Scenario: Count sent mail
When Drupal sends an email:
| to | fred@example.com |
| subject | test |
And Drupal sends a mail:
| to | jane@example.com |
| subject | test |
And Drupal sends a mail:
| to | jane@example.com |
| subject | something else |
Then 2 new emails are sent with the subject "test"
And 1 mail has been sent to "jane" with the subject "something else"
And no new emails are sent
And no mail has been sent to "hans"

Scenario: I follow link in mail
When Drupal sends a mail:
| to | fred@example.com |
| subject | test link |
| body | A link to Google: http://www.Google.com |
And I follow the link to "google" from the mail with the subject "test link"
Then I should see "Search"

Scenario: We try to be order insensitive
When Drupal sends an email:
| to | fred@example.com |
| subject | test |
| body | test body |
And Drupal sends a mail:
| to | jane@example.com |
| subject | test |
| body | test body 2 |
Then mails have been sent:
| to | subject | body |
| jane | test | body 2 |
| fred | | test body |
170 changes: 170 additions & 0 deletions src/Drupal/DrupalExtension/Context/MailContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php

namespace Drupal\DrupalExtension\Context;

use Behat\Gherkin\Node\TableNode;

/**
* Provides pre-built step definitions for interacting with mail.
*/
class MailContext extends RawMailContext {

/**
* By default, prevent mail from being actually sent out during tests.
*
* @BeforeScenario
*/
public function disableMail($event) {
$tags = array_merge($event->getFeature()->getTags(), $event->getScenario()->getTags());
if (!in_array('sendmail', $tags) && !in_array('sendemail', $tags)) {
$this->getMailManager()->disableMail();
// Always reset mail count, in case the default mail manager is being used
// which enables mail collecting automatically when mail is disabled, making
//the use of the @mail tag optional in this case.
$this->mailCount = [];
}
}

/**
* Restore mail sending.
*
* @AfterScenario
*/
public function enableMail($event) {
$tags = array_merge($event->getFeature()->getTags(), $event->getScenario()->getTags());
if (!in_array('sendmail', $tags) && !in_array('sendemail', $tags)) {
$this->getMailManager()->enableMail();
}
}

/**
* Allow opting in to mail collection. When using the default mail manager
* service, it is not necessary to use this tag.
*
* @BeforeScenario @mail @email
*/
public function collectMail() {
$this->getMailManager()->startCollectingMail();
}

/**
* Stop collecting mail at scenario end.
*
* @AfterScenario @mail @email
*/
public function stopCollectingMail() {
$this->getMailManager()->stopCollectingMail();
}

/**
* This is mainly useful for testing this context.
*
* @When Drupal sends a/an (e)mail:
*/
public function DrupalSendsMail(TableNode $fields) {
$mail = [
'body' => $this->getRandom()->name(255),
'subject' => $this->getRandom()->name(20),
'to' => $this->getRandom()->name(10) . '@anonexample.com',
'langcode' => '',
];
foreach ($fields->getRowsHash() as $field => $value) {
$mail[$field] = $value;
}
$this->getDriver()->sendMail($mail['body'], $mail['subject'], $mail['to'], $mail['langcode']);
}

/**
* Check all mail sent during the scenario.
*
* @Then (a )(an )(e)mail(s) has/have been sent:
* @Then (a )(an )(e)mail(s) has/have been sent to :to:
* @Then (a )(an )(e)mail(s) has/have been sent with the subject :subject:
* @Then (a )(an )(e)mail(s) has/have been sent to :to with the subject :subject:
*/
public function mailHasBeenSent(TableNode $expectedMailTable, $to = '', $subject = '') {
$expectedMail = $expectedMailTable->getHash();
$actualMail = $this->getMail(['to' => $to, 'subject' => $subject], FALSE);
$this->compareMail($actualMail, $expectedMail);
}

/**
* Check mail sent since the last step that checked mail.
*
* @Then (a )(an )new (e)mail(s) is/are sent:
* @Then (a )(an )new (e)mail(s) is/are sent to :to:
* @Then (a )(an )new (e)mail(s) is/are sent with the subject :subject:
* @Then (a )(an )new (e)mail(s) is/are sent to :to with the subject :subject:
*/
public function newMailIsSent(TableNode $expectedMailTable, $to = '', $subject = '') {
$expectedMail = $expectedMailTable->getHash();
$actualMail = $this->getMail(['to' => $to, 'subject' => $subject], TRUE);
$this->compareMail($actualMail, $expectedMail);
}

/**
* Check all mail sent during the scenario.
*
* @Then :count (e)mail(s) has/have been sent
* @Then :count (e)mail(s) has/have been sent to :to
* @Then :count (e)mail(s) has/have been sent with the subject :subject
* @Then :count (e)mail(s) has/have been sent to :to with the subject :subject
*/
public function noMailHasBeenSent($count, $to = '', $subject = '') {
$actualMail = $this->getMail(['to' => $to, 'subject' => $subject], FALSE);
$count = $count === 'no' ? 0 : $count;
$count = $count === 'a' ? NULL : $count;
$count = $count === 'an' ? NULL : $count;
$this->assertMailCount($actualMail, $count);
}

/**
* Check mail sent since the last step that checked mail.
*
* @Then :count new (e)mail(s) is/are sent
* @Then :count new (e)mail(s) is/are sent to :to
* @Then :count new (e)mail(s) is/are sent with the subject :subject
* @Then :count new (e)mail(s) is/are sent to :to with the subject :subject
*/
public function noNewMailIsSent($count, $to = '', $subject = '') {
$actualMail = $this->getMail(['to' => $to, 'subject' => $subject], TRUE);
$count = $count === 'no' ? 0 : $count;
$count = $count === 'a' ? 1 : $count;
$count = $count === 'an' ? 1 : $count;
$this->assertMailCount($actualMail, $count);
}

/**
* @When I follow the link to :urlFragment from the (e)mail
* @When I follow the link to :urlFragment from the (e)mail to :to
* @When I follow the link to :urlFragment from the (e)mail with the subject :subject
* @When I follow the link to :urlFragment from the (e)mail to :to with the subject :subject
*/
public function followLinkInMail($urlFragment, $to = '', $subject = '') {
// Get the mail
$matches = ['to' => $to, 'subject' => $subject];
$mail = $this->getMail($matches, FALSE, -1);
if (count($mail) == 0) {
throw new \Exception('No such mail found.');
}
$body = $mail['body'];

// Find web URLs in the mail
$urlPattern = '`.*?((http|https)://[\w#$&+,\/:;[email protected]]+)[^\w#$&+,\/:;[email protected]]*?`i';
if (preg_match_all($urlPattern, $body, $urls)) {
// Visit the first url that contains the desired fragment.
foreach ($urls[1] as $url) {
$match = (strpos(strtolower($url), strtolower($urlFragment)) !== FALSE);
if ($match) {
$this->getMinkContext()->visitPath($url);
return;
}
}
throw new \Exception(sprintf('No URL in mail body contained "%s".', $urlFragment));
}
else {
throw new \Exception('No URL found in mail body.');
}
}

}
Loading

0 comments on commit 2190203

Please sign in to comment.