INFRA-132 - tests/ - PHPStorm cleanup
[civicrm-core.git] / tests / phpunit / CiviTest / CiviMailUtils.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06a1bc01 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25*/
26
27/**
28 * Mail utils for use during unit testing to allow retrieval
29 * and examination of 'sent' emails.
30 *
31 * Basic usage:
32 *
33 * $mut = new CiviMailUtils( $this, true ); //true automatically starts spooling
34 * ... do stuff ...
35 * $msg = $mut->getMostRecentEmail( 'raw' ); // or 'ezc' to get an ezc mail object
36 * ... assert stuff about $msg ...
37 * $mut->stop();
38 *
39 *
40 * @package CiviCRM
41 */
42
43require_once 'ezc/Base/src/ezc_bootstrap.php';
44require_once 'ezc/autoload/mail_autoload.php';
45
4cbe18b8
EM
46/**
47 * Class CiviMailUtils
48 */
6a488035
TO
49class CiviMailUtils extends PHPUnit_Framework_TestCase {
50
51 /**
52 * @var mixed current outbound email option
53 */
54 protected $_outBound_option = NULL;
55
56 /**
57 * @var bool is this a webtest
58 */
59 protected $_webtest = FALSE;
60
61 /**
62 * Constructor
63 *
858d0bf8 64 * @param CiviSeleniumTestCase|CiviUnitTestCase $unit_test The currently running test
e16033b4
TO
65 * @param bool $startImmediately
66 * Start writing to db now or wait until start() is called.
6a488035 67 */
00be9182 68 public function __construct(&$unit_test, $startImmediately = TRUE) {
70520a0b
CW
69 $this->_ut = $unit_test;
70
6a488035
TO
71 // Check if running under webtests or not
72 if (is_subclass_of($unit_test, 'CiviSeleniumTestCase')) {
73 $this->_webtest = TRUE;
74 }
75
76 if ($startImmediately) {
77 $this->start();
78 }
79 }
80
81 /**
82 * Start writing emails to db instead of current option
83 */
00be9182 84 public function start() {
6a488035
TO
85 if ($this->_webtest) {
86 // Change outbound mail setting
14d3f751 87 $this->_ut->openCiviPage('admin/setting/smtp', "reset=1", "_qf_Smtp_next");
6a488035
TO
88
89 // First remember the current setting
90 $this->_outBound_option = $this->getSelectedOutboundOption();
91
92 $this->_ut->click('xpath=//input[@name="outBound_option" and @value="' . CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB . '"]');
14d3f751 93 $this->_ut->clickLink("_qf_Smtp_next");
6a488035
TO
94
95 // Is there supposed to be a status message displayed when outbound email settings are changed?
96 // assert something?
97
98 }
99 else {
100
101 // save current setting for outbound option, then change it
102 $mailingBackend = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
103 'mailing_backend'
104 );
105
106 $this->_outBound_option = $mailingBackend['outBound_option'];
107 $mailingBackend['outBound_option'] = CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB;
108
109 CRM_Core_BAO_Setting::setItem($mailingBackend,
110 CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
111 'mailing_backend'
112 );
113
114 $mailingBackend = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
115 'mailing_backend'
116 );
117 }
118 }
119
00be9182 120 public function stop() {
6a488035 121 if ($this->_webtest) {
054c3522
CW
122 if ($this->_outBound_option != CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB) {
123 // Change outbound mail setting
124 $this->_ut->openCiviPage('admin/setting/smtp', "reset=1", "_qf_Smtp_next");
125 $this->_ut->click('xpath=//input[@name="outBound_option" and @value="' . $this->_outBound_option . '"]');
3a35908d 126 // There will be a warning when switching from test to live mode
054c3522 127 if ($this->_outBound_option != CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED) {
499508f0 128 $this->_ut->getAlert();
054c3522
CW
129 }
130 $this->_ut->clickLink("_qf_Smtp_next");
131 }
6a488035
TO
132 }
133 else {
134
135 $mailingBackend = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
136 'mailing_backend'
137 );
138
139 $mailingBackend['outBound_option'] = $this->_outBound_option;
140
141 CRM_Core_BAO_Setting::setItem($mailingBackend,
142 CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
143 'mailing_backend'
144 );
145 }
146 }
147
4cbe18b8
EM
148 /**
149 * @param string $type
150 *
151 * @return ezcMail|string
152 */
00be9182 153 public function getMostRecentEmail($type = 'raw') {
6a488035
TO
154 $msg = '';
155
6a488035 156 if ($this->_webtest) {
6a488035 157 // I don't understand but for some reason we have to load the page twice for a recent mailing to appear.
14d3f751
CW
158 $this->_ut->openCiviPage('mailing/browse/archived', 'reset=1');
159 $this->_ut->openCiviPage('mailing/browse/archived', 'reset=1', 'css=td.crm-mailing-name');
160 }
161 // We can't fetch mailing headers from webtest so we'll only try if the format is raw
162 if ($this->_webtest && $type == 'raw') {
6a488035 163 // This should select the first "Report" link in the table, which is sorted by Completion Date descending, so in theory is the most recent email. Not sure of a more robust way at the moment.
b3d40287 164 $this->_ut->clickLink('xpath=//tr[contains(@id, "crm-mailing_")]//a[text()="Report"]');
6a488035
TO
165
166 // Also not sure how robust this is, but there isn't a good
167 // identifier for this link either.
168 $this->_ut->waitForElementPresent('xpath=//a[contains(text(), "View complete message")]');
a5d61f09 169 $this->_ut->clickAjaxLink('xpath=//a[contains(text(), "View complete message")]');
14d3f751 170 $msg = $this->_ut->getText('css=.ui-dialog-content.crm-ajax-container');
6a488035
TO
171 }
172 else {
173 $dao = CRM_Core_DAO::executeQuery('SELECT headers, body FROM civicrm_mailing_spool ORDER BY id DESC LIMIT 1');
174 if ($dao->fetch()) {
175 $msg = $dao->headers . "\n\n" . $dao->body;
176 }
177 $dao->free();
178 }
179
180 switch ($type) {
181 case 'raw':
182 // nothing to do
183 break;
6c6e6187 184
6a488035
TO
185 case 'ezc':
186 $msg = $this->convertToEzc($msg);
187 break;
188 }
189 return $msg;
190 }
191
192 /**
e16033b4
TO
193 * @param string $type
194 * 'raw'|'ezc'.
cbdcc634
EM
195 *
196 * @throws Exception
6a488035
TO
197 * @return array(ezcMail)|array(string)
198 */
00be9182 199 public function getAllMessages($type = 'raw') {
6a488035
TO
200 $msgs = array();
201
202 if ($this->_webtest) {
203 throw new Exception("Not implementated: getAllMessages for WebTest");
204 }
205 else {
206 $dao = CRM_Core_DAO::executeQuery('SELECT headers, body FROM civicrm_mailing_spool ORDER BY id');
207 while ($dao->fetch()) {
208 $msgs[] = $dao->headers . "\n\n" . $dao->body;
209 }
210 $dao->free();
211 }
212
213 switch ($type) {
214 case 'raw':
215 // nothing to do
216 break;
6c6e6187 217
6a488035
TO
218 case 'ezc':
219 foreach ($msgs as $i => $msg) {
220 $msgs[$i] = $this->convertToEzc($msg);
221 }
222 break;
223 }
224
225 return $msgs;
226 }
227
4cbe18b8
EM
228 /**
229 * @return int
230 */
00be9182 231 public function getSelectedOutboundOption() {
6a488035
TO
232 $selectedOption = CRM_Mailing_Config::OUTBOUND_OPTION_MAIL;
233 // Is there a better way to do this? How do you get the currently selected value of a radio button in selenium?
234 for ($i = 0; $i <= 5; $i++) {
235 if ($i != CRM_Mailing_Config::OUTBOUND_OPTION_MOCK) {
236 if ($this->_ut->getValue('xpath=//input[@name="outBound_option" and @value="' . $i . '"]') == "on") {
237 $selectedOption = $i;
238 break;
239 }
240 }
241 }
242 return $selectedOption;
243 }
244
245 /*
246 * Utility functions (previously part of CiviUnitTestCase)
247 * Included for backward compatibility with existing tests.
248 */
249
250 /**
251 * Check contents of mail log
77b97be7 252 *
e16033b4
TO
253 * @param array $strings
254 * Strings that should be included.
255 * @param array $absentStrings
256 * Strings that should not be included.
77b97be7 257 * @param string $prefix
6a488035 258 *
77b97be7 259 * @return \ezcMail|string
6a488035 260 */
00be9182 261 public function checkMailLog($strings, $absentStrings = array(), $prefix = '') {
6a488035
TO
262 $mail = $this->getMostRecentEmail('raw');
263 foreach ($strings as $string) {
264 $this->_ut->assertContains($string, $mail, "$string . not found in $mail $prefix");
265 }
266 foreach ($absentStrings as $string) {
92915c55 267 $this->_ut->assertEmpty(strstr($mail, $string), "$string incorrectly found in $mail $prefix");;
6a488035
TO
268 }
269 return $mail;
270 }
271
272 /**
273 * Check that mail log is empty
274 */
00be9182 275 public function assertMailLogEmpty($prefix = '') {
6a488035
TO
276 $mail = $this->getMostRecentEmail('raw');
277 $this->_ut->assertEmpty($mail, 'mail sent when it should not have been ' . $prefix);
278 }
279
280 /**
281 * Assert that $expectedRecipients (and no else) have received emails
282 *
e16033b4
TO
283 * @param array $expectedRecipients
284 * Array($msgPos => array($recipPos => $emailAddr)).
6a488035 285 */
00be9182 286 public function assertRecipients($expectedRecipients) {
6a488035
TO
287 $recipients = array();
288 foreach ($this->getAllMessages('ezc') as $message) {
289 $recipients[] = CRM_Utils_Array::collect('email', $message->to);
290 }
291 sort($recipients);
292 sort($expectedRecipients);
293 $this->_ut->assertEquals(
294 $expectedRecipients,
295 $recipients,
296 "Incorrect recipients: " . print_r(array('expected' => $expectedRecipients, 'actual' => $recipients), TRUE)
297 );
298 }
299
300 /**
301 * Remove any sent messages from the log
302 */
00be9182 303 public function clearMessages() {
6a488035
TO
304 if ($this->_webtest) {
305 throw new Exception("Not implementated: clearMessages for WebTest");
306 }
307 else {
308 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_mailing_spool ORDER BY id DESC LIMIT 1');
309 }
310 }
311
312 /**
e16033b4
TO
313 * @param string $msg
314 * Email header and body.
6a488035
TO
315 * @return ezcMail
316 */
317 private function convertToEzc($msg) {
14d3f751 318 $set = new ezcMailVariableSet($msg);
6a488035
TO
319 $parser = new ezcMailParser();
320 $mail = $parser->parseMail($set);
321 $this->_ut->assertNotEmpty($mail, 'Cannot parse mail');
322 return $mail[0];
323 }
324}