Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
39de6fd5 | 4 | | CiviCRM version 4.6 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
e7112fa7 | 6 | | Copyright CiviCRM LLC (c) 2004-2015 | |
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 | +--------------------------------------------------------------------+ | |
d25dd0ee | 25 | */ |
6a488035 TO |
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 | ||
43 | require_once 'ezc/Base/src/ezc_bootstrap.php'; | |
44 | require_once 'ezc/autoload/mail_autoload.php'; | |
45 | ||
4cbe18b8 EM |
46 | /** |
47 | * Class CiviMailUtils | |
48 | */ | |
6a488035 TO |
49 | class 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 | /** | |
eceb18cc | 62 | * Constructor. |
6a488035 | 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 | /** | |
eceb18cc | 82 | * Start writing emails to db instead of current option. |
6a488035 | 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 | /** | |
eceb18cc | 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 | /** | |
eceb18cc | 273 | * Check that mail log is empty. |
1e1fdcf6 | 274 | * @param string $prefix |
6a488035 | 275 | */ |
00be9182 | 276 | public function assertMailLogEmpty($prefix = '') { |
6a488035 TO |
277 | $mail = $this->getMostRecentEmail('raw'); |
278 | $this->_ut->assertEmpty($mail, 'mail sent when it should not have been ' . $prefix); | |
279 | } | |
280 | ||
281 | /** | |
282 | * Assert that $expectedRecipients (and no else) have received emails | |
283 | * | |
e16033b4 TO |
284 | * @param array $expectedRecipients |
285 | * Array($msgPos => array($recipPos => $emailAddr)). | |
6a488035 | 286 | */ |
00be9182 | 287 | public function assertRecipients($expectedRecipients) { |
6a488035 TO |
288 | $recipients = array(); |
289 | foreach ($this->getAllMessages('ezc') as $message) { | |
290 | $recipients[] = CRM_Utils_Array::collect('email', $message->to); | |
291 | } | |
11f535e4 TO |
292 | $cmp = function($a, $b) { |
293 | if ($a[0] == $b[0]) { | |
294 | return 0; | |
295 | } | |
296 | return ($a[0] < $b[0]) ? 1 : -1; | |
297 | }; | |
298 | usort($recipients, $cmp); | |
299 | usort($expectedRecipients, $cmp); | |
6a488035 TO |
300 | $this->_ut->assertEquals( |
301 | $expectedRecipients, | |
302 | $recipients, | |
303 | "Incorrect recipients: " . print_r(array('expected' => $expectedRecipients, 'actual' => $recipients), TRUE) | |
304 | ); | |
305 | } | |
306 | ||
307 | /** | |
eceb18cc | 308 | * Remove any sent messages from the log. |
6a488035 | 309 | */ |
00be9182 | 310 | public function clearMessages() { |
6a488035 TO |
311 | if ($this->_webtest) { |
312 | throw new Exception("Not implementated: clearMessages for WebTest"); | |
313 | } | |
314 | else { | |
315 | CRM_Core_DAO::executeQuery('DELETE FROM civicrm_mailing_spool ORDER BY id DESC LIMIT 1'); | |
316 | } | |
317 | } | |
318 | ||
319 | /** | |
e16033b4 TO |
320 | * @param string $msg |
321 | * Email header and body. | |
6a488035 TO |
322 | * @return ezcMail |
323 | */ | |
324 | private function convertToEzc($msg) { | |
14d3f751 | 325 | $set = new ezcMailVariableSet($msg); |
6a488035 TO |
326 | $parser = new ezcMailParser(); |
327 | $mail = $parser->parseMail($set); | |
328 | $this->_ut->assertNotEmpty($mail, 'Cannot parse mail'); | |
329 | return $mail[0]; | |
330 | } | |
96025800 | 331 | |
6a488035 | 332 | } |