Completed
Push — master ( 078292...b58d46 )
by Jonathan
12s
created

MailContext::followLinkInMail()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 26
rs 8.439
cc 5
eloc 16
nc 5
nop 3
1
<?php
2
3
namespace Drupal\DrupalExtension\Context;
4
5
use Behat\Gherkin\Node\TableNode;
6
7
/**
8
 * Provides pre-built step definitions for interacting with mail.
9
 */
10
class MailContext extends RawMailContext
11
{
12
13
    /**
14
   * By default, prevent mail from being actually sent out during tests.
15
   *
16
   * @BeforeScenario
17
   */
18 View Code Duplication
    public function disableMail($event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
19
    {
20
        $tags = array_merge($event->getFeature()->getTags(), $event->getScenario()->getTags());
21
        if (!in_array('sendmail', $tags) && !in_array('sendemail', $tags)) {
22
            $this->getMailManager()->disableMail();
23
            // Always reset mail count, in case the default mail manager is being used
24
            // which enables mail collecting automatically when mail is disabled, making
25
            //the use of the @mail tag optional in this case.
26
            $this->mailCount = [];
27
        }
28
    }
29
30
  /**
31
   * Restore mail sending.
32
   *
33
   * @AfterScenario
34
   */
35 View Code Duplication
    public function enableMail($event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
36
    {
37
        $tags = array_merge($event->getFeature()->getTags(), $event->getScenario()->getTags());
38
        if (!in_array('sendmail', $tags) && !in_array('sendemail', $tags)) {
39
            $this->getMailManager()->enableMail();
40
        }
41
    }
42
43
  /**
44
   * Allow opting in to mail collection. When using the default mail manager
45
   * service, it is not necessary to use this tag.
46
   *
47
   * @BeforeScenario @mail @email
48
   */
49
    public function collectMail()
50
    {
51
        $this->getMailManager()->startCollectingMail();
52
    }
53
54
  /**
55
   * Stop collecting mail at scenario end.
56
   *
57
   * @AfterScenario @mail @email
58
   */
59
    public function stopCollectingMail()
60
    {
61
        $this->getMailManager()->stopCollectingMail();
62
    }
63
64
  /**
65
   * This is mainly useful for testing this context.
66
   *
67
   * @When Drupal sends a/an (e)mail:
68
   */
69
    public function drupalSendsMail(TableNode $fields)
70
    {
71
        $mail = [
72
        'body' => $this->getRandom()->name(255),
73
        'subject' => $this->getRandom()->name(20),
74
        'to' => $this->getRandom()->name(10) . '@anonexample.com',
75
        'langcode' => '',
76
        ];
77
        foreach ($fields->getRowsHash() as $field => $value) {
78
            $mail[$field] = $value;
79
        }
80
        $this->getDriver()->sendMail($mail['body'], $mail['subject'], $mail['to'], $mail['langcode']);
81
    }
82
83
  /**
84
   * Check all mail sent during the scenario.
85
   *
86
   * @Then (a )(an )(e)mail(s) has/have been sent:
87
   * @Then (a )(an )(e)mail(s) has/have been sent to :to:
88
   * @Then (a )(an )(e)mail(s) has/have been sent with the subject :subject:
89
   * @Then (a )(an )(e)mail(s) has/have been sent to :to with the subject :subject:
90
   */
91
    public function mailHasBeenSent(TableNode $expectedMailTable, $to = '', $subject = '')
92
    {
93
        $expectedMail = $expectedMailTable->getHash();
94
        $actualMail = $this->getMail(['to' => $to, 'subject' => $subject], false);
95
        $this->compareMail($actualMail, $expectedMail);
96
    }
97
98
  /**
99
   * Check mail sent since the last step that checked mail.
100
   *
101
   * @Then (a )(an )new (e)mail(s) is/are sent:
102
   * @Then (a )(an )new (e)mail(s) is/are sent to :to:
103
   * @Then (a )(an )new (e)mail(s) is/are sent with the subject :subject:
104
   * @Then (a )(an )new (e)mail(s) is/are sent to :to with the subject :subject:
105
   */
106
    public function newMailIsSent(TableNode $expectedMailTable, $to = '', $subject = '')
107
    {
108
        $expectedMail = $expectedMailTable->getHash();
109
        $actualMail = $this->getMail(['to' => $to, 'subject' => $subject], true);
110
        $this->compareMail($actualMail, $expectedMail);
111
    }
112
113
  /**
114
   * Check all mail sent during the scenario.
115
   *
116
   * @Then :count (e)mail(s) has/have been sent
117
   * @Then :count (e)mail(s) has/have been sent to :to
118
   * @Then :count (e)mail(s) has/have been sent with the subject :subject
119
   * @Then :count (e)mail(s) has/have been sent to :to with the subject :subject
120
   */
121
    public function noMailHasBeenSent($count, $to = '', $subject = '')
122
    {
123
        $actualMail = $this->getMail(['to' => $to, 'subject' => $subject], false);
124
        $count = $count === 'no' ? 0 : $count;
125
        $count = $count === 'a' ? null : $count;
126
        $count = $count === 'an' ? null : $count;
127
        $this->assertMailCount($actualMail, $count);
128
    }
129
130
  /**
131
   * Check mail sent since the last step that checked mail.
132
   *
133
   * @Then :count new (e)mail(s) is/are sent
134
   * @Then :count new (e)mail(s) is/are sent to :to
135
   * @Then :count new (e)mail(s) is/are sent with the subject :subject
136
   * @Then :count new (e)mail(s) is/are sent to :to with the subject :subject
137
   */
138
    public function noNewMailIsSent($count, $to = '', $subject = '')
139
    {
140
        $actualMail = $this->getMail(['to' => $to, 'subject' => $subject], true);
141
        $count = $count === 'no' ? 0 : $count;
142
        $count = $count === 'a' ? 1 : $count;
143
        $count = $count === 'an' ? 1 : $count;
144
        $this->assertMailCount($actualMail, $count);
145
    }
146
  
147
  /**
148
   * @When I follow the link to :urlFragment from the (e)mail
149
   * @When I follow the link to :urlFragment from the (e)mail to :to
150
   * @When I follow the link to :urlFragment from the (e)mail with the subject :subject
151
   * @When I follow the link to :urlFragment from the (e)mail to :to with the subject :subject
152
   */
153
    public function followLinkInMail($urlFragment, $to = '', $subject = '')
154
    {
155
        // Get the mail
156
        $matches = ['to' => $to, 'subject' => $subject];
157
        $mail = $this->getMail($matches, false, -1);
158
        if (count($mail) == 0) {
159
            throw new \Exception('No such mail found.');
160
        }
161
        $body = $mail['body'];
162
163
        // Find web URLs in the mail
164
        $urlPattern = '`.*?((http|https)://[\w#$&+,\/:;[email protected]]+)[^\w#$&+,\/:;[email protected]]*?`i';
165
        if (preg_match_all($urlPattern, $body, $urls)) {
166
            // Visit the first url that contains the desired fragment.
167
            foreach ($urls[1] as $url) {
168
                $match = (strpos(strtolower($url), strtolower($urlFragment)) !== false);
169
                if ($match) {
170
                    $this->getMinkContext()->visitPath($url);
171
                    return;
172
                }
173
            }
174
            throw new \Exception(sprintf('No URL in mail body contained "%s".', $urlFragment));
175
        } else {
176
            throw new \Exception('No URL found in mail body.');
177
        }
178
    }
179
}
180