1<?php
2
3/*
4 * This file is part of the symfony package.
5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11/**
12 * sfTesterMailer implements tests for the symfony mailer object.
13 *
14 * @package    symfony
15 * @subpackage test
16 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17 * @version    SVN: $Id$
18 */
19class sfTesterMailer extends sfTester
20{
21  protected
22    $logger  = null,
23    $message = null;
24
25  /**
26   * Prepares the tester.
27   */
28  public function prepare()
29  {
30  }
31
32  /**
33   * Initializes the tester.
34   */
35  public function initialize()
36  {
37    $this->logger = $this->browser->getContext()->getMailer()->getLogger();
38
39    if ($this->logger->countMessages())
40    {
41      $messages = $this->logger->getMessages();
42
43      $this->message = $messages[0];
44    }
45  }
46
47  /**
48   * Tests if message was send and optional how many.
49   *
50   * @param int $nb number of messages
51   *
52   * @return sfTestFunctionalBase|sfTester
53   */
54  public function hasSent($nb = null)
55  {
56    if (null === $nb)
57    {
58      $this->tester->ok($this->logger->countMessages() > 0, 'mailer sent some email(s).');
59    }
60    else
61    {
62      $this->tester->is($this->logger->countMessages(), $nb, sprintf('mailer sent %s email(s).', $nb));
63    }
64
65    return $this->getObjectToReturn();
66  }
67
68  /**
69   * Outputs some debug information about mails sent during the current request.
70   */
71  public function debug()
72  {
73    foreach ($this->logger->getMessages() as $message)
74    {
75      echo $message->toString()."\n\n";
76    }
77
78    exit(1);
79  }
80
81  /**
82   * Changes the context to use the email corresponding to the given criteria.
83   *
84   * @param string|array $to       the email or array(email => alias)
85   * @param int          $position address position
86   *
87   * @return sfTestFunctionalBase|sfTester
88   */
89  public function withMessage($to, $position = 1)
90  {
91    $messageEmail = $to;
92    if(is_array($to))
93    {
94      $alias        = current($to);
95      $to           = key($to);
96      $messageEmail = sprintf('%s <%s>', $alias, $to);
97    }
98
99    $matches = 0;
100    foreach ($this->logger->getMessages() as $message)
101    {
102      $email = $message->getTo();
103      if ($to == key($email))
104      {
105        $matches++;
106
107        if ($matches == $position)
108        {
109          $this->message = $message;
110
111          if(isset($alias) AND $alias != current($email))
112          {
113            break;
114          }
115
116          $this->tester->pass(sprintf('switch context to the message number "%s" sent to "%s"', $position, $messageEmail));
117
118          return $this;
119        }
120      }
121    }
122
123    $this->tester->fail(sprintf('unable to find a message sent to "%s"', $messageEmail));
124
125    return $this;
126  }
127
128  /**
129   * Tests for a mail message body.
130   *
131   * @param string $value regular expression or value
132   *
133   * @return sfTestFunctionalBase|sfTester
134   */
135  public function checkBody($value)
136  {
137    if (!$this->message)
138    {
139      $this->tester->fail('unable to test as no email were sent');
140    }
141
142    $body = $this->message->getBody();
143    $ok = false;
144    $regex = false;
145    $mustMatch = true;
146    if (preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $value, $match))
147    {
148      $regex = $value;
149      if ($match[1] == '!')
150      {
151        $mustMatch = false;
152        $regex = substr($value, 1);
153      }
154    }
155
156    if (false !== $regex)
157    {
158      if ($mustMatch)
159      {
160        if (preg_match($regex, $body))
161        {
162          $ok = true;
163          $this->tester->pass(sprintf('email body matches "%s"', $value));
164        }
165      }
166      else
167      {
168        if (preg_match($regex, $body))
169        {
170          $ok = true;
171          $this->tester->fail(sprintf('email body does not match "%s"', $value));
172        }
173      }
174    }
175    else if ($body == $value)
176    {
177      $ok = true;
178      $this->tester->pass(sprintf('email body is "%s"', $value));
179    }
180
181    if (!$ok)
182    {
183      if (!$mustMatch)
184      {
185        $this->tester->pass(sprintf('email body matches "%s"', $value));
186      }
187      else
188      {
189        $this->tester->fail(sprintf('email body matches "%s"', $value));
190      }
191    }
192
193    return $this->getObjectToReturn();
194  }
195
196  /**
197   * Tests for a mail message header.
198   *
199   * @param string $key   entry to test
200   * @param string $value regular expression or value
201   *
202   * @return sfTestFunctionalBase|sfTester
203   */
204  public function checkHeader($key, $value)
205  {
206    if (!$this->message)
207    {
208      $this->tester->fail('unable to test as no email were sent');
209    }
210
211    $headers = array();
212    foreach ($this->message->getHeaders()->getAll($key) as $header)
213    {
214      $headers[] = $header->getFieldBody();
215    }
216    $current = implode(', ', $headers);
217    $ok = false;
218    $regex = false;
219    $mustMatch = true;
220    if (preg_match('/^(!)?([^a-zA-Z0-9\\\\]).+?\\2[ims]?$/', $value, $match))
221    {
222      $regex = $value;
223      if ($match[1] == '!')
224      {
225        $mustMatch = false;
226        $regex = substr($value, 1);
227      }
228    }
229
230    foreach ($headers as $header)
231    {
232      if (false !== $regex)
233      {
234        if ($mustMatch)
235        {
236          if (preg_match($regex, $header))
237          {
238            $ok = true;
239            $this->tester->pass(sprintf('email header "%s" matches "%s" (%s)', $key, $value, $current));
240            break;
241          }
242        }
243        else
244        {
245          if (preg_match($regex, $header))
246          {
247            $ok = true;
248            $this->tester->fail(sprintf('email header "%s" does not match "%s" (%s)', $key, $value, $current));
249            break;
250          }
251        }
252      }
253      else if ($header == $value)
254      {
255        $ok = true;
256        $this->tester->pass(sprintf('email header "%s" is "%s" (%s)', $key, $value, $current));
257        break;
258      }
259    }
260
261    if (!$ok)
262    {
263      if (!$mustMatch)
264      {
265        $this->tester->pass(sprintf('email header "%s" matches "%s" (%s)', $key, $value, $current));
266      }
267      else
268      {
269        $this->tester->fail(sprintf('email header "%s" matches "%s" (%s)', $key, $value, $current));
270      }
271    }
272
273    return $this->getObjectToReturn();
274  }
275}
276