Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
81621fee | 4 | | CiviCRM version 4.7 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
8c9251b3 | 6 | | Copyright CiviCRM LLC (c) 2004-2018 | |
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 and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
d25dd0ee | 26 | */ |
6a488035 | 27 | |
aa2733c0 | 28 | define('CIVICRM_WEBTEST', 1); |
6a488035 | 29 | |
6a488035 TO |
30 | /** |
31 | * Base class for CiviCRM Selenium tests | |
32 | * | |
33 | * Common functions for unit tests | |
34 | * @package CiviCRM | |
35 | */ | |
36 | class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase { | |
37 | ||
42daf119 CW |
38 | // Current logged-in user |
39 | protected $loggedInAs = NULL; | |
6a488035 | 40 | |
d3f2fd13 TO |
41 | private $settingCache; |
42 | ||
6a488035 | 43 | /** |
eceb18cc | 44 | * Constructor. |
6a488035 TO |
45 | * |
46 | * Because we are overriding the parent class constructor, we | |
47 | * need to show the same arguments as exist in the constructor of | |
48 | * PHPUnit_Framework_TestCase, since | |
49 | * PHPUnit_Framework_TestSuite::createTest() creates a | |
50 | * ReflectionClass of the Test class and checks the constructor | |
51 | * of that class to decide how to set up the test. | |
52 | * | |
e16033b4 TO |
53 | * @param string $name |
54 | * @param array $data | |
55 | * @param string $dataName | |
2a6da8d7 | 56 | * @param array $browser |
6a488035 | 57 | */ |
00be9182 | 58 | public function __construct($name = NULL, array$data = array(), $dataName = '', array$browser = array()) { |
6a488035 | 59 | parent::__construct($name, $data, $dataName, $browser); |
42daf119 | 60 | $this->loggedInAs = NULL; |
6a488035 | 61 | |
6a488035 | 62 | $this->settings = new CiviSeleniumSettings(); |
b5c0ad9a TO |
63 | if (property_exists($this->settings, 'serverStartupTimeOut') && $this->settings->serverStartupTimeOut) { |
64 | global $CiviSeleniumTestCase_polled; | |
65 | if (!$CiviSeleniumTestCase_polled) { | |
66 | $CiviSeleniumTestCase_polled = TRUE; | |
67 | CRM_Utils_Network::waitForServiceStartup( | |
68 | $this->drivers[0]->getHost(), | |
69 | $this->drivers[0]->getPort(), | |
70 | $this->settings->serverStartupTimeOut | |
71 | ); | |
72 | } | |
73 | } | |
6a488035 TO |
74 | |
75 | // autoload | |
76 | require_once 'CRM/Core/ClassLoader.php'; | |
77 | CRM_Core_ClassLoader::singleton()->register(); | |
78 | ||
79 | // also initialize a connection to the db | |
42daf119 | 80 | // FIXME: not necessary for most tests, consider moving into functions that need this |
6a488035 TO |
81 | $config = CRM_Core_Config::singleton(); |
82 | } | |
83 | ||
84 | protected function setUp() { | |
85 | $this->setBrowser($this->settings->browser); | |
86 | // Make sure that below strings have path separator at the end | |
87 | $this->setBrowserUrl($this->settings->sandboxURL); | |
88 | $this->sboxPath = $this->settings->sandboxPATH; | |
b5c0ad9a TO |
89 | if (property_exists($this->settings, 'rcHost') && $this->settings->rcHost) { |
90 | $this->setHost($this->settings->rcHost); | |
91 | } | |
92 | if (property_exists($this->settings, 'rcPort') && $this->settings->rcPort) { | |
93 | $this->setPort($this->settings->rcPort); | |
94 | } | |
d3f2fd13 | 95 | $this->settingCache = array(); |
6a488035 TO |
96 | } |
97 | ||
7fe37828 EM |
98 | /** |
99 | * @return string | |
100 | */ | |
bf446982 TO |
101 | protected function prepareTestSession() { |
102 | $result = parent::prepareTestSession(); | |
103 | ||
104 | // Set any cookies required by local installation | |
105 | // Note: considered doing this in setUp(), but the Selenium session wasn't yet initialized. | |
106 | if (property_exists($this->settings, 'cookies')) { | |
107 | // We don't really care about this page, but it seems we need | |
108 | // to open a page before setting a cookie. | |
109 | $this->open($this->sboxPath); | |
110 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
111 | $this->setCookies($this->settings->cookies); | |
112 | } | |
113 | return $result; | |
114 | } | |
115 | ||
116 | /** | |
e16033b4 | 117 | * @param array $cookies |
16b10e64 CW |
118 | * Each item is an Array with keys: |
119 | * - name: string | |
120 | * - value: string; note that RFC's don't define particular encoding scheme, so | |
bf446982 TO |
121 | * you must pick one yourself and pre-encode; does not allow values with |
122 | * commas, semicolons, or whitespace | |
16b10e64 CW |
123 | * - path: string; default: '/' |
124 | * - max_age: int; default: 1 week (7*24*60*60) | |
bf446982 TO |
125 | */ |
126 | protected function setCookies($cookies) { | |
127 | foreach ($cookies as $cookie) { | |
128 | if (!isset($cookie['path'])) { | |
129 | $cookie['path'] = '/'; | |
130 | } | |
131 | if (!isset($cookie['max_age'])) { | |
6c6e6187 | 132 | $cookie['max_age'] = 7 * 24 * 60 * 60; |
bf446982 TO |
133 | } |
134 | $this->deleteCookie($cookie['name'], $cookie['path']); | |
135 | $optionExprs = array(); | |
136 | foreach ($cookie as $key => $value) { | |
137 | if ($key != 'name' && $key != 'value') { | |
138 | $optionExprs[] = "$key=$value"; | |
139 | } | |
140 | } | |
141 | $this->createCookie("{$cookie['name']}={$cookie['value']}", implode(', ', $optionExprs)); | |
142 | } | |
143 | } | |
144 | ||
6a488035 | 145 | protected function tearDown() { |
6a488035 TO |
146 | } |
147 | ||
148 | /** | |
eceb18cc | 149 | * Authenticate as drupal user. |
5896d037 TO |
150 | * @param $user : (str) the key 'user' or 'admin', or a literal username |
151 | * @param $pass : (str) if $user is a literal username and not 'user' or 'admin', supply the password | |
6a488035 | 152 | */ |
00be9182 | 153 | public function webtestLogin($user = 'user', $pass = NULL) { |
42daf119 CW |
154 | // If already logged in as correct user, do nothing |
155 | if ($this->loggedInAs === $user) { | |
156 | return; | |
157 | } | |
158 | // If we are logged in as a different user, log out first | |
159 | if ($this->loggedInAs) { | |
160 | $this->webtestLogout(); | |
161 | } | |
6a488035 | 162 | $this->open("{$this->sboxPath}user"); |
42daf119 CW |
163 | // Lookup username & password if not supplied |
164 | $username = $user; | |
165 | if ($pass === NULL) { | |
166 | $pass = $user == 'admin' ? $this->settings->adminPassword : $this->settings->password; | |
167 | $username = $user == 'admin' ? $this->settings->adminUsername : $this->settings->username; | |
168 | } | |
6a488035 TO |
169 | // Make sure login form is available |
170 | $this->waitForElementPresent('edit-submit'); | |
171 | $this->type('edit-name', $username); | |
42daf119 | 172 | $this->type('edit-pass', $pass); |
6a488035 TO |
173 | $this->click('edit-submit'); |
174 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
42daf119 CW |
175 | $this->loggedInAs = $user; |
176 | } | |
177 | ||
00be9182 | 178 | public function webtestLogout() { |
42daf119 CW |
179 | if ($this->loggedInAs) { |
180 | $this->open($this->sboxPath . "user/logout"); | |
181 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
182 | } | |
183 | $this->loggedInAs = NULL; | |
6a488035 TO |
184 | } |
185 | ||
186 | /** | |
187 | * Open an internal path beginning with 'civicrm/' | |
188 | * | |
5a4f6742 CW |
189 | * @param string $url |
190 | * omit the 'civicrm/' it will be added for you. | |
191 | * @param string|array $args | |
192 | * optional url arguments. | |
e16033b4 TO |
193 | * @param $waitFor |
194 | * Page element to wait for - using this is recommended to ensure the document is fully loaded. | |
6a488035 TO |
195 | * |
196 | * Although it doesn't seem to do much now, using this function is recommended for | |
197 | * opening all civi pages, and using the $args param is also strongly encouraged | |
198 | * This will make it much easier to run webtests in other CMSs in the future | |
199 | */ | |
00be9182 | 200 | public function openCiviPage($url, $args = NULL, $waitFor = 'civicrm-footer') { |
6a488035 TO |
201 | // Construct full url with args |
202 | // This could be extended in future to work with other CMS style urls | |
203 | if ($args) { | |
204 | if (is_array($args)) { | |
205 | $sep = '?'; | |
206 | foreach ($args as $key => $val) { | |
207 | $url .= $sep . $key . '=' . $val; | |
208 | $sep = '&'; | |
209 | } | |
210 | } | |
211 | else { | |
212 | $url .= "?$args"; | |
213 | } | |
214 | } | |
215 | $this->open("{$this->sboxPath}civicrm/$url"); | |
42daf119 | 216 | $this->waitForPageToLoad($this->getTimeoutMsec()); |
b50973e8 | 217 | $this->checkForErrorsOnPage(); |
6a488035 TO |
218 | if ($waitFor) { |
219 | $this->waitForElementPresent($waitFor); | |
220 | } | |
221 | } | |
222 | ||
b45c587e | 223 | /** |
eceb18cc | 224 | * Click on a link or button. |
b45c587e CW |
225 | * Wait for the page to load |
226 | * Wait for an element to be present | |
1e1fdcf6 EM |
227 | * @param $element |
228 | * @param string $waitFor | |
229 | * @param bool $waitForPageLoad | |
b45c587e | 230 | */ |
00be9182 | 231 | public function clickLink($element, $waitFor = 'civicrm-footer', $waitForPageLoad = TRUE) { |
b45c587e | 232 | $this->click($element); |
28154ee7 PJ |
233 | // conditional wait for page load e.g for ajax form save |
234 | if ($waitForPageLoad) { | |
235 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
b50973e8 | 236 | $this->checkForErrorsOnPage(); |
28154ee7 | 237 | } |
b45c587e CW |
238 | if ($waitFor) { |
239 | $this->waitForElementPresent($waitFor); | |
240 | } | |
241 | } | |
405bc6ee CW |
242 | |
243 | /** | |
eceb18cc | 244 | * Click a link or button and wait for an ajax dialog to load. |
50d95825 CW |
245 | * @param string $element |
246 | * @param string $waitFor | |
247 | */ | |
6c6e6187 | 248 | public function clickPopupLink($element, $waitFor = NULL) { |
a5d61f09 CW |
249 | $this->clickAjaxLink($element, 'css=.ui-dialog'); |
250 | if ($waitFor) { | |
251 | $this->waitForElementPresent($waitFor); | |
252 | } | |
253 | } | |
254 | ||
255 | /** | |
eceb18cc | 256 | * Click a link or button and wait for ajax content to load or refresh. |
a5d61f09 CW |
257 | * @param string $element |
258 | * @param string $waitFor | |
259 | */ | |
6c6e6187 | 260 | public function clickAjaxLink($element, $waitFor = NULL) { |
50d95825 | 261 | $this->click($element); |
50d95825 CW |
262 | if ($waitFor) { |
263 | $this->waitForElementPresent($waitFor); | |
264 | } | |
57d32317 | 265 | $this->waitForAjaxContent(); |
50d95825 CW |
266 | } |
267 | ||
268 | /** | |
269 | * Force a link to open full-page, even if it would normally open in a popup | |
e739afc3 | 270 | * @note: works with links only, not buttons |
50d95825 | 271 | * @param string $element |
405bc6ee CW |
272 | * @param string $waitFor |
273 | */ | |
00be9182 | 274 | public function clickLinkSuppressPopup($element, $waitFor = 'civicrm-footer') { |
405bc6ee CW |
275 | $link = $this->getAttribute($element . '@href'); |
276 | $this->open($link); | |
277 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
278 | if ($waitFor) { | |
279 | $this->waitForElementPresent($waitFor); | |
280 | } | |
281 | } | |
b45c587e | 282 | |
50d95825 | 283 | /** |
eceb18cc | 284 | * Wait for all ajax snippets to finish loading. |
50d95825 | 285 | */ |
00be9182 | 286 | public function waitForAjaxContent() { |
50d95825 | 287 | $this->waitForElementNotPresent('css=.blockOverlay'); |
e739afc3 CW |
288 | // Some ajax calls happen in pairs (e.g. submit a popup form then refresh the underlying content) |
289 | // So we'll wait a sec and recheck to see if any more stuff is loading | |
290 | sleep(1); | |
291 | if ($this->isElementPresent('css=.blockOverlay')) { | |
292 | $this->waitForAjaxContent(); | |
293 | } | |
50d95825 CW |
294 | } |
295 | ||
6a488035 | 296 | /** |
eceb18cc | 297 | * Call the API on the local server. |
6a488035 | 298 | * (kind of defeats the point of a webtest - see CRM-11889) |
1e1fdcf6 EM |
299 | * @param $entity |
300 | * @param $action | |
301 | * @param $params | |
302 | * @return array|int | |
6a488035 | 303 | */ |
00be9182 | 304 | public function webtest_civicrm_api($entity, $action, $params) { |
6a488035 TO |
305 | if (!isset($params['version'])) { |
306 | $params['version'] = 3; | |
307 | } | |
308 | ||
309 | $result = civicrm_api($entity, $action, $params); | |
ef9cbdb7 | 310 | $this->assertAPISuccess($result); |
6a488035 TO |
311 | return $result; |
312 | } | |
313 | ||
314 | /** | |
ef9cbdb7 TO |
315 | * Call the API on the remote server using the AJAX endpoint. |
316 | * | |
6a488035 | 317 | * @see CRM-11889 |
1e1fdcf6 EM |
318 | * @param $entity |
319 | * @param $action | |
320 | * @param array $params | |
321 | * @return mixed | |
6a488035 | 322 | */ |
00be9182 | 323 | public function rest_civicrm_api($entity, $action, $params = array()) { |
6a488035 TO |
324 | $params += array( |
325 | 'version' => 3, | |
326 | ); | |
ef9cbdb7 TO |
327 | static $reqId = 0; |
328 | $reqId++; | |
329 | ||
330 | $jsCmd = ' | |
331 | setTimeout(function(){ | |
332 | CRM.api3("@entity", "@action", @params).then(function(a){ | |
333 | cj("<textarea>").css("display", "none").prop("id","crmajax@reqId").val(JSON.stringify(a)).appendTo("body"); | |
334 | }); | |
335 | }, 500); | |
336 | '; | |
337 | $jsArgs = array( | |
338 | '@entity' => $entity, | |
339 | '@action' => $action, | |
340 | '@params' => json_encode($params), | |
341 | '@reqId' => $reqId, | |
6a488035 | 342 | ); |
ef9cbdb7 TO |
343 | $js = strtr($jsCmd, $jsArgs); |
344 | $this->runScript($js); | |
345 | $this->waitForElementPresent("crmajax{$reqId}"); | |
346 | $result = json_decode($this->getValue("crmajax{$reqId}"), TRUE); | |
347 | $this->runScript("cj('#crmajax{$reqId}').remove();"); | |
348 | return $result; | |
6a488035 TO |
349 | } |
350 | ||
4cbe18b8 | 351 | /** |
100fef9d | 352 | * @param string $option_group_name |
4cbe18b8 EM |
353 | * |
354 | * @return array|int | |
355 | */ | |
00be9182 | 356 | public function webtestGetFirstValueForOptionGroup($option_group_name) { |
6a488035 TO |
357 | $result = $this->webtest_civicrm_api("OptionValue", "getvalue", array( |
358 | 'option_group_name' => $option_group_name, | |
359 | 'option.limit' => 1, | |
21dfd5f5 | 360 | 'return' => 'value', |
6a488035 TO |
361 | )); |
362 | return $result; | |
363 | } | |
364 | ||
4cbe18b8 EM |
365 | /** |
366 | * @return mixed | |
367 | */ | |
00be9182 | 368 | public function webtestGetValidCountryID() { |
6a488035 TO |
369 | static $_country_id; |
370 | if (is_null($_country_id)) { | |
a1fddd2c | 371 | $_country_id = Civi::settings()->get('defaultContactCountry'); |
6a488035 TO |
372 | } |
373 | return $_country_id; | |
374 | } | |
375 | ||
4cbe18b8 EM |
376 | /** |
377 | * @param $entity | |
378 | * | |
379 | * @return mixed|null | |
380 | */ | |
00be9182 | 381 | public function webtestGetValidEntityID($entity) { |
6a488035 TO |
382 | // michaelmcandrew: would like to use getvalue but there is a bug |
383 | // for e.g. group where option.limit not working at the moment CRM-9110 | |
384 | $result = $this->webtest_civicrm_api($entity, "get", array('option.limit' => 1, 'return' => 'id')); | |
385 | if (!empty($result['values'])) { | |
386 | return current(array_keys($result['values'])); | |
387 | } | |
388 | return NULL; | |
389 | } | |
390 | ||
d3f2fd13 TO |
391 | /** |
392 | * @param string $field | |
393 | * @return mixed | |
394 | */ | |
395 | public function webtestGetSetting($field) { | |
396 | if (!isset($this->settingCache[$field])) { | |
397 | $result = $this->webtest_civicrm_api("Setting", "getsingle", array( | |
398 | 'return' => $field, | |
399 | )); | |
400 | $this->settingCache[$field] = $result[$field]; | |
401 | } | |
402 | return $this->settingCache[$field]; | |
403 | } | |
404 | ||
fc8cb638 | 405 | /** |
406 | * override this since the built in function doesn't work with the new phpunit. | |
407 | * @param string $element | |
408 | * @param string $text | |
409 | */ | |
410 | public function waitForText($element, $text) { | |
411 | $this->waitForTextPresent($text); | |
412 | $this->assertElementContainsText($element, $text); | |
413 | } | |
414 | ||
1fbd57f8 | 415 | /** |
eceb18cc | 416 | * Ensures the required CiviCRM components are enabled. |
1e1fdcf6 | 417 | * @param $components |
1fbd57f8 | 418 | */ |
00be9182 | 419 | public function enableComponents($components) { |
1fbd57f8 CW |
420 | $this->openCiviPage("admin/setting/component", "reset=1", "_qf_Component_next-bottom"); |
421 | $enabledComponents = $this->getSelectOptions("enableComponents-t"); | |
422 | $added = FALSE; | |
423 | foreach ((array) $components as $comp) { | |
424 | if (!in_array($comp, $enabledComponents)) { | |
0bd37c06 | 425 | $this->addSelection("enableComponents-f", "label=$comp"); |
1fbd57f8 CW |
426 | $this->click("//option[@value='$comp']"); |
427 | $this->click("add"); | |
428 | $added = TRUE; | |
429 | } | |
430 | } | |
431 | if ($added) { | |
59843a57 CW |
432 | $this->clickLink("_qf_Component_next-bottom"); |
433 | $this->checkCRMAlert("Saved"); | |
1fbd57f8 CW |
434 | } |
435 | } | |
436 | ||
b25b6f70 WA |
437 | /** |
438 | * Ensures the required currencies are enabled. | |
439 | * @param $currencies | |
440 | */ | |
441 | public function enableCurrency($currencies) { | |
442 | $this->openCiviPage("admin/setting/localization", "reset=1", "_qf_Localization_next-bottom"); | |
443 | $enabledCurrency = $this->getSelectOptions("currencyLimit-t"); | |
444 | foreach ($enabledCurrency as $k => $val) { | |
445 | $enabledCurrency[$k] = substr($val, 0, 3); | |
446 | } | |
447 | $added = FALSE; | |
448 | foreach ((array) $currencies as $curr) { | |
449 | if (!in_array($curr, $enabledCurrency)) { | |
450 | $this->addSelection("currencyLimit-f", "value=$curr"); | |
451 | $this->click("//option[@value='$curr']"); | |
452 | $this->click("add"); | |
453 | $added = TRUE; | |
454 | } | |
455 | } | |
456 | if ($added) { | |
457 | $this->clickLink("_qf_Localization_next-bottom"); | |
458 | } | |
459 | } | |
460 | ||
6a488035 | 461 | /** |
eceb18cc | 462 | * Add a contact with the given first and last names and either a given email. |
6a488035 TO |
463 | * (when specified), a random email (when true) or no email (when unspecified or null). |
464 | * | |
e16033b4 TO |
465 | * @param string $fname |
466 | * Contact’s first name. | |
467 | * @param string $lname | |
468 | * Contact’s last name. | |
469 | * @param mixed $email | |
470 | * Contact’s email (when string) or random email (when true) or no email (when null). | |
72b3a70c | 471 | * @param string $contactSubtype |
2a6da8d7 | 472 | * |
72b3a70c CW |
473 | * @return string|null |
474 | * either a string with the (either generated or provided) email or null (if no email) | |
6a488035 | 475 | */ |
00be9182 | 476 | public function webtestAddContact($fname = 'Anthony', $lname = 'Anderson', $email = NULL, $contactSubtype = NULL) { |
5c88df60 | 477 | $args = 'reset=1&ct=Individual'; |
6a488035 | 478 | if ($contactSubtype) { |
5c88df60 | 479 | $args .= "&cst={$contactSubtype}"; |
6a488035 | 480 | } |
5c88df60 | 481 | $this->openCiviPage('contact/add', $args, '_qf_Contact_upload_view-bottom'); |
6a488035 TO |
482 | $this->type('first_name', $fname); |
483 | $this->type('last_name', $lname); | |
484 | if ($email === TRUE) { | |
485 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
486 | } | |
487 | if ($email) { | |
488 | $this->type('email_1_email', $email); | |
489 | } | |
5c88df60 | 490 | $this->clickLink('_qf_Contact_upload_view-bottom'); |
6a488035 TO |
491 | return $email; |
492 | } | |
493 | ||
4cbe18b8 EM |
494 | /** |
495 | * @param string $householdName | |
496 | * @param null $email | |
497 | * | |
498 | * @return null|string | |
499 | */ | |
00be9182 | 500 | public function webtestAddHousehold($householdName = "Smith's Home", $email = NULL) { |
b45c587e | 501 | $this->openCiviPage("contact/add", "reset=1&ct=Household"); |
6a488035 TO |
502 | $this->click('household_name'); |
503 | $this->type('household_name', $householdName); | |
504 | ||
505 | if ($email === TRUE) { | |
506 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
507 | } | |
508 | if ($email) { | |
509 | $this->type('email_1_email', $email); | |
510 | } | |
511 | ||
5c88df60 | 512 | $this->clickLink('_qf_Contact_upload_view'); |
6a488035 TO |
513 | return $email; |
514 | } | |
515 | ||
4cbe18b8 EM |
516 | /** |
517 | * @param string $organizationName | |
518 | * @param null $email | |
519 | * @param null $contactSubtype | |
520 | * | |
521 | * @return null|string | |
522 | */ | |
00be9182 | 523 | public function webtestAddOrganization($organizationName = "Organization XYZ", $email = NULL, $contactSubtype = NULL) { |
5c88df60 | 524 | $args = 'reset=1&ct=Organization'; |
2ddaadeb | 525 | if ($contactSubtype) { |
5c88df60 | 526 | $args .= "&cst={$contactSubtype}"; |
2ddaadeb | 527 | } |
5c88df60 | 528 | $this->openCiviPage('contact/add', $args, '_qf_Contact_upload_view-bottom'); |
6a488035 TO |
529 | $this->click('organization_name'); |
530 | $this->type('organization_name', $organizationName); | |
531 | ||
532 | if ($email === TRUE) { | |
533 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
534 | } | |
535 | if ($email) { | |
536 | $this->type('email_1_email', $email); | |
537 | } | |
5c88df60 | 538 | $this->clickLink('_qf_Contact_upload_view'); |
6a488035 TO |
539 | return $email; |
540 | } | |
541 | ||
542 | /** | |
1e1fdcf6 EM |
543 | * @param $sortName |
544 | * @param string $fieldName | |
6a488035 | 545 | */ |
00be9182 | 546 | public function webtestFillAutocomplete($sortName, $fieldName = 'contact_id') { |
6c6e6187 | 547 | $this->select2($fieldName, $sortName); |
5320adf4 | 548 | //$this->assertContains($sortName, $this->getValue($fieldName), "autocomplete expected $sortName but didn’t find it in " . $this->getValue($fieldName)); |
6a488035 TO |
549 | } |
550 | ||
551 | /** | |
1e1fdcf6 | 552 | * @param $sortName |
6a488035 | 553 | */ |
00be9182 | 554 | public function webtestOrganisationAutocomplete($sortName) { |
33cf86bd | 555 | $this->clickAt("//*[@id='contact_id']/../div/a"); |
5320adf4 WA |
556 | $this->waitForElementPresent("//*[@id='select2-drop']/div/input"); |
557 | $this->keyDown("//*[@id='select2-drop']/div/input", " "); | |
558 | $this->type("//*[@id='select2-drop']/div/input", $sortName); | |
559 | $this->typeKeys("//*[@id='select2-drop']/div/input", $sortName); | |
560 | $this->waitForElementPresent("//*[@class='select2-result-label']"); | |
561 | $this->clickAt("//*[@class='select2-results']/li[1]"); | |
6a488035 TO |
562 | //$this->assertContains($sortName, $this->getValue('contact_1'), "autocomplete expected $sortName but didn’t find it in " . $this->getValue('contact_1')); |
563 | } | |
564 | ||
4cbe18b8 | 565 | /** |
c490a46a CW |
566 | * 1. By default, when no strtotime arg is specified, sets date to "now + 1 month" |
567 | * 2. Does not set time. For setting both date and time use webtestFillDateTime() method. | |
568 | * 3. Examples of $strToTime arguments - | |
569 | * webtestFillDate('start_date',"now") | |
570 | * webtestFillDate('start_date',"10 September 2000") | |
571 | * webtestFillDate('start_date',"+1 day") | |
572 | * webtestFillDate('start_date',"+1 week") | |
573 | * webtestFillDate('start_date',"+1 week 2 days 4 hours 2 seconds") | |
574 | * webtestFillDate('start_date',"next Thursday") | |
575 | * webtestFillDate('start_date',"last Monday") | |
4cbe18b8 EM |
576 | * @param $dateElement |
577 | * @param null $strToTimeArgs | |
578 | */ | |
cd71816e | 579 | public function webtestFillDate($dateElement, $strToTimeArgs = NULL, $multiselect = FALSE) { |
6a488035 TO |
580 | $timeStamp = strtotime($strToTimeArgs ? $strToTimeArgs : '+1 month'); |
581 | ||
582 | $year = date('Y', $timeStamp); | |
583 | // -1 ensures month number is inline with calender widget's month | |
584 | $mon = date('n', $timeStamp) - 1; | |
585 | $day = date('j', $timeStamp); | |
586 | ||
cd71816e | 587 | if (!$multiselect) { |
22d1f513 | 588 | $this->click("xpath=//input[@id='{$dateElement}']/following-sibling::input"); |
cd71816e | 589 | } |
6a488035 TO |
590 | $this->waitForElementPresent("css=div#ui-datepicker-div.ui-datepicker div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-month"); |
591 | $this->select("css=div#ui-datepicker-div.ui-datepicker div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-month", "value=$mon"); | |
592 | $this->select("css=div#ui-datepicker-div div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-year", "value=$year"); | |
593 | $this->click("link=$day"); | |
594 | } | |
595 | ||
4cbe18b8 | 596 | /** |
c490a46a | 597 | * 1. set both date and time. |
4cbe18b8 EM |
598 | * @param $dateElement |
599 | * @param null $strToTimeArgs | |
600 | */ | |
00be9182 | 601 | public function webtestFillDateTime($dateElement, $strToTimeArgs = NULL) { |
6a488035 TO |
602 | $this->webtestFillDate($dateElement, $strToTimeArgs); |
603 | ||
604 | $timeStamp = strtotime($strToTimeArgs ? $strToTimeArgs : '+1 month'); | |
605 | $hour = date('h', $timeStamp); | |
606 | $min = date('i', $timeStamp); | |
607 | $meri = date('A', $timeStamp); | |
608 | ||
609 | $this->type("{$dateElement}_time", "{$hour}:{$min}{$meri}"); | |
610 | } | |
611 | ||
612 | /** | |
613 | * Verify that given label/value pairs are in *sibling* td cells somewhere on the page. | |
614 | * | |
e16033b4 TO |
615 | * @param array $expected |
616 | * Array of key/value pairs (like Status/Registered) to be checked. | |
617 | * @param string $xpathPrefix | |
618 | * Pass in an xpath locator to "get to" the desired table or tables. Will be prefixed to xpath. | |
6a488035 | 619 | * table path. Include leading forward slashes (e.g. "//div[@id='activity-content']"). |
e16033b4 TO |
620 | * @param string $tableId |
621 | * Pass in the id attribute of a table to be verified if you want to only check a specific table. | |
6a488035 TO |
622 | * on the web page. |
623 | */ | |
00be9182 | 624 | public function webtestVerifyTabularData($expected, $xpathPrefix = NULL, $tableId = NULL) { |
6a488035 TO |
625 | $tableLocator = ""; |
626 | if ($tableId) { | |
627 | $tableLocator = "[@id='$tableId']"; | |
628 | } | |
629 | foreach ($expected as $label => $value) { | |
24f591b0 | 630 | //assertContains() accepts param as string |
631 | $value = "$value"; | |
6a488035 | 632 | if ($xpathPrefix) { |
5ddf4885 | 633 | $this->waitForElementPresent("xpath=//table{$tableLocator}/tbody/tr/td{$xpathPrefix}[text()='{$label}']/../following-sibling::td"); |
b02d5792 | 634 | $this->assertElementContainsText("xpath=//table{$tableLocator}/tbody/tr/td{$xpathPrefix}[text()='{$label}']/../following-sibling::td", $value); |
6a488035 TO |
635 | } |
636 | else { | |
5ddf4885 | 637 | $this->waitForElementPresent("xpath=//table{$tableLocator}/tbody/tr/td[text()='{$label}']/following-sibling::td"); |
b02d5792 | 638 | $this->assertElementContainsText("xpath=//table{$tableLocator}/tbody/tr/td[text()='{$label}']/following-sibling::td", $value); |
6a488035 TO |
639 | } |
640 | } | |
641 | } | |
642 | ||
643 | /** | |
eceb18cc | 644 | * Types text into a ckEditor rich text field in a form. |
6a488035 | 645 | * |
e16033b4 TO |
646 | * @param string $fieldName |
647 | * Form field name (as assigned by PHP buildForm class). | |
648 | * @param string $text | |
649 | * Text to type into the field. | |
650 | * @param string $editor | |
651 | * Which text editor (valid values are 'CKEditor', 'TinyMCE'). | |
6a488035 | 652 | * |
1e1fdcf6 EM |
653 | * @param bool $compressed |
654 | * @throws \PHPUnit_Framework_AssertionFailedError | |
6a488035 | 655 | */ |
00be9182 | 656 | public function fillRichTextField($fieldName, $text = 'Typing this text into editor.', $editor = 'CKEditor', $compressed = FALSE) { |
6a488035 TO |
657 | // make sure cursor focuses on the field |
658 | $this->fireEvent($fieldName, 'focus'); | |
659 | if ($editor == 'CKEditor') { | |
02e08b2e | 660 | if ($compressed) { |
000a086f | 661 | $this->click("xpath=//textarea[@id='{$fieldName}']/../div[1]"); |
02e08b2e | 662 | } |
6a488035 TO |
663 | $this->waitForElementPresent("xpath=//div[@id='cke_{$fieldName}']//iframe"); |
664 | $this->runScript("CKEDITOR.instances['{$fieldName}'].setData('<p>{$text}</p>');"); | |
665 | } | |
666 | elseif ($editor == 'TinyMCE') { | |
f97d29d1 RN |
667 | $this->waitForElementPresent("xpath=//iframe[@id='{$fieldName}_ifr']"); |
668 | $this->runScript("tinyMCE.activeEditor.setContent('<p>{$text}</p>');"); | |
6a488035 TO |
669 | } |
670 | else { | |
671 | $this->fail("Unknown editor value: $editor, failing (in CiviSeleniumTestCase::fillRichTextField ..."); | |
672 | } | |
673 | $this->selectFrame('relative=top'); | |
674 | } | |
675 | ||
676 | /** | |
eceb18cc | 677 | * Types option label and name into a table of multiple choice options. |
6a488035 TO |
678 | * (for price set fields of type select, radio, or checkbox) |
679 | * TODO: extend for custom field multiple choice table input | |
680 | * | |
e16033b4 TO |
681 | * @param array $options |
682 | * Form field name (as assigned by PHP buildForm class). | |
683 | * @param array $validateStrings | |
684 | * Appends label and name strings to this array so they can be validated later. | |
6a488035 TO |
685 | * |
686 | * @return void | |
687 | */ | |
00be9182 | 688 | public function addMultipleChoiceOptions($options, &$validateStrings) { |
6a488035 TO |
689 | foreach ($options as $oIndex => $oValue) { |
690 | $validateStrings[] = $oValue['label']; | |
691 | $validateStrings[] = $oValue['amount']; | |
a7488080 | 692 | if (!empty($oValue['membership_type_id'])) { |
6a488035 TO |
693 | $this->select("membership_type_id_{$oIndex}", "value={$oValue['membership_type_id']}"); |
694 | } | |
a7488080 | 695 | if (!empty($oValue['financial_type_id'])) { |
6a488035 TO |
696 | $this->select("option_financial_type_id_{$oIndex}", "label={$oValue['financial_type_id']}"); |
697 | } | |
698 | $this->type("option_label_{$oIndex}", $oValue['label']); | |
699 | $this->type("option_amount_{$oIndex}", $oValue['amount']); | |
b02d5792 | 700 | $this->click('link=add another choice'); |
6a488035 TO |
701 | } |
702 | } | |
703 | ||
704 | /** | |
eceb18cc | 705 | * Use a contact EntityRef field to add a new contact. |
e16033b4 TO |
706 | * @param string $field |
707 | * Selector. | |
80f3b91d | 708 | * @param string $contactType |
a6c01b45 | 709 | * @return array |
16b10e64 | 710 | * Array of contact attributes (id, names, email) |
80f3b91d | 711 | */ |
00be9182 | 712 | public function createDialogContact($field = 'contact_id', $contactType = 'Individual') { |
80f3b91d CW |
713 | $selectId = 's2id_' . $this->getAttribute($field . '@id'); |
714 | $this->clickAt("xpath=//div[@id='$selectId']/a"); | |
715 | $this->clickAjaxLink("xpath=//li[@class='select2-no-results']//a[contains(text(), 'New $contactType')]", '_qf_Edit_next'); | |
716 | ||
717 | $name = substr(sha1(rand()), 0, rand(6, 8)); | |
718 | $params = array(); | |
719 | if ($contactType == 'Individual') { | |
720 | $params['first_name'] = "$name $contactType"; | |
721 | $params['last_name'] = substr(sha1(rand()), 0, rand(5, 9)); | |
722 | } | |
723 | else { | |
724 | $params[strtolower($contactType) . '_name'] = "$name $contactType"; | |
725 | } | |
5896d037 | 726 | foreach ($params as $param => $val) { |
80f3b91d CW |
727 | $this->type($param, $val); |
728 | } | |
729 | $this->type('email-Primary', $params['email'] = "{$name}@example.com"); | |
730 | $this->clickAjaxLink('_qf_Edit_next'); | |
731 | ||
6c6e6187 | 732 | $this->waitForText("xpath=//div[@id='$selectId']", "$name"); |
80f3b91d CW |
733 | |
734 | $params['sort_name'] = $contactType == 'Individual' ? $params['last_name'] . ', ' . $params['first_name'] : "$name $contactType"; | |
735 | $params['display_name'] = $contactType == 'Individual' ? $params['first_name'] . ' ' . $params['last_name'] : $params['sort_name']; | |
736 | $params['id'] = $this->getValue($field); | |
737 | return $params; | |
738 | } | |
739 | ||
740 | /** | |
741 | * @deprecated in favor of createDialogContact | |
1e1fdcf6 EM |
742 | * @param string $fname |
743 | * @param string $lname | |
744 | * @param string $email | |
745 | * @param int $type | |
746 | * @param string $selectId | |
747 | * @param int $row | |
748 | * @param string $prefix | |
6a488035 | 749 | */ |
3bdca100 | 750 | public function webtestNewDialogContact( |
5896d037 TO |
751 | $fname = 'Anthony', $lname = 'Anderson', $email = 'anthony@anderson.biz', |
752 | $type = 4, $selectId = 's2id_contact_id', $row = 1, $prefix = '') { | |
6a488035 TO |
753 | // 4 - Individual profile |
754 | // 5 - Organization profile | |
755 | // 6 - Household profile | |
0e32ba2d | 756 | $profile = array('4' => 'New Individual', '5' => 'New Organization', '6' => 'New Household'); |
201e298c | 757 | $this->clickAt("xpath=//div[@id='$selectId']/a"); |
a5d61f09 | 758 | $this->clickPopupLink("xpath=//li[@class='select2-no-results']//a[contains(text(),' $profile[$type]')]", '_qf_Edit_next'); |
6a488035 TO |
759 | |
760 | switch ($type) { | |
761 | case 4: | |
762 | $this->type('first_name', $fname); | |
763 | $this->type('last_name', $lname); | |
764 | break; | |
765 | ||
766 | case 5: | |
767 | $this->type('organization_name', $fname); | |
768 | break; | |
769 | ||
770 | case 6: | |
771 | $this->type('household_name', $fname); | |
772 | break; | |
773 | } | |
774 | ||
775 | $this->type('email-Primary', $email); | |
9c5c0056 | 776 | $this->clickAjaxLink('_qf_Edit_next'); |
6a488035 TO |
777 | |
778 | // Is new contact created? | |
779 | if ($lname) { | |
6c6e6187 | 780 | $this->waitForText("xpath=//div[@id='$selectId']", "$lname, $fname"); |
6a488035 TO |
781 | } |
782 | else { | |
6c6e6187 | 783 | $this->waitForText("xpath=//div[@id='$selectId']", "$fname"); |
6a488035 TO |
784 | } |
785 | } | |
786 | ||
787 | /** | |
eceb18cc | 788 | * Generic function to check that strings are present in the page. |
6a488035 TO |
789 | * |
790 | * @strings array array of strings or a single string | |
791 | * | |
2a6da8d7 | 792 | * @param $strings |
2b37475d | 793 | * @return void |
6a488035 | 794 | */ |
00be9182 | 795 | public function assertStringsPresent($strings) { |
6a488035 TO |
796 | foreach ((array) $strings as $string) { |
797 | $this->assertTrue($this->isTextPresent($string), "Could not find $string on page"); | |
798 | } | |
799 | } | |
800 | ||
801 | /** | |
802 | * Generic function to parse a URL string into it's elements.extract a variable value from a string (url) | |
803 | * | |
804 | * @url string url to parse or retrieve current url if null | |
805 | * | |
2a6da8d7 | 806 | * @param null $url |
a6c01b45 CW |
807 | * @return array |
808 | * returns an associative array containing any of the various components | |
6a488035 TO |
809 | * of the URL that are present. Querystring elements are returned in sub-array (elements.queryString) |
810 | * http://php.net/manual/en/function.parse-url.php | |
6a488035 | 811 | */ |
00be9182 | 812 | public function parseURL($url = NULL) { |
6a488035 TO |
813 | if (!$url) { |
814 | $url = $this->getLocation(); | |
815 | } | |
816 | ||
817 | $elements = parse_url($url); | |
818 | if (!empty($elements['query'])) { | |
819 | $elements['queryString'] = array(); | |
820 | parse_str($elements['query'], $elements['queryString']); | |
821 | } | |
822 | return $elements; | |
823 | } | |
824 | ||
efb29358 | 825 | /** |
eceb18cc | 826 | * Returns a single argument from the url query. |
1e1fdcf6 EM |
827 | * @param $arg |
828 | * @param null $url | |
829 | * @return null | |
efb29358 | 830 | */ |
6c6e6187 TO |
831 | public function urlArg($arg, $url = NULL) { |
832 | $elements = $this->parseURL($url); | |
833 | return isset($elements['queryString'][$arg]) ? $elements['queryString'][$arg] : NULL; | |
834 | } | |
efb29358 | 835 | |
6a488035 TO |
836 | /** |
837 | * Define a payment processor for use by a webtest. Default is to create Dummy processor | |
838 | * which is useful for testing online public forms (online contribution pages and event registration) | |
839 | * | |
e16033b4 TO |
840 | * @param string $processorName |
841 | * Name assigned to new processor. | |
842 | * @param string $processorType | |
843 | * Name for processor type (e.g. PayPal, Dummy, etc.). | |
844 | * @param array $processorSettings | |
845 | * Array of fieldname => value for required settings for the processor. | |
6a488035 | 846 | * |
2a6da8d7 EM |
847 | * @param string $financialAccount |
848 | * @throws PHPUnit_Framework_AssertionFailedError | |
57d32317 | 849 | * @return int |
6a488035 | 850 | */ |
00be9182 | 851 | public function webtestAddPaymentProcessor($processorName = 'Test Processor', $processorType = 'Dummy', $processorSettings = NULL, $financialAccount = 'Deposit Bank Account') { |
6a488035 TO |
852 | if (!$processorName) { |
853 | $this->fail("webTestAddPaymentProcessor requires $processorName."); | |
854 | } | |
e8eccbf5 CW |
855 | // Ensure we are logged in as admin before we proceed |
856 | $this->webtestLogin('admin'); | |
857 | ||
c3ad8633 CW |
858 | if ($processorName === 'Test Processor') { |
859 | // Use the default test processor, no need to create a new one | |
0512e9c6 | 860 | $this->openCiviPage('admin/paymentProcessor', 'action=update&id=1&reset=1', '_qf_PaymentProcessor_cancel-bottom'); |
c3ad8633 | 861 | $this->check('is_default'); |
39c74f87 | 862 | $this->select('financial_account_id', "label={$financialAccount}"); |
c3ad8633 CW |
863 | $this->clickLink('_qf_PaymentProcessor_next-bottom'); |
864 | return 1; | |
6a488035 | 865 | } |
e8eccbf5 CW |
866 | |
867 | if ($processorType == 'Dummy') { | |
868 | $processorSettings = array( | |
869 | 'user_name' => 'dummy', | |
870 | 'url_site' => 'http://dummy.com', | |
871 | 'test_user_name' => 'dummytest', | |
872 | 'test_url_site' => 'http://dummytest.com', | |
873 | ); | |
874 | } | |
6a488035 TO |
875 | elseif ($processorType == 'AuthNet') { |
876 | // FIXME: we 'll need to make a new separate account for testing | |
877 | $processorSettings = array( | |
599e7e41 | 878 | //dummy live username/password are passed to bypass processor validation on live credential |
879 | 'user_name' => '3HcY62mY', | |
880 | 'password' => '69943NrwaQA92b8J', | |
6a488035 | 881 | 'test_user_name' => '5ULu56ex', |
e390a377 | 882 | 'password' => '7ARxW575w736eF5p', |
6a488035 TO |
883 | 'test_password' => '7ARxW575w736eF5p', |
884 | ); | |
885 | } | |
6a488035 TO |
886 | elseif ($processorType == 'PayPal') { |
887 | $processorSettings = array( | |
888 | 'test_user_name' => '559999327053114', | |
3109a145 | 889 | 'user_name' => '559999327053114', |
6a488035 TO |
890 | 'test_password' => 'R2zv2g60-A7GXKJYl0nR0g', |
891 | 'test_signature' => 'R2zv2g60-A7GXKJYl0nR0g', | |
3109a145 | 892 | 'password' => 'R2zv2g60-A7GXKJYl0nR0g', |
893 | 'signature' => 'R2zv2g60-A7GXKJYl0nR0g', | |
6a488035 TO |
894 | ); |
895 | } | |
896 | elseif ($processorType == 'PayPal_Standard') { | |
897 | $processorSettings = array( | |
599e7e41 | 898 | 'user_name' => 'V18ki@9r5Bf.org', |
6a488035 TO |
899 | 'test_user_name' => 'V18ki@9r5Bf.org', |
900 | ); | |
901 | } | |
902 | elseif (empty($processorSettings)) { | |
903 | $this->fail("webTestAddPaymentProcessor requires $processorSettings array if processorType is not Dummy."); | |
904 | } | |
905 | $pid = CRM_Core_DAO::getFieldValue("CRM_Financial_DAO_PaymentProcessorType", $processorType, "id", "name"); | |
906 | if (empty($pid)) { | |
907 | $this->fail("$processorType processortype not found."); | |
908 | } | |
57d32317 | 909 | $this->openCiviPage('admin/paymentProcessor', 'action=add&reset=1&pp=' . $pid, 'name'); |
6a488035 TO |
910 | $this->type('name', $processorName); |
911 | $this->select('financial_account_id', "label={$financialAccount}"); | |
6c6e6187 | 912 | foreach ($processorSettings as $f => $v) { |
6a488035 TO |
913 | $this->type($f, $v); |
914 | } | |
14d071ba | 915 | |
57d32317 CW |
916 | // Save |
917 | $this->clickLink('_qf_PaymentProcessor_next-bottom'); | |
918 | ||
f48a56fc | 919 | $this->waitForTextPresent($processorName); |
6a488035 | 920 | |
57d32317 CW |
921 | // Get payment processor id |
922 | $paymentProcessorLink = $this->getAttribute("xpath=//table[@class='selector row-highlight']//tbody//tr/td[text()='{$processorName}']/../td[7]/span/a[1]@href"); | |
923 | return $this->urlArg('id', $paymentProcessorLink); | |
6a488035 | 924 | } |
5c88df60 | 925 | |
00be9182 | 926 | public function webtestAddCreditCardDetails() { |
6a488035 TO |
927 | $this->waitForElementPresent('credit_card_type'); |
928 | $this->select('credit_card_type', 'label=Visa'); | |
929 | $this->type('credit_card_number', '4807731747657838'); | |
930 | $this->type('cvv2', '123'); | |
931 | $this->select('credit_card_exp_date[M]', 'label=Feb'); | |
932 | $this->select('credit_card_exp_date[Y]', 'label=2019'); | |
933 | } | |
934 | ||
4cbe18b8 EM |
935 | /** |
936 | * @param null $firstName | |
937 | * @param null $middleName | |
938 | * @param null $lastName | |
939 | * | |
940 | * @return array | |
941 | */ | |
00be9182 | 942 | public function webtestAddBillingDetails($firstName = NULL, $middleName = NULL, $lastName = NULL) { |
6a488035 TO |
943 | if (!$firstName) { |
944 | $firstName = 'John'; | |
945 | } | |
946 | ||
947 | if (!$middleName) { | |
948 | $middleName = 'Apple'; | |
949 | } | |
950 | ||
951 | if (!$lastName) { | |
952 | $lastName = 'Smith_' . substr(sha1(rand()), 0, 7); | |
953 | } | |
954 | ||
955 | $this->type('billing_first_name', $firstName); | |
956 | $this->type('billing_middle_name', $middleName); | |
957 | $this->type('billing_last_name', $lastName); | |
958 | ||
959 | $this->type('billing_street_address-5', '234 Lincoln Ave'); | |
960 | $this->type('billing_city-5', 'San Bernadino'); | |
86797006 | 961 | $this->select2('billing_country_id-5', 'UNITED STATES'); |
b3d40287 | 962 | $this->select2('billing_state_province_id-5', 'California'); |
6a488035 TO |
963 | $this->type('billing_postal_code-5', '93245'); |
964 | ||
965 | return array($firstName, $middleName, $lastName); | |
966 | } | |
967 | ||
4cbe18b8 EM |
968 | /** |
969 | * @param $fieldLocator | |
970 | * @param null $filePath | |
971 | * | |
972 | * @return null|string | |
973 | */ | |
00be9182 | 974 | public function webtestAttachFile($fieldLocator, $filePath = NULL) { |
6a488035 TO |
975 | if (!$filePath) { |
976 | $filePath = '/tmp/testfile_' . substr(sha1(rand()), 0, 7) . '.txt'; | |
977 | $fp = @fopen($filePath, 'w'); | |
3bdca100 | 978 | fwrite($fp, 'Test file created by selenium test.'); |
6a488035 TO |
979 | @fclose($fp); |
980 | } | |
981 | ||
982 | $this->assertTrue(file_exists($filePath), 'Not able to locate file: ' . $filePath); | |
983 | ||
984 | $this->attachFile($fieldLocator, "file://{$filePath}"); | |
985 | ||
986 | return $filePath; | |
987 | } | |
988 | ||
4cbe18b8 EM |
989 | /** |
990 | * @param $headers | |
991 | * @param $rows | |
992 | * @param null $filePath | |
993 | * | |
994 | * @return null|string | |
995 | */ | |
00be9182 | 996 | public function webtestCreateCSV($headers, $rows, $filePath = NULL) { |
6a488035 TO |
997 | if (!$filePath) { |
998 | $filePath = '/tmp/testcsv_' . substr(sha1(rand()), 0, 7) . '.csv'; | |
999 | } | |
1000 | ||
1001 | $data = '"' . implode('", "', $headers) . '"' . "\r\n"; | |
1002 | ||
1003 | foreach ($rows as $row) { | |
1004 | $temp = array(); | |
1005 | foreach ($headers as $field => $header) { | |
1006 | $temp[$field] = isset($row[$field]) ? '"' . $row[$field] . '"' : '""'; | |
1007 | } | |
1008 | $data .= implode(', ', $temp) . "\r\n"; | |
1009 | } | |
1010 | ||
1011 | $fp = @fopen($filePath, 'w'); | |
1012 | @fwrite($fp, $data); | |
1013 | @fclose($fp); | |
1014 | ||
1015 | $this->assertTrue(file_exists($filePath), 'Not able to locate file: ' . $filePath); | |
1016 | ||
1017 | return $filePath; | |
1018 | } | |
1019 | ||
1020 | /** | |
1021 | * Create new relationship type w/ user specified params or default. | |
1022 | * | |
5a4f6742 | 1023 | * @param array $params |
72b3a70c | 1024 | * array of required params. |
6a488035 | 1025 | * |
72b3a70c CW |
1026 | * @return array |
1027 | * array of saved params values. | |
6a488035 | 1028 | */ |
00be9182 | 1029 | public function webtestAddRelationshipType($params = array()) { |
b45c587e | 1030 | $this->openCiviPage("admin/reltype", "reset=1&action=add"); |
6a488035 TO |
1031 | |
1032 | //build the params if not passed. | |
1033 | if (!is_array($params) || empty($params)) { | |
1034 | $params = array( | |
1035 | 'label_a_b' => 'Test Relationship Type A - B -' . rand(), | |
1036 | 'label_b_a' => 'Test Relationship Type B - A -' . rand(), | |
1037 | 'contact_types_a' => 'Individual', | |
1038 | 'contact_types_b' => 'Individual', | |
1039 | 'description' => 'Test Relationship Type Description', | |
1040 | ); | |
1041 | } | |
1042 | //make sure we have minimum required params. | |
1043 | if (!isset($params['label_a_b']) || empty($params['label_a_b'])) { | |
1044 | $params['label_a_b'] = 'Test Relationship Type A - B -' . rand(); | |
1045 | } | |
1046 | ||
1047 | //start the form fill. | |
1048 | $this->type('label_a_b', $params['label_a_b']); | |
1049 | $this->type('label_b_a', $params['label_b_a']); | |
1050 | $this->select('contact_types_a', "value={$params['contact_type_a']}"); | |
1051 | $this->select('contact_types_b', "value={$params['contact_type_b']}"); | |
1052 | $this->type('description', $params['description']); | |
1053 | ||
1054 | //save the data. | |
1055 | $this->click('_qf_RelationshipType_next-bottom'); | |
1056 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1057 | ||
1058 | //does data saved. | |
1059 | $this->assertTrue($this->isTextPresent('The Relationship Type has been saved.'), | |
1060 | "Status message didn't show up after saving!" | |
1061 | ); | |
1062 | ||
b45c587e | 1063 | $this->openCiviPage("admin/reltype", "reset=1"); |
6a488035 TO |
1064 | |
1065 | //validate data on selector. | |
1066 | $data = $params; | |
1067 | if (isset($data['description'])) { | |
1068 | unset($data['description']); | |
1069 | } | |
1070 | $this->assertStringsPresent($data); | |
1071 | ||
1072 | return $params; | |
1073 | } | |
1074 | ||
1075 | /** | |
1076 | * Create new online contribution page w/ user specified params or defaults. | |
b45c587e | 1077 | * FIXME: this function take an absurd number of params - very unwieldy :( |
6a488035 | 1078 | * |
2a6da8d7 EM |
1079 | * @param null $hash |
1080 | * @param null $rand | |
1081 | * @param null $pageTitle | |
1082 | * @param array $processor | |
1083 | * @param bool $amountSection | |
1084 | * @param bool $payLater | |
1085 | * @param bool $onBehalf | |
1086 | * @param bool $pledges | |
1087 | * @param bool $recurring | |
1088 | * @param bool $membershipTypes | |
100fef9d | 1089 | * @param int $memPriceSetId |
2a6da8d7 EM |
1090 | * @param bool $friend |
1091 | * @param int $profilePreId | |
1092 | * @param int $profilePostId | |
1093 | * @param bool $premiums | |
1094 | * @param bool $widget | |
1095 | * @param bool $pcp | |
1096 | * @param bool $isAddPaymentProcessor | |
1097 | * @param bool $isPcpApprovalNeeded | |
1098 | * @param bool $isSeparatePayment | |
1099 | * @param bool $honoreeSection | |
91d49cae | 1100 | * @param bool $allowOtherAmount |
2a6da8d7 EM |
1101 | * @param bool $isConfirmEnabled |
1102 | * @param string $financialType | |
1103 | * @param bool $fixedAmount | |
1104 | * @param bool $membershipsRequired | |
6a488035 | 1105 | * |
a6c01b45 CW |
1106 | * @return null |
1107 | * of newly created online contribution page. | |
6a488035 | 1108 | */ |
3bdca100 | 1109 | public function webtestAddContributionPage( |
5896d037 TO |
1110 | $hash = NULL, |
1111 | $rand = NULL, | |
1112 | $pageTitle = NULL, | |
1113 | $processor = array('Test Processor' => 'Dummy'), | |
1114 | $amountSection = TRUE, | |
1115 | $payLater = TRUE, | |
1116 | $onBehalf = TRUE, | |
1117 | $pledges = TRUE, | |
1118 | $recurring = FALSE, | |
1119 | $membershipTypes = TRUE, | |
1120 | $memPriceSetId = NULL, | |
1121 | $friend = TRUE, | |
1122 | $profilePreId = 1, | |
1123 | $profilePostId = 7, | |
1124 | $premiums = TRUE, | |
1125 | $widget = TRUE, | |
1126 | $pcp = TRUE, | |
1127 | $isAddPaymentProcessor = TRUE, | |
1128 | $isPcpApprovalNeeded = FALSE, | |
1129 | $isSeparatePayment = FALSE, | |
1130 | $honoreeSection = TRUE, | |
1131 | $allowOtherAmount = TRUE, | |
1132 | $isConfirmEnabled = TRUE, | |
1133 | $financialType = 'Donation', | |
1134 | $fixedAmount = TRUE, | |
dccd9f4f ERL |
1135 | $membershipsRequired = TRUE, |
1136 | $isPledgeStart = FALSE | |
6a488035 TO |
1137 | ) { |
1138 | if (!$hash) { | |
1139 | $hash = substr(sha1(rand()), 0, 7); | |
1140 | } | |
1141 | if (!$pageTitle) { | |
1142 | $pageTitle = 'Donate Online ' . $hash; | |
1143 | } | |
1144 | ||
1145 | if (!$rand) { | |
1146 | $rand = 2 * rand(2, 50); | |
1147 | } | |
1148 | ||
1149 | // Create a new payment processor if requested | |
1150 | if ($isAddPaymentProcessor) { | |
1151 | while (list($processorName, $processorType) = each($processor)) { | |
1152 | $this->webtestAddPaymentProcessor($processorName, $processorType); | |
1153 | } | |
1154 | } | |
1155 | ||
1156 | // go to the New Contribution Page page | |
b45c587e | 1157 | $this->openCiviPage('admin/contribute', 'action=add&reset=1'); |
6a488035 TO |
1158 | |
1159 | // fill in step 1 (Title and Settings) | |
1160 | $this->type('title', $pageTitle); | |
1161 | ||
1162 | //to select financial type | |
1163 | $this->select('financial_type_id', "label={$financialType}"); | |
1164 | ||
1165 | if ($onBehalf) { | |
1166 | $this->click('is_organization'); | |
d340a0e8 | 1167 | $this->select("xpath=//*[@class='crm-contribution-onbehalf_profile_id']//span[@class='crm-profile-selector-select']//select", 'label=On Behalf Of Organization'); |
6a488035 TO |
1168 | $this->type('for_organization', "On behalf $hash"); |
1169 | ||
1170 | if ($onBehalf == 'required') { | |
1171 | $this->click('CIVICRM_QFID_2_4'); | |
1172 | } | |
1173 | elseif ($onBehalf == 'optional') { | |
1174 | $this->click('CIVICRM_QFID_1_2'); | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | $this->fillRichTextField('intro_text', 'This is introductory message for ' . $pageTitle, 'CKEditor'); | |
1179 | $this->fillRichTextField('footer_text', 'This is footer message for ' . $pageTitle, 'CKEditor'); | |
1180 | ||
1181 | $this->type('goal_amount', 10 * $rand); | |
1182 | ||
1183 | // FIXME: handle Start/End Date/Time | |
1184 | if ($honoreeSection) { | |
1185 | $this->click('honor_block_is_active'); | |
1186 | $this->type('honor_block_title', "Honoree Section Title $hash"); | |
1187 | $this->type('honor_block_text', "Honoree Introductory Message $hash"); | |
5ddf4885 | 1188 | $this->click("//*[@id='s2id_soft_credit_types']/ul"); |
1189 | $this->waitForElementPresent("//*[@id='select2-drop']/ul"); | |
1190 | $this->waitForElementPresent("//*[@class='select2-result-label']"); | |
1191 | $this->clickAt("//*[@class='select2-results']/li[1]"); | |
6a488035 TO |
1192 | } |
1193 | ||
1194 | // is confirm enabled? it starts out enabled, so uncheck it if false | |
1195 | if (!$isConfirmEnabled) { | |
1196 | $this->click("id=is_confirm_enabled"); | |
1197 | } | |
1198 | ||
b45c587e CW |
1199 | // Submit form |
1200 | $this->clickLink('_qf_Settings_next', "_qf_Amount_next-bottom"); | |
1201 | ||
1202 | // Get contribution page id | |
1203 | $pageId = $this->urlArg('id'); | |
6a488035 TO |
1204 | |
1205 | // fill in step 2 (Processor, Pay Later, Amounts) | |
1206 | if (!empty($processor)) { | |
1207 | reset($processor); | |
1208 | while (list($processorName) = each($processor)) { | |
1209 | // select newly created processor | |
1210 | $xpath = "xpath=//label[text() = '{$processorName}']/preceding-sibling::input[1]"; | |
1211 | $this->assertTrue($this->isTextPresent($processorName)); | |
1212 | $this->check($xpath); | |
1213 | } | |
1214 | } | |
1215 | ||
1216 | if ($amountSection && !$memPriceSetId) { | |
1217 | if ($payLater) { | |
1218 | $this->click('is_pay_later'); | |
1219 | $this->type('pay_later_text', "Pay later label $hash"); | |
3c001b0e | 1220 | $this->fillRichTextField('pay_later_receipt', "Pay later instructions $hash"); |
6a488035 TO |
1221 | } |
1222 | ||
1223 | if ($pledges) { | |
1224 | $this->click('is_pledge_active'); | |
1225 | $this->click('pledge_frequency_unit[week]'); | |
1226 | $this->click('is_pledge_interval'); | |
1227 | $this->type('initial_reminder_day', 3); | |
1228 | $this->type('max_reminders', 2); | |
1229 | $this->type('additional_reminder_day', 1); | |
dccd9f4f ERL |
1230 | if ($isPledgeStart) { |
1231 | $this->webtestFillDate('pledge_start_date', '+1 month'); | |
1232 | } | |
6a488035 TO |
1233 | } |
1234 | elseif ($recurring) { | |
1235 | $this->click('is_recur'); | |
1236 | $this->click("is_recur_interval"); | |
1237 | $this->click("is_recur_installments"); | |
1238 | } | |
91d49cae | 1239 | if ($allowOtherAmount) { |
6a488035 TO |
1240 | |
1241 | $this->click('is_allow_other_amount'); | |
1242 | ||
1243 | // there shouldn't be minimums and maximums on test contribution forms unless you specify it | |
1244 | //$this->type('min_amount', $rand / 2); | |
1245 | //$this->type('max_amount', $rand * 10); | |
1246 | } | |
91d49cae | 1247 | if ($fixedAmount || !$allowOtherAmount) { |
1019390e PN |
1248 | $this->type('label_1', "Label $hash"); |
1249 | $this->type('value_1', "$rand"); | |
1250 | } | |
77f1e6b1 | 1251 | $this->click('CIVICRM_QFID_1_4'); |
6a488035 TO |
1252 | } |
1253 | else { | |
1254 | $this->click('amount_block_is_active'); | |
1255 | } | |
1256 | ||
1257 | $this->click('_qf_Amount_next'); | |
1258 | $this->waitForElementPresent('_qf_Amount_next-bottom'); | |
1259 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1260 | $text = "'Amount' information has been saved."; | |
1261 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1262 | ||
1263 | if ($memPriceSetId || (($membershipTypes === TRUE) || (is_array($membershipTypes) && !empty($membershipTypes)))) { | |
1264 | // go to step 3 (memberships) | |
1265 | $this->click('link=Memberships'); | |
6de2d1f6 | 1266 | $this->waitForElementPresent('_qf_MembershipBlock_submit_savenext'); |
6a488035 TO |
1267 | |
1268 | // fill in step 3 (Memberships) | |
1269 | $this->click('member_is_active'); | |
1270 | $this->waitForElementPresent('displayFee'); | |
1271 | $this->type('new_title', "Title - New Membership $hash"); | |
1272 | $this->type('renewal_title', "Title - Renewals $hash"); | |
1273 | ||
1274 | if ($memPriceSetId) { | |
1275 | $this->click('member_price_set_id'); | |
1276 | $this->select('member_price_set_id', "value={$memPriceSetId}"); | |
1277 | } | |
1278 | else { | |
1279 | if ($membershipTypes === TRUE) { | |
0b49a3ec | 1280 | $membershipTypes = array(array('id' => 2, 'name' => 'Student', 'default' => 1)); |
6a488035 TO |
1281 | } |
1282 | ||
1283 | // FIXME: handle Introductory Message - New Memberships/Renewals | |
1284 | foreach ($membershipTypes as $mType) { | |
1285 | $this->click("membership_type_{$mType['id']}"); | |
1286 | if (array_key_exists('default', $mType)) { | |
0b49a3ec | 1287 | $this->click("xpath=//label[text() = '$mType[name]']/parent::td/parent::tr/td[2]/input"); |
6a488035 TO |
1288 | } |
1289 | if (array_key_exists('auto_renew', $mType)) { | |
1290 | $this->select("auto_renew_{$mType['id']}", "label=Give option"); | |
1291 | } | |
1292 | } | |
1019390e PN |
1293 | if ($membershipsRequired) { |
1294 | $this->click('is_required'); | |
1295 | } | |
6a488035 TO |
1296 | if ($isSeparatePayment) { |
1297 | $this->click('is_separate_payment'); | |
1298 | } | |
1299 | } | |
225a8648 | 1300 | $this->clickLink('_qf_MembershipBlock_next', '_qf_MembershipBlock_next-bottom'); |
6a488035 | 1301 | $text = "'MembershipBlock' information has been saved."; |
0b49a3ec | 1302 | $this->isTextPresent($text); |
6a488035 TO |
1303 | } |
1304 | ||
1305 | // go to step 4 (thank-you and receipting) | |
1306 | $this->click('link=Receipt'); | |
1307 | $this->waitForElementPresent('_qf_ThankYou_next-bottom'); | |
1308 | ||
1309 | // fill in step 4 | |
1310 | $this->type('thankyou_title', "Thank-you Page Title $hash"); | |
1311 | // FIXME: handle Thank-you Message/Page Footer | |
1312 | $this->type('receipt_from_name', "Receipt From Name $hash"); | |
1313 | $this->type('receipt_from_email', "$hash@example.org"); | |
1314 | $this->type('receipt_text', "Receipt Message $hash"); | |
1315 | $this->type('cc_receipt', "$hash@example.net"); | |
1316 | $this->type('bcc_receipt', "$hash@example.com"); | |
1317 | ||
1318 | $this->click('_qf_ThankYou_next'); | |
1319 | $this->waitForElementPresent('_qf_ThankYou_next-bottom'); | |
1320 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1321 | $text = "'ThankYou' information has been saved."; | |
1322 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1323 | ||
1324 | if ($friend) { | |
1325 | // fill in step 5 (Tell a Friend) | |
1326 | $this->click('link=Tell a Friend'); | |
1327 | $this->waitForElementPresent('_qf_Contribute_next-bottom'); | |
1328 | $this->click('tf_is_active'); | |
1329 | $this->type('tf_title', "TaF Title $hash"); | |
1330 | $this->type('intro', "TaF Introduction $hash"); | |
1331 | $this->type('suggested_message', "TaF Suggested Message $hash"); | |
1332 | $this->type('general_link', "TaF Info Page Link $hash"); | |
1333 | $this->type('tf_thankyou_title', "TaF Thank-you Title $hash"); | |
1334 | $this->type('tf_thankyou_text', "TaF Thank-you Message $hash"); | |
1335 | ||
1336 | //$this->click('_qf_Contribute_next'); | |
1337 | $this->click('_qf_Contribute_next-bottom'); | |
1338 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1339 | $text = "'Friend' information has been saved."; | |
1340 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1341 | } | |
1342 | ||
1343 | if ($profilePreId || $profilePostId) { | |
1344 | // fill in step 6 (Include Profiles) | |
1345 | $this->click('css=li#tab_custom a'); | |
1346 | $this->waitForElementPresent('_qf_Custom_next-bottom'); | |
1347 | ||
1348 | if ($profilePreId) { | |
1421174e | 1349 | $this->select('css=tr.crm-contribution-contributionpage-custom-form-block-custom_pre_id span.crm-profile-selector-select select', "value={$profilePreId}"); |
6a488035 TO |
1350 | } |
1351 | ||
1352 | if ($profilePostId) { | |
1421174e | 1353 | $this->select('css=tr.crm-contribution-contributionpage-custom-form-block-custom_post_id span.crm-profile-selector-select select', "value={$profilePostId}"); |
6a488035 TO |
1354 | } |
1355 | ||
1356 | $this->click('_qf_Custom_next-bottom'); | |
1357 | //$this->waitForElementPresent('_qf_Custom_next-bottom'); | |
1358 | ||
1359 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1360 | $text = "'Custom' information has been saved."; | |
1361 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1362 | } | |
1363 | ||
1364 | if ($premiums) { | |
1365 | // fill in step 7 (Premiums) | |
1366 | $this->click('link=Premiums'); | |
1367 | $this->waitForElementPresent('_qf_Premium_next-bottom'); | |
1368 | $this->click('premiums_active'); | |
1369 | $this->type('premiums_intro_title', "Prem Title $hash"); | |
1370 | $this->type('premiums_intro_text', "Prem Introductory Message $hash"); | |
1371 | $this->type('premiums_contact_email', "$hash@example.info"); | |
1372 | $this->type('premiums_contact_phone', rand(100000000, 999999999)); | |
1373 | $this->click('premiums_display_min_contribution'); | |
1374 | $this->type('premiums_nothankyou_label', 'No thank-you'); | |
1375 | $this->click('_qf_Premium_next'); | |
1376 | $this->waitForElementPresent('_qf_Premium_next-bottom'); | |
1377 | ||
1378 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1379 | $text = "'Premium' information has been saved."; | |
1380 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
c432c016 | 1381 | $this->openCiviPage("admin/contribute/premium", "reset=1&action=update&id={$pageId}"); |
feb02c31 | 1382 | $this->waitForAjaxContent(); |
feb02c31 WA |
1383 | $this->waitForElementPresent('_qf_Premium_cancel-bottom'); |
1384 | $this->click("xpath=//div[@class='messages status no-popup']/a[text()='add one']"); | |
1385 | $this->waitForElementPresent('_qf_AddProduct_cancel-bottom'); | |
1386 | $this->select('product_id', "value=1"); | |
7051f2e5 | 1387 | $this->select('financial_type_id', "value=1"); |
feb02c31 WA |
1388 | $this->click('_qf_AddProduct_next-bottom'); |
1389 | $this->waitForElementPresent('_qf_Premium_cancel-bottom'); | |
1390 | $this->click('_qf_Premium_next-bottom'); | |
df90c6dd | 1391 | $this->waitForPageToLoad($this->getTimeoutMsec()); |
6a488035 TO |
1392 | } |
1393 | ||
6a488035 TO |
1394 | if ($widget) { |
1395 | // fill in step 8 (Widget Settings) | |
1396 | $this->click('link=Widgets'); | |
1397 | $this->waitForElementPresent('_qf_Widget_next-bottom'); | |
6a488035 TO |
1398 | $this->click('is_active'); |
1399 | $this->type('url_logo', "URL to Logo Image $hash"); | |
1400 | $this->type('button_title', "Button Title $hash"); | |
1401 | // Type About text in ckEditor (fieldname, text to type, editor) | |
1402 | $this->fillRichTextField('about', 'This is for ' . $pageTitle, 'CKEditor'); | |
1403 | ||
1404 | $this->click('_qf_Widget_next'); | |
1405 | $this->waitForElementPresent('_qf_Widget_next-bottom'); | |
1406 | ||
1407 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1408 | $text = "'Widget' information has been saved."; | |
1409 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1410 | } | |
1411 | ||
1412 | if ($pcp) { | |
1413 | // fill in step 9 (Enable Personal Campaign Pages) | |
1414 | $this->click('link=Personal Campaigns'); | |
1415 | $this->waitForElementPresent('_qf_Contribute_next-bottom'); | |
1416 | $this->click('pcp_active'); | |
1417 | if (!$isPcpApprovalNeeded) { | |
1418 | $this->click('is_approval_needed'); | |
1419 | } | |
1420 | $this->type('notify_email', "$hash@example.name"); | |
1421 | $this->select('supporter_profile_id', 'value=2'); | |
1422 | $this->type('tellfriend_limit', 7); | |
1423 | $this->type('link_text', "'Create Personal Campaign Page' link text $hash"); | |
1424 | ||
1425 | $this->click('_qf_Contribute_next-bottom'); | |
1426 | //$this->waitForElementPresent('_qf_PCP_next-bottom'); | |
1427 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1428 | $text = "'Pcp' information has been saved."; | |
1429 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1430 | } | |
1431 | ||
b45c587e | 1432 | return $pageId; |
6a488035 TO |
1433 | } |
1434 | ||
1435 | /** | |
100fef9d | 1436 | * Update default strict rule. |
6a488035 | 1437 | * |
2a6da8d7 | 1438 | * @param string $contactType |
e16033b4 TO |
1439 | * @param array $fields |
1440 | * Fields to be set for strict rule. | |
1441 | * @param int $threshold | |
1442 | * Rule's threshold value. | |
6a488035 | 1443 | */ |
00be9182 | 1444 | public function webtestStrictDedupeRuleDefault($contactType = 'Individual', $fields = array(), $threshold = 10) { |
6a488035 TO |
1445 | // set default strict rule. |
1446 | $strictRuleId = 4; | |
1447 | if ($contactType == 'Organization') { | |
1448 | $strictRuleId = 5; | |
1449 | } | |
1450 | elseif ($contactType == 'Household') { | |
1451 | $strictRuleId = 6; | |
1452 | } | |
1453 | ||
1454 | // Default dedupe fields for each Contact type. | |
1455 | if (empty($fields)) { | |
1456 | $fields = array('civicrm_email.email' => 10); | |
1457 | if ($contactType == 'Organization') { | |
1458 | $fields = array( | |
1459 | 'civicrm_contact.organization_name' => 10, | |
1460 | 'civicrm_email.email' => 10, | |
1461 | ); | |
1462 | } | |
1463 | elseif ($contactType == 'Household') { | |
1464 | $fields = array( | |
1465 | 'civicrm_contact.household_name' => 10, | |
1466 | 'civicrm_email.email' => 10, | |
1467 | ); | |
1468 | } | |
1469 | } | |
1470 | ||
b45c587e | 1471 | $this->openCiviPage('contact/deduperules', "action=update&id=$strictRuleId", '_qf_DedupeRules_next-bottom'); |
6a488035 TO |
1472 | |
1473 | $count = 0; | |
1474 | foreach ($fields as $field => $weight) { | |
1475 | $this->select("where_{$count}", "value={$field}"); | |
1476 | $this->type("length_{$count}", ''); | |
1477 | $this->type("weight_{$count}", $weight); | |
1478 | $count++; | |
1479 | } | |
1480 | ||
1481 | if ($count > 4) { | |
1482 | $this->type('threshold', $threshold); | |
1483 | // click save | |
1484 | $this->click('_qf_DedupeRules_next-bottom'); | |
1485 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1486 | return; | |
1487 | } | |
1488 | ||
1489 | for ($i = $count; $i <= 4; $i++) { | |
1490 | $this->select("where_{$i}", 'label=- none -'); | |
1491 | $this->type("length_{$i}", ''); | |
1492 | $this->type("weight_{$i}", ''); | |
1493 | } | |
1494 | ||
1495 | $this->type('threshold', $threshold); | |
1496 | ||
1497 | // click save | |
1498 | $this->click('_qf_DedupeRules_next-bottom'); | |
1499 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1500 | } | |
1501 | ||
4cbe18b8 EM |
1502 | /** |
1503 | * @param string $period_type | |
1504 | * @param int $duration_interval | |
1505 | * @param string $duration_unit | |
1506 | * @param string $auto_renew | |
bd265d68 | 1507 | * @param int $minimumFee |
1508 | * @param string $financialType | |
4cbe18b8 EM |
1509 | * |
1510 | * @return array | |
1511 | */ | |
7a731220 | 1512 | public function webtestAddMembershipType($period_type = 'rolling', $duration_interval = 1, $duration_unit = 'year', $auto_renew = 'no', $minimumFee = 100, $financialType = 'Member Dues') { |
6a488035 TO |
1513 | $membershipTitle = substr(sha1(rand()), 0, 7); |
1514 | $membershipOrg = $membershipTitle . ' memorg'; | |
1515 | $this->webtestAddOrganization($membershipOrg, TRUE); | |
1516 | ||
1517 | $title = 'Membership Type ' . substr(sha1(rand()), 0, 7); | |
1518 | $memTypeParams = array( | |
1519 | 'membership_type' => $title, | |
1520 | 'member_of_contact' => $membershipOrg, | |
7a731220 | 1521 | 'financial_type' => $financialType, |
6a488035 TO |
1522 | 'period_type' => $period_type, |
1523 | ); | |
1524 | ||
42daf119 | 1525 | $this->openCiviPage("admin/member/membershipType/add", "action=add&reset=1", '_qf_MembershipType_cancel-bottom'); |
6a488035 TO |
1526 | |
1527 | $this->type('name', $memTypeParams['membership_type']); | |
1528 | ||
1529 | // if auto_renew optional or required - a valid payment processor must be created first (e.g Auth.net) | |
1530 | // select the radio first since the element id changes after membership org search results are loaded | |
1531 | switch ($auto_renew) { | |
1532 | case 'optional': | |
16dc87ac | 1533 | $this->click("xpath=//table[@class='form-layout-compressed']/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'Give option, but not required')]"); |
6a488035 TO |
1534 | break; |
1535 | ||
1536 | case 'required': | |
16dc87ac | 1537 | $this->click("xpath=//table[@class='form-layout-compressed']/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'Auto-renew required')]"); |
6a488035 TO |
1538 | break; |
1539 | ||
1540 | default: | |
1541 | //check if for the element presence (the Auto renew options can be absent when proper payment processor not configured) | |
1542 | if ($this->isElementPresent("xpath=//div[@id='membership_type_form']//table/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'No auto-renew option')]")) { | |
16dc87ac | 1543 | $this->click("xpath=//table[@class='form-layout-compressed']/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'No auto-renew option')]"); |
6a488035 TO |
1544 | } |
1545 | break; | |
1546 | } | |
1547 | ||
6c6e6187 | 1548 | $this->select2('member_of_contact_id', $membershipTitle); |
6a488035 | 1549 | |
4da07767 | 1550 | $this->type('minimum_fee', $minimumFee); |
7a731220 | 1551 | $this->select('financial_type_id', "label={$memTypeParams['financial_type']}"); |
6a488035 TO |
1552 | |
1553 | $this->type('duration_interval', $duration_interval); | |
16dc87ac | 1554 | $this->waitForElementPresent('duration_unit'); |
6a488035 | 1555 | $this->select('duration_unit', "label={$duration_unit}"); |
4ea7e2aa | 1556 | $this->waitForElementPresent('period_type'); |
5ddf4885 | 1557 | $this->select('period_type', "value={$period_type}"); |
6a488035 TO |
1558 | |
1559 | $this->click('_qf_MembershipType_upload-bottom'); | |
1560 | $this->waitForElementPresent('link=Add Membership Type'); | |
1561 | $this->assertTrue($this->isTextPresent("The membership type '$title' has been saved.")); | |
1562 | ||
1563 | return $memTypeParams; | |
1564 | } | |
1565 | ||
4cbe18b8 EM |
1566 | /** |
1567 | * @param null $groupName | |
1568 | * @param null $parentGroupName | |
1569 | * | |
1570 | * @return null|string | |
1571 | */ | |
00be9182 | 1572 | public function WebtestAddGroup($groupName = NULL, $parentGroupName = NULL) { |
6a488035 TO |
1573 | $this->openCiviPage('group/add', 'reset=1', '_qf_Edit_upload-bottom'); |
1574 | ||
1575 | // fill group name | |
1576 | if (!$groupName) { | |
1577 | $groupName = 'group_' . substr(sha1(rand()), 0, 7); | |
1578 | } | |
1579 | $this->type('title', $groupName); | |
1580 | ||
1581 | // fill description | |
1582 | $this->type('description', 'Adding new group.'); | |
1583 | ||
1584 | // check Access Control | |
1585 | $this->click('group_type[1]'); | |
1586 | ||
1587 | // check Mailing List | |
1588 | $this->click('group_type[2]'); | |
1589 | ||
1590 | // select Visibility as Public Pages | |
1591 | $this->select('visibility', 'value=Public Pages'); | |
1592 | ||
1593 | // select parent group | |
1594 | if ($parentGroupName) { | |
1595 | $this->select('parents', "*$parentGroupName"); | |
1596 | } | |
1597 | ||
1598 | // Clicking save. | |
16dc87ac | 1599 | $this->click('_qf_Edit_upload-bottom'); |
6a488035 TO |
1600 | |
1601 | // Is status message correct? | |
fc8cb638 | 1602 | $this->waitForText('crm-notification-container', "The Group '$groupName' has been saved."); |
6a488035 TO |
1603 | return $groupName; |
1604 | } | |
1605 | ||
4cbe18b8 EM |
1606 | /** |
1607 | * @param string $activityType | |
1608 | * | |
1609 | * @return null | |
1610 | */ | |
00be9182 | 1611 | public function WebtestAddActivity($activityType = "Meeting") { |
6a488035 TO |
1612 | // Adding Adding contact with randomized first name for test testContactContextActivityAdd |
1613 | // We're using Quick Add block on the main page for this. | |
1614 | $firstName1 = substr(sha1(rand()), 0, 7); | |
1615 | $this->webtestAddContact($firstName1, "Summerson", $firstName1 . "@summerson.name"); | |
1616 | $firstName2 = substr(sha1(rand()), 0, 7); | |
1617 | $this->webtestAddContact($firstName2, "Anderson", $firstName2 . "@anderson.name"); | |
1618 | ||
6a488035 TO |
1619 | $this->click("css=li#tab_activity a"); |
1620 | ||
1621 | // waiting for the activity dropdown to show up | |
1622 | $this->waitForElementPresent("other_activity"); | |
1623 | ||
1624 | // Select the activity type from the activity dropdown | |
1625 | $this->select("other_activity", "label=Meeting"); | |
1626 | ||
1627 | $this->waitForElementPresent("_qf_Activity_upload-bottom"); | |
44a0d8ea | 1628 | $this->waitForElementPresent("s2id_target_contact_id"); |
6a488035 TO |
1629 | |
1630 | $this->assertTrue($this->isTextPresent("Anderson, " . $firstName2), "Contact not found in line " . __LINE__); | |
1631 | ||
1632 | // Typing contact's name into the field (using typeKeys(), not type()!)... | |
44a0d8ea | 1633 | $this->select2("assignee_contact_id", $firstName1, TRUE); |
6a488035 TO |
1634 | |
1635 | // ...and verifying if the page contains properly formatted display name for chosen contact. | |
1636 | $this->assertTrue($this->isTextPresent("Summerson, " . $firstName1), "Contact not found in line " . __LINE__); | |
1637 | ||
1638 | // Putting the contents into subject field - assigning the text to variable, it'll come in handy later | |
1639 | $subject = "This is subject of test activity being added through activity tab of contact summary screen."; | |
1640 | // For simple input fields we can use field id as selector | |
1641 | $this->type("subject", $subject); | |
1642 | $this->type("location", "Some location needs to be put in this field."); | |
1643 | ||
1644 | $this->webtestFillDateTime('activity_date_time', '+1 month 11:10PM'); | |
1645 | ||
1646 | // Setting duration. | |
1647 | $this->type("duration", "30"); | |
1648 | ||
1649 | // Putting in details. | |
1650 | $this->type("details", "Really brief details information."); | |
1651 | ||
1652 | // Making sure that status is set to Scheduled (using value, not label). | |
1653 | $this->select("status_id", "value=1"); | |
1654 | ||
1655 | // Setting priority. | |
1656 | $this->select("priority_id", "value=1"); | |
1657 | ||
1658 | // Scheduling follow-up. | |
1659 | $this->click("css=.crm-activity-form-block-schedule_followup div.crm-accordion-header"); | |
1660 | $this->select("followup_activity_type_id", "value=1"); | |
1661 | $this->webtestFillDateTime('followup_date', '+2 month 11:10PM'); | |
1662 | $this->type("followup_activity_subject", "This is subject of schedule follow-up activity"); | |
1663 | ||
1664 | // Clicking save. | |
1665 | $this->click("_qf_Activity_upload-bottom"); | |
44a0d8ea | 1666 | $this->waitForElementPresent("xpath=//div[@id='crm-notification-container']"); |
6a488035 TO |
1667 | |
1668 | // Is status message correct? | |
44a0d8ea | 1669 | $this->waitForText('crm-notification-container', "Activity '$subject' has been saved."); |
6a488035 | 1670 | |
bf333c47 | 1671 | $this->waitForElementPresent("xpath=//div[@class='dataTables_wrapper no-footer']//table/tbody/tr[2]/td[8]/span/a[text()='View']"); |
6a488035 TO |
1672 | |
1673 | // click through to the Activity view screen | |
b3d40287 | 1674 | $this->clickLinkSuppressPopup("xpath=//div[@class='dataTables_wrapper no-footer']//table/tbody/tr[2]/td[8]/span/a[text()='View']", '_qf_Activity_cancel-bottom'); |
76e86fd8 | 1675 | |
efb29358 CW |
1676 | // parse URL to grab the activity id |
1677 | // pass id back to any other tests that call this class | |
1678 | return $this->urlArg('id'); | |
6a488035 TO |
1679 | } |
1680 | ||
4cbe18b8 EM |
1681 | /** |
1682 | * @return bool | |
1683 | */ | |
3bdca100 | 1684 | public static function checkDoLocalDBTest() { |
6a488035 TO |
1685 | if (defined('CIVICRM_WEBTEST_LOCAL_DB') && |
1686 | CIVICRM_WEBTEST_LOCAL_DB | |
1687 | ) { | |
1688 | require_once 'tests/phpunit/CiviTest/CiviDBAssert.php'; | |
1689 | return TRUE; | |
1690 | } | |
1691 | return FALSE; | |
1692 | } | |
1693 | ||
1694 | /** | |
eceb18cc | 1695 | * Generic function to compare expected values after an api call to retrieved. |
6a488035 TO |
1696 | * DB values. |
1697 | * | |
fcb93467 EM |
1698 | * @param string $daoName |
1699 | * DAO Name of object we're evaluating. | |
1700 | * @param int $id | |
1701 | * Id of object | |
1702 | * @param array $match | |
1703 | * Associative array of field name => expected value. Empty if asserting | |
6a488035 | 1704 | * that a DELETE occurred |
3bdca100 | 1705 | * @param bool $delete |
fcb93467 | 1706 | * are we checking that a DELETE action occurred? |
6a488035 | 1707 | */ |
00be9182 | 1708 | public function assertDBState($daoName, $id, $match, $delete = FALSE) { |
fcb93467 EM |
1709 | if (self::checkDoLocalDBTest()) { |
1710 | CiviDBAssert::assertDBState($this, $daoName, $id, $match, $delete); | |
6a488035 | 1711 | } |
6a488035 TO |
1712 | } |
1713 | ||
4cbe18b8 | 1714 | /** |
4f1f1f2a | 1715 | * Request a record from the DB by seachColumn+searchValue. Success if a record is found. |
c490a46a | 1716 | * @param string $daoName |
08caad8e EM |
1717 | * @param string $searchValue |
1718 | * @param string $returnColumn | |
1719 | * @param string $searchColumn | |
1720 | * @param string $message | |
4cbe18b8 | 1721 | */ |
00be9182 | 1722 | public function assertDBNotNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) { |
08caad8e EM |
1723 | if (self::checkDoLocalDBTest()) { |
1724 | CiviDBAssert::assertDBNotNull($this, $daoName, $searchValue, $returnColumn, $searchColumn, $message); | |
6a488035 | 1725 | } |
6a488035 TO |
1726 | } |
1727 | ||
4cbe18b8 | 1728 | /** |
08caad8e | 1729 | * Request a record from the DB by searchColumn+searchValue. Success if returnColumn value is NULL. |
c490a46a | 1730 | * @param string $daoName |
08caad8e EM |
1731 | * @param string $searchValue |
1732 | * @param string $returnColumn | |
1733 | * @param string $searchColumn | |
1734 | * @param string $message | |
4cbe18b8 | 1735 | */ |
00be9182 | 1736 | public function assertDBNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) { |
08caad8e EM |
1737 | if (self::checkDoLocalDBTest()) { |
1738 | CiviDBAssert::assertDBNull($this, $daoName, $searchValue, $returnColumn, $searchColumn, $message); | |
6a488035 | 1739 | } |
6a488035 TO |
1740 | } |
1741 | ||
4cbe18b8 | 1742 | /** |
4f1f1f2a | 1743 | * Request a record from the DB by id. Success if row not found. |
c490a46a | 1744 | * @param string $daoName |
100fef9d | 1745 | * @param int $id |
9d06e7e6 | 1746 | * @param string $message |
4cbe18b8 | 1747 | */ |
08caad8e EM |
1748 | public function assertDBRowNotExist($daoName, $id, $message) { |
1749 | if (self::checkDoLocalDBTest()) { | |
1750 | CiviDBAssert::assertDBRowNotExist($this, $daoName, $id, $message); | |
6a488035 | 1751 | } |
6a488035 TO |
1752 | } |
1753 | ||
4cbe18b8 | 1754 | /** |
eceb18cc | 1755 | * Compare all values in a single retrieved DB record to an array of expected values. |
c490a46a | 1756 | * @param string $daoName |
100fef9d | 1757 | * @param array $searchParams |
4cbe18b8 EM |
1758 | * @param $expectedValues |
1759 | */ | |
00be9182 | 1760 | public function assertDBCompareValues($daoName, $searchParams, $expectedValues) { |
b7d77cba EM |
1761 | if (self::checkDoLocalDBTest()) { |
1762 | CiviDBAssert::assertDBCompareValues($this, $daoName, $searchParams, $expectedValues); | |
6a488035 | 1763 | } |
6a488035 TO |
1764 | } |
1765 | ||
4cbe18b8 EM |
1766 | /** |
1767 | * @param $expected | |
1768 | * @param $actual | |
1769 | * @param string $message | |
1770 | */ | |
00be9182 | 1771 | public function assertType($expected, $actual, $message = '') { |
b7d77cba | 1772 | $this->assertInternalType($expected, $actual, $message); |
6a488035 TO |
1773 | } |
1774 | ||
6a488035 | 1775 | /** |
eceb18cc | 1776 | * Add new Financial Account. |
f0be539a EM |
1777 | * @param $financialAccountTitle |
1778 | * @param bool $financialAccountDescription | |
1779 | * @param bool $accountingCode | |
1780 | * @param bool $firstName | |
1781 | * @param bool $financialAccountType | |
1782 | * @param bool $taxDeductible | |
1783 | * @param bool $isActive | |
1784 | * @param bool $isTax | |
1785 | * @param bool $taxRate | |
1786 | * @param bool $isDefault | |
6a488035 | 1787 | */ |
3bdca100 | 1788 | public function _testAddFinancialAccount( |
5896d037 TO |
1789 | $financialAccountTitle, |
1790 | $financialAccountDescription = FALSE, | |
1791 | $accountingCode = FALSE, | |
1792 | $firstName = FALSE, | |
1793 | $financialAccountType = FALSE, | |
1794 | $taxDeductible = FALSE, | |
1795 | $isActive = FALSE, | |
1796 | $isTax = FALSE, | |
1797 | $taxRate = FALSE, | |
1798 | $isDefault = FALSE | |
6a488035 TO |
1799 | ) { |
1800 | ||
b45c587e | 1801 | $this->openCiviPage("admin/financial/financialAccount", "reset=1"); |
6a488035 TO |
1802 | |
1803 | $this->click("link=Add Financial Account"); | |
1804 | $this->waitForElementPresent('_qf_FinancialAccount_cancel-botttom'); | |
1805 | ||
1806 | // Financial Account Name | |
1807 | $this->type('name', $financialAccountTitle); | |
1808 | ||
1809 | // Financial Description | |
1810 | if ($financialAccountDescription) { | |
1811 | $this->type('description', $financialAccountDescription); | |
1812 | } | |
1813 | ||
1814 | //Accounting Code | |
1815 | if ($accountingCode) { | |
1816 | $this->type('accounting_code', $accountingCode); | |
1817 | } | |
1818 | ||
1819 | // Autofill Organization | |
1820 | if ($firstName) { | |
1821 | $this->webtestOrganisationAutocomplete($firstName); | |
1822 | } | |
1823 | ||
1824 | // Financial Account Type | |
1825 | if ($financialAccountType) { | |
1826 | $this->select('financial_account_type_id', "label={$financialAccountType}"); | |
1827 | } | |
1828 | ||
1829 | // Is Tax Deductible | |
1830 | if ($taxDeductible) { | |
1831 | $this->check('is_deductible'); | |
1832 | } | |
1833 | else { | |
1834 | $this->uncheck('is_deductible'); | |
1835 | } | |
1836 | // Is Active | |
1837 | if (!$isActive) { | |
1838 | $this->check('is_active'); | |
1839 | } | |
1840 | else { | |
1841 | $this->uncheck('is_active'); | |
1842 | } | |
1843 | // Is Tax | |
1844 | if ($isTax) { | |
1845 | $this->check('is_tax'); | |
1846 | } | |
1847 | else { | |
1848 | $this->uncheck('is_tax'); | |
1849 | } | |
1850 | // Tax Rate | |
1851 | if ($taxRate) { | |
1852 | $this->type('tax_rate', $taxRate); | |
1853 | } | |
1854 | ||
1855 | // Set Default | |
1856 | if ($isDefault) { | |
1857 | $this->check('is_default'); | |
1858 | } | |
1859 | else { | |
1860 | $this->uncheck('is_default'); | |
1861 | } | |
1862 | $this->click('_qf_FinancialAccount_next-botttom'); | |
6a488035 TO |
1863 | } |
1864 | ||
6a488035 | 1865 | /** |
eceb18cc | 1866 | * Edit Financial Account. |
1e1fdcf6 EM |
1867 | * @param $editfinancialAccount |
1868 | * @param bool $financialAccountTitle | |
1869 | * @param bool $financialAccountDescription | |
1870 | * @param bool $accountingCode | |
1871 | * @param bool $firstName | |
1872 | * @param bool $financialAccountType | |
1873 | * @param bool $taxDeductible | |
1874 | * @param bool $isActive | |
1875 | * @param bool $isTax | |
1876 | * @param bool $taxRate | |
1877 | * @param bool $isDefault | |
6a488035 | 1878 | */ |
3bdca100 | 1879 | public function _testEditFinancialAccount( |
5896d037 | 1880 | $editfinancialAccount, |
92915c55 TO |
1881 | $financialAccountTitle = FALSE, |
1882 | $financialAccountDescription = FALSE, | |
1883 | $accountingCode = FALSE, | |
1884 | $firstName = FALSE, | |
1885 | $financialAccountType = FALSE, | |
1886 | $taxDeductible = FALSE, | |
1887 | $isActive = TRUE, | |
1888 | $isTax = FALSE, | |
1889 | $taxRate = FALSE, | |
1890 | $isDefault = FALSE | |
6a488035 TO |
1891 | ) { |
1892 | if ($firstName) { | |
b45c587e | 1893 | $this->openCiviPage("admin/financial/financialAccount", "reset=1"); |
6a488035 TO |
1894 | } |
1895 | ||
4a058f26 WA |
1896 | $this->waitForElementPresent("xpath=//table/tbody//tr/td[1]/div[text()='{$editfinancialAccount}']/../../td[9]/span/a[text()='Edit']"); |
1897 | $this->clickLink("xpath=//table/tbody//tr/td[1]/div[text()='{$editfinancialAccount}']/../../td[9]/span/a[text()='Edit']", '_qf_FinancialAccount_cancel-botttom', FALSE); | |
6a488035 TO |
1898 | |
1899 | // Change Financial Account Name | |
1900 | if ($financialAccountTitle) { | |
1901 | $this->type('name', $financialAccountTitle); | |
1902 | } | |
1903 | ||
1904 | // Financial Description | |
1905 | if ($financialAccountDescription) { | |
1906 | $this->type('description', $financialAccountDescription); | |
1907 | } | |
1908 | ||
1909 | //Accounting Code | |
1910 | if ($accountingCode) { | |
1911 | $this->type('accounting_code', $accountingCode); | |
1912 | } | |
1913 | ||
6a488035 TO |
1914 | // Autofill Edit Organization |
1915 | if ($firstName) { | |
1916 | $this->webtestOrganisationAutocomplete($firstName); | |
1917 | } | |
1918 | ||
1919 | // Financial Account Type | |
1920 | if ($financialAccountType) { | |
1921 | $this->select('financial_account_type_id', "label={$financialAccountType}"); | |
1922 | } | |
1923 | ||
1924 | // Is Tax Deductible | |
1925 | if ($taxDeductible) { | |
1926 | $this->check('is_deductible'); | |
1927 | } | |
1928 | else { | |
1929 | $this->uncheck('is_deductible'); | |
1930 | } | |
1931 | ||
1932 | // Is Tax | |
1933 | if ($isTax) { | |
1934 | $this->check('is_tax'); | |
1935 | } | |
1936 | else { | |
1937 | $this->uncheck('is_tax'); | |
1938 | } | |
1939 | ||
1940 | // Tax Rate | |
1941 | if ($taxRate) { | |
1942 | $this->type('tax_rate', $taxRate); | |
1943 | } | |
1944 | ||
1945 | // Set Default | |
1946 | if ($isDefault) { | |
1947 | $this->check('is_default'); | |
1948 | } | |
1949 | else { | |
1950 | $this->uncheck('is_default'); | |
1951 | } | |
1952 | ||
1953 | // Is Active | |
1954 | if ($isActive) { | |
1955 | $this->check('is_active'); | |
1956 | } | |
1957 | else { | |
1958 | $this->uncheck('is_active'); | |
1959 | } | |
1960 | $this->click('_qf_FinancialAccount_next-botttom'); | |
6cbe4dc3 | 1961 | $this->waitForElementPresent('link=Add Financial Account'); |
6a488035 TO |
1962 | } |
1963 | ||
58466af1 | 1964 | /** |
1965 | * @param $setTitle | |
1966 | * @param $usedFor | |
1967 | * @param $setHelp | |
1968 | * @param null $financialType | |
1969 | */ | |
1970 | public function _testAddSet($setTitle, $usedFor, $setHelp, $financialType = NULL) { | |
1971 | $this->openCiviPage("admin/price", "reset=1&action=add", '_qf_Set_next-bottom'); | |
1972 | ||
1973 | // Enter Priceset fields (Title, Used For ...) | |
1974 | $this->type('title', $setTitle); | |
1975 | if ($usedFor == 'Event') { | |
1976 | $this->check('extends_1'); | |
1977 | } | |
1978 | elseif ($usedFor == 'Contribution') { | |
1979 | $this->check('extends_2'); | |
1980 | } | |
1981 | ||
1982 | if ($financialType) { | |
1983 | $this->select("financial_type_id", "label={$financialType}"); | |
1984 | } | |
1985 | $this->type('help_pre', $setHelp); | |
1986 | ||
1987 | $this->assertChecked('is_active', 'Verify that Is Active checkbox is set.'); | |
1988 | $this->clickLink('_qf_Set_next-bottom'); | |
1989 | } | |
1990 | ||
1991 | /** | |
1992 | * @param $fields | |
1993 | * @param $validateString | |
1994 | * @param $financialType | |
1995 | * @param bool $dateSpecificFields | |
1996 | */ | |
1997 | public function _testAddPriceFields(&$fields, &$validateString, $financialType, $dateSpecificFields = FALSE) { | |
1998 | $validateStrings[] = $financialType; | |
1999 | $sid = $this->urlArg('sid'); | |
2000 | $this->openCiviPage('admin/price/field', "reset=1&action=add&sid=$sid", 'label'); | |
2001 | foreach ($fields as $label => $type) { | |
2002 | $validateStrings[] = $label; | |
2003 | ||
2004 | $this->type('label', $label); | |
2005 | $this->select('html_type', "value={$type}"); | |
2006 | ||
2007 | switch ($type) { | |
2008 | case 'Text': | |
2009 | $validateStrings[] = '525.00'; | |
2010 | $this->type('price', '525.00'); | |
2011 | if ($dateSpecificFields == TRUE) { | |
2012 | $this->webtestFillDateTime('active_on', '+1 week'); | |
2013 | } | |
2014 | else { | |
2015 | $this->check('is_required'); | |
2016 | } | |
2017 | break; | |
2018 | ||
2019 | case 'Select': | |
2020 | $options = array( | |
2021 | 1 => array( | |
2022 | 'label' => 'Chicken', | |
2023 | 'amount' => '30.00', | |
2024 | ), | |
2025 | 2 => array( | |
2026 | 'label' => 'Vegetarian', | |
2027 | 'amount' => '25.00', | |
2028 | ), | |
2029 | ); | |
2030 | $this->addMultipleChoiceOptions($options, $validateStrings); | |
2031 | if ($dateSpecificFields == TRUE) { | |
2032 | $this->webtestFillDateTime('expire_on', '-1 week'); | |
2033 | } | |
2034 | break; | |
2035 | ||
2036 | case 'Radio': | |
2037 | $options = array( | |
2038 | 1 => array( | |
2039 | 'label' => 'Yes', | |
2040 | 'amount' => '50.00', | |
2041 | ), | |
2042 | 2 => array( | |
2043 | 'label' => 'No', | |
2044 | 'amount' => '0', | |
2045 | ), | |
2046 | ); | |
2047 | $this->addMultipleChoiceOptions($options, $validateStrings); | |
2048 | $this->check('is_required'); | |
2049 | if ($dateSpecificFields == TRUE) { | |
2050 | $this->webtestFillDateTime('active_on', '-1 week'); | |
2051 | } | |
2052 | break; | |
2053 | ||
2054 | case 'CheckBox': | |
2055 | $options = array( | |
2056 | 1 => array( | |
2057 | 'label' => 'First Night', | |
2058 | 'amount' => '15.00', | |
2059 | ), | |
2060 | 2 => array( | |
2061 | 'label' => 'Second Night', | |
2062 | 'amount' => '15.00', | |
2063 | ), | |
2064 | ); | |
2065 | $this->addMultipleChoiceOptions($options, $validateStrings); | |
2066 | if ($dateSpecificFields == TRUE) { | |
2067 | $this->webtestFillDateTime('expire_on', '+1 week'); | |
2068 | } | |
2069 | break; | |
2070 | ||
2071 | default: | |
2072 | break; | |
2073 | } | |
2074 | $this->select('financial_type_id', "label={$financialType}"); | |
2075 | $this->clickLink('_qf_Field_next_new-bottom', '_qf_Field_next-bottom', FALSE); | |
2076 | $this->waitForText('crm-notification-container', "Price Field '$label' has been saved."); | |
2077 | } | |
2078 | } | |
2079 | ||
6a488035 | 2080 | /** |
eceb18cc | 2081 | * Delete Financial Account. |
1e1fdcf6 | 2082 | * @param $financialAccountTitle |
6a488035 | 2083 | */ |
00be9182 | 2084 | public function _testDeleteFinancialAccount($financialAccountTitle) { |
4a058f26 | 2085 | $this->click("xpath=//table/tbody//tr/td[1]/div[text()='{$financialAccountTitle}']/../../td[9]/span/a[text()='Delete']"); |
6a488035 TO |
2086 | $this->waitForElementPresent('_qf_FinancialAccount_next-botttom'); |
2087 | $this->click('_qf_FinancialAccount_next-botttom'); | |
2088 | $this->waitForElementPresent('link=Add Financial Account'); | |
6cbe4dc3 | 2089 | $this->waitForText('crm-notification-container', "Selected Financial Account has been deleted."); |
6a488035 TO |
2090 | } |
2091 | ||
2092 | /** | |
eceb18cc | 2093 | * Verify data after ADD and EDIT. |
1e1fdcf6 | 2094 | * @param $verifyData |
6a488035 | 2095 | */ |
00be9182 | 2096 | public function _assertFinancialAccount($verifyData) { |
6a488035 TO |
2097 | foreach ($verifyData as $key => $expectedValue) { |
2098 | $actualValue = $this->getValue($key); | |
2099 | if ($key == 'parent_financial_account') { | |
2100 | $this->assertTrue((bool) preg_match("/^{$expectedValue}/", $actualValue)); | |
2101 | } | |
2102 | else { | |
2103 | $this->assertEquals($expectedValue, $actualValue); | |
2104 | } | |
2105 | } | |
2106 | } | |
2107 | ||
4cbe18b8 EM |
2108 | /** |
2109 | * @param $verifySelectFieldData | |
2110 | */ | |
00be9182 | 2111 | public function _assertSelectVerify($verifySelectFieldData) { |
6a488035 TO |
2112 | foreach ($verifySelectFieldData as $key => $expectedvalue) { |
2113 | $actualvalue = $this->getSelectedLabel($key); | |
2114 | $this->assertEquals($expectedvalue, $actualvalue); | |
2115 | } | |
2116 | } | |
2117 | ||
4cbe18b8 EM |
2118 | /** |
2119 | * @param $financialType | |
2120 | * @param string $option | |
2121 | */ | |
00be9182 | 2122 | public function addeditFinancialType($financialType, $option = 'new') { |
b45c587e | 2123 | $this->openCiviPage("admin/financial/financialType", "reset=1"); |
6a488035 TO |
2124 | |
2125 | if ($option == 'Delete') { | |
4a058f26 | 2126 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1]/div[text()='$financialType[name]']/../../td[7]/span[2]"); |
6a488035 | 2127 | $this->waitForElementPresent("css=span.btn-slide-active"); |
4a058f26 | 2128 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1]/div[text()='$financialType[name]']/../../td[7]/span[2]/ul/li[2]/a"); |
6a488035 TO |
2129 | $this->waitForElementPresent("_qf_FinancialType_next"); |
2130 | $this->click("_qf_FinancialType_next"); | |
6cbe4dc3 AS |
2131 | $this->waitForElementPresent("newFinancialType"); |
2132 | $this->waitForText('crm-notification-container', 'Selected financial type has been deleted.'); | |
6a488035 TO |
2133 | return; |
2134 | } | |
2135 | if ($option == 'new') { | |
2136 | $this->click("link=Add Financial Type"); | |
2137 | } | |
2138 | else { | |
4a058f26 | 2139 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1]/div[text()='$financialType[oldname]']/../../td[7]/span/a[text()='Edit']"); |
6a488035 | 2140 | } |
c1d1bf14 | 2141 | $this->waitForElementPresent("name"); |
6a488035 TO |
2142 | $this->type('name', $financialType['name']); |
2143 | if ($option == 'new') { | |
2144 | $this->type('description', $financialType['name'] . ' description'); | |
2145 | } | |
2146 | ||
2147 | if ($financialType['is_reserved']) { | |
2148 | $this->check('is_reserved'); | |
2149 | } | |
2150 | else { | |
2151 | $this->uncheck('is_reserved'); | |
2152 | } | |
2153 | ||
2154 | if ($financialType['is_deductible']) { | |
2155 | $this->check('is_deductible'); | |
2156 | } | |
2157 | else { | |
2158 | $this->uncheck('is_deductible'); | |
2159 | } | |
2160 | ||
2161 | $this->click('_qf_FinancialType_next'); | |
6a488035 | 2162 | if ($option == 'new') { |
ba6f320f | 2163 | $text = "Your Financial \"{$financialType['name']}\" Type has been created, along with a corresponding income account \"{$financialType['name']}\". That income account, along with standard financial accounts \"Accounts Receivable\", \"Banking Fees\" and \"Premiums\" have been linked to the financial type. You may edit or replace those relationships here."; |
6a488035 TO |
2164 | } |
2165 | else { | |
c51f8adb | 2166 | $text = "The financial type \"{$financialType['name']}\" has been updated."; |
6a488035 | 2167 | } |
5c88df60 | 2168 | $this->checkCRMAlert($text); |
6a488035 TO |
2169 | } |
2170 | ||
42daf119 | 2171 | /** |
eceb18cc | 2172 | * Give the specified permissions. |
b45c587e | 2173 | * Note: this function logs in as 'admin' (logging out if necessary) |
1e1fdcf6 | 2174 | * @param $permission |
42daf119 | 2175 | */ |
00be9182 | 2176 | public function changePermissions($permission) { |
42daf119 CW |
2177 | $this->webtestLogin('admin'); |
2178 | $this->open("{$this->sboxPath}admin/people/permissions"); | |
6a488035 | 2179 | $this->waitForElementPresent('edit-submit'); |
42daf119 CW |
2180 | foreach ((array) $permission as $perm) { |
2181 | $this->check($perm); | |
6a488035 TO |
2182 | } |
2183 | $this->click('edit-submit'); | |
2184 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
2185 | $this->assertTrue($this->isTextPresent('The changes have been saved.')); | |
6a488035 TO |
2186 | } |
2187 | ||
4cbe18b8 EM |
2188 | /** |
2189 | * @param $profileTitle | |
2190 | * @param $profileFields | |
2191 | */ | |
00be9182 | 2192 | public function addProfile($profileTitle, $profileFields) { |
42daf119 | 2193 | $this->openCiviPage('admin/uf/group', "reset=1"); |
6a488035 | 2194 | |
39a2888d | 2195 | $this->clickLink('link=Add Profile', '_qf_Group_cancel-bottom'); |
6a488035 | 2196 | $this->type('title', $profileTitle); |
7df6dc24 | 2197 | $this->clickLink('_qf_Group_next-bottom'); |
6a488035 | 2198 | |
39a2888d | 2199 | $this->waitForText('crm-notification-container', "Your CiviCRM Profile '{$profileTitle}' has been added. You can add fields to this profile now."); |
6a488035 TO |
2200 | |
2201 | foreach ($profileFields as $field) { | |
2202 | $this->waitForElementPresent('field_name_0'); | |
6a488035 TO |
2203 | $this->click("id=field_name_0"); |
2204 | $this->select("id=field_name_0", "label=" . $field['type']); | |
2205 | $this->waitForElementPresent('field_name_1'); | |
2206 | $this->click("id=field_name_1"); | |
2207 | $this->select("id=field_name_1", "label=" . $field['name']); | |
2208 | $this->waitForElementPresent('label'); | |
2209 | $this->type("id=label", $field['label']); | |
2210 | $this->click("id=_qf_Field_next_new-top"); | |
bf2c3b74 | 2211 | $this->waitForElementPresent("xpath=//select[@id='field_name_1'][@style='display: none;']"); |
6a488035 TO |
2212 | //$this->assertTrue($this->isTextPresent("Your CiviCRM Profile Field '" . $field['name'] . "' has been saved to '" . $profileTitle . "'. You can add another profile field.")); |
2213 | } | |
2214 | } | |
2215 | ||
4cbe18b8 | 2216 | /** |
100fef9d | 2217 | * @param string $name |
4cbe18b8 EM |
2218 | * @param $sku |
2219 | * @param $amount | |
2220 | * @param $price | |
2221 | * @param $cost | |
2222 | * @param $financialType | |
2223 | */ | |
00be9182 | 2224 | public function addPremium($name, $sku, $amount, $price, $cost, $financialType) { |
022def1d | 2225 | $this->waitForElementPresent("_qf_ManagePremiums_upload-bottom"); |
6a488035 TO |
2226 | $this->type("name", $name); |
2227 | $this->type("sku", $sku); | |
2228 | $this->click("CIVICRM_QFID_noImage_16"); | |
2229 | $this->type("min_contribution", $amount); | |
2230 | $this->type("price", $price); | |
2231 | $this->type("cost", $cost); | |
2232 | if ($financialType) { | |
2233 | $this->select("financial_type_id", "label={$financialType}"); | |
2234 | } | |
022def1d | 2235 | $this->click("_qf_ManagePremiums_upload-bottom"); |
6a488035 TO |
2236 | $this->waitForPageToLoad($this->getTimeoutMsec()); |
2237 | } | |
2238 | ||
4cbe18b8 EM |
2239 | /** |
2240 | * @param $label | |
2241 | * @param $financialAccount | |
2242 | */ | |
00be9182 | 2243 | public function addPaymentInstrument($label, $financialAccount) { |
118e964e | 2244 | $this->openCiviPage('admin/options/payment_instrument', 'action=add&reset=1', "_qf_Options_next-bottom"); |
6a488035 | 2245 | $this->type("label", $label); |
45d22844 | 2246 | $this->type("value", "value" . $label); |
6a488035 TO |
2247 | $this->select("financial_account_id", "value=$financialAccount"); |
2248 | $this->click("_qf_Options_next-bottom"); | |
2249 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
2250 | } | |
2251 | ||
5ff68892 | 2252 | /** |
eceb18cc | 2253 | * Ensure we have a default mailbox set up for CiviMail. |
5ff68892 | 2254 | */ |
00be9182 | 2255 | public function setupDefaultMailbox() { |
5ff68892 CW |
2256 | $this->openCiviPage('admin/mailSettings', 'action=update&id=1&reset=1'); |
2257 | // Check if it hasn't already been set up | |
2258 | if (!$this->getSelectedValue('protocol')) { | |
2259 | $this->type('name', 'Test Domain'); | |
2260 | $this->select('protocol', "IMAP"); | |
2261 | $this->type('server', 'localhost'); | |
2262 | $this->type('domain', 'example.com'); | |
e739afc3 | 2263 | $this->clickLink('_qf_MailSettings_next-top'); |
5ff68892 CW |
2264 | } |
2265 | } | |
2266 | ||
6a488035 TO |
2267 | /** |
2268 | * Determine the default time-out in milliseconds. | |
2269 | * | |
2270 | * @return string, timeout expressed in milliseconds | |
2271 | */ | |
00be9182 | 2272 | public function getTimeoutMsec() { |
6a488035 TO |
2273 | // note: existing local versions of CiviSeleniumSettings may not declare $timeout, so use @ |
2274 | $timeout = ($this->settings && @$this->settings->timeout) ? ($this->settings->timeout * 1000) : 30000; | |
2275 | return (string) $timeout; // don't know why, but all our old code used a string | |
2276 | } | |
6a488035 | 2277 | |
c4e6d4e8 PJ |
2278 | /** |
2279 | * CRM-12378 | |
2280 | * checks custom fields rendering / loading properly on the fly WRT entity passed as parameter | |
2281 | * | |
2282 | * | |
e16033b4 TO |
2283 | * @param array $customSets |
2284 | * Custom sets i.e entity wise sets want to be created and checked. | |
16b10e64 | 2285 | * e.g $customSets = array(array('entity' => 'Contribution', 'subEntity' => 'Donation', |
5896d037 TO |
2286 | * 'triggerElement' => $triggerElement)) |
2287 | * array $triggerElement: the element which is responsible for custom group to load | |
2288 | * | |
2289 | * which uses the entity info as its selection value | |
e16033b4 TO |
2290 | * @param array $pageUrl |
2291 | * The url which on which the ajax custom group load takes place. | |
b7d77cba | 2292 | * @param string $beforeTriggering |
c4e6d4e8 PJ |
2293 | * @return void |
2294 | */ | |
00be9182 | 2295 | public function customFieldSetLoadOnTheFlyCheck($customSets, $pageUrl, $beforeTriggering = NULL) { |
a40669b6 CW |
2296 | // FIXME: Testing a theory that these failures have something to do with permissions |
2297 | $this->webtestLogin('admin'); | |
2298 | ||
c4e6d4e8 PJ |
2299 | //add the custom set |
2300 | $return = $this->addCustomGroupField($customSets); | |
2301 | ||
87f534f9 | 2302 | // FIXME: Hack to ensure caches are properly cleared |
dc499911 CW |
2303 | if (TRUE) { |
2304 | $userName = $this->loggedInAs; | |
e42c089b | 2305 | $this->webtestLogout(); |
dc499911 | 2306 | $this->webtestLogin($userName); |
e42c089b CW |
2307 | } |
2308 | ||
87f534f9 | 2309 | $this->openCiviPage($pageUrl['url'], $pageUrl['args']); |
b50973e8 CW |
2310 | |
2311 | // FIXME: Try to find out what the heck is going on with these tests | |
2312 | $this->waitForAjaxContent(); | |
2313 | $this->checkForErrorsOnPage(); | |
2314 | ||
5896d037 | 2315 | foreach ($return as $values) { |
c4e6d4e8 PJ |
2316 | foreach ($values as $entityType => $customData) { |
2317 | //initiate necessary variables | |
2318 | list($entity, $entityData) = explode('_', $entityType); | |
2319 | $elementType = CRM_Utils_Array::value('type', $customData['triggerElement'], 'select'); | |
2320 | $elementName = CRM_Utils_Array::value('name', $customData['triggerElement']); | |
e42c089b | 2321 | if (is_callable($beforeTriggering)) { |
5b8ddc60 PJ |
2322 | call_user_func($beforeTriggering); |
2323 | } | |
c4e6d4e8 PJ |
2324 | if ($elementType == 'select') { |
2325 | //reset the select box, so triggering of ajax only happens | |
2326 | //WRT input of value in this function | |
2327 | $this->select($elementName, "index=0"); | |
2328 | } | |
2329 | if (!empty($entityData)) { | |
2330 | if ($elementType == 'select') { | |
2331 | $this->select($elementName, "label=regexp:{$entityData}"); | |
2332 | } | |
2333 | elseif ($elementType == 'checkbox') { | |
2334 | $val = explode(',', $entityData); | |
5896d037 | 2335 | foreach ($val as $v) { |
c4e6d4e8 PJ |
2336 | $checkId = $this->getAttribute("xpath=//label[text()='{$v}']/@for"); |
2337 | $this->check($checkId); | |
2338 | } | |
2339 | } | |
16345393 AS |
2340 | elseif ($elementType == 'select2') { |
2341 | $this->select2($elementName, $entityData); | |
2342 | } | |
c4e6d4e8 | 2343 | } |
a2cfaf9e CW |
2344 | // FIXME: Try to find out what the heck is going on with these tests |
2345 | $this->waitForAjaxContent(); | |
2346 | $this->checkForErrorsOnPage(); | |
a40669b6 | 2347 | |
c4e6d4e8 | 2348 | //checking for proper custom data which is loading through ajax |
a40669b6 | 2349 | $this->waitForElementPresent("css=.custom-group-{$customData['cgtitle']}"); |
16345393 | 2350 | $this->assertElementPresent("xpath=//div[contains(@class, 'custom-group-{$customData['cgtitle']}')]/div[contains(@class, 'crm-accordion-body')]/table/tbody/tr/td[2]/input", |
c4e6d4e8 PJ |
2351 | "The on the fly custom group field is not present for entity : {$entity} => {$entityData}"); |
2352 | } | |
2353 | } | |
2354 | } | |
2355 | ||
4cbe18b8 EM |
2356 | /** |
2357 | * @param $customSets | |
2358 | * | |
2359 | * @return array | |
2360 | */ | |
00be9182 | 2361 | public function addCustomGroupField($customSets) { |
57d32317 | 2362 | $return = array(); |
c4e6d4e8 PJ |
2363 | foreach ($customSets as $customSet) { |
2364 | $this->openCiviPage("admin/custom/group", "action=add&reset=1"); | |
2365 | ||
2366 | //fill custom group title | |
2367 | $customGroupTitle = "webtest_for_ajax_cd" . substr(sha1(rand()), 0, 4); | |
2368 | $this->click("title"); | |
2369 | $this->type("title", $customGroupTitle); | |
2370 | ||
2371 | //custom group extends | |
2372 | $this->click("extends_0"); | |
2373 | $this->select("extends_0", "value={$customSet['entity']}"); | |
2374 | if (!empty($customSet['subEntity'])) { | |
2375 | $this->addSelection("extends_1", "label={$customSet['subEntity']}"); | |
2376 | } | |
2377 | ||
2378 | // Don't collapse | |
2379 | $this->uncheck('collapse_display'); | |
2380 | ||
2381 | // Save | |
2382 | $this->click('_qf_Group_next-bottom'); | |
c4e6d4e8 PJ |
2383 | |
2384 | //Is custom group created? | |
2385 | $this->waitForText('crm-notification-container', "Your custom field set '{$customGroupTitle}' has been added."); | |
5dac229e | 2386 | |
c4e6d4e8 | 2387 | $gid = $this->urlArg('gid'); |
5dac229e | 2388 | $this->waitForTextPresent("{$customGroupTitle} - New Field"); |
c4e6d4e8 PJ |
2389 | |
2390 | $fieldLabel = "custom_field_for_{$customSet['entity']}_{$customSet['subEntity']}" . substr(sha1(rand()), 0, 4); | |
c3ad8633 | 2391 | $this->waitForElementPresent('label'); |
c4e6d4e8 | 2392 | $this->type('label', $fieldLabel); |
50d95825 | 2393 | $this->click('_qf_Field_done-bottom'); |
c4e6d4e8 | 2394 | |
c3ad8633 CW |
2395 | $this->waitForText('crm-notification-container', $fieldLabel); |
2396 | $this->waitForAjaxContent(); | |
2397 | ||
2398 | $customGroupTitle = preg_replace('/\s/', '_', trim($customGroupTitle)); | |
c4e6d4e8 | 2399 | $return[] = array( |
5896d037 TO |
2400 | "{$customSet['entity']}_{$customSet['subEntity']}" => array( |
2401 | 'cgtitle' => $customGroupTitle, | |
2402 | 'gid' => $gid, | |
21dfd5f5 TO |
2403 | 'triggerElement' => $customSet['triggerElement'], |
2404 | ), | |
5896d037 | 2405 | ); |
e739afc3 CW |
2406 | |
2407 | // Go home for a sec to give time for caches to clear | |
2408 | $this->openCiviPage(''); | |
c4e6d4e8 PJ |
2409 | } |
2410 | return $return; | |
2411 | } | |
5320adf4 WA |
2412 | |
2413 | /** | |
e4f46be0 | 2414 | * Type and select first occurrence of autocomplete. |
ea3ddccf | 2415 | * |
1e1fdcf6 | 2416 | * @param $fieldName |
ea3ddccf | 2417 | * @param string $labels |
1e1fdcf6 EM |
2418 | * @param bool $multiple |
2419 | * @param bool $xpath | |
5320adf4 | 2420 | */ |
0b49a3ec | 2421 | public function select2($fieldName, $labels, $multiple = FALSE, $xpath = FALSE) { |
57d32317 CW |
2422 | // In the case of chainSelect, wait for options to load |
2423 | $this->waitForElementNotPresent('css=select.loading'); | |
2af8120a | 2424 | if ($multiple) { |
761fe7bb | 2425 | foreach ((array) $labels as $label) { |
0b49a3ec | 2426 | $this->clickAt("//*[@id='$fieldName']/../div/ul/li"); |
2427 | $this->keyDown("//*[@id='$fieldName']/../div/ul/li//input", " "); | |
2428 | $this->type("//*[@id='$fieldName']/../div/ul/li//input", $label); | |
2429 | $this->typeKeys("//*[@id='$fieldName']/../div/ul/li//input", $label); | |
2430 | $this->waitForElementPresent("//*[@class='select2-result-label']"); | |
2431 | $this->clickAt("//*[contains(@class,'select2-result-selectable')]/div[contains(@class, 'select2-result-label')]"); | |
2432 | } | |
2af8120a AS |
2433 | } |
2434 | else { | |
3e60ff7f JP |
2435 | if ($xpath) { |
2436 | $this->clickAt($fieldName); | |
2437 | } | |
2438 | else { | |
2439 | $this->clickAt("//*[@id='$fieldName']/../div/a"); | |
2440 | } | |
2af8120a AS |
2441 | $this->waitForElementPresent("//*[@id='select2-drop']/div/input"); |
2442 | $this->keyDown("//*[@id='select2-drop']/div/input", " "); | |
0b49a3ec | 2443 | $this->type("//*[@id='select2-drop']/div/input", $labels); |
2444 | $this->typeKeys("//*[@id='select2-drop']/div/input", $labels); | |
2af8120a | 2445 | $this->waitForElementPresent("//*[@class='select2-result-label']"); |
e9322446 | 2446 | $this->clickAt("//*[contains(@class,'select2-result-selectable')]/div[contains(@class, 'select2-result-label')]"); |
2af8120a | 2447 | } |
e739afc3 CW |
2448 | // Wait a sec for select2 to update the original element |
2449 | sleep(1); | |
5320adf4 | 2450 | } |
f1690d4a | 2451 | |
2452 | /** | |
eceb18cc | 2453 | * Select multiple options. |
8a65f8da | 2454 | * @param $fieldId |
2455 | * @param $options | |
06dfe3b5 | 2456 | * @param $isDate if multiple date is to be selected from datepicker |
f1690d4a | 2457 | */ |
8a65f8da | 2458 | public function multiselect2($fieldId, $options, $isDate = FALSE) { |
50d95825 CW |
2459 | // In the case of chainSelect, wait for options to load |
2460 | $this->waitForElementNotPresent('css=select.loading'); | |
8a65f8da | 2461 | foreach ($options as $value) { |
06dfe3b5 | 2462 | if ($isDate) { |
8a65f8da | 2463 | $this->clickAt("xpath=//*[@id='$fieldId']/../div/ul//li/input"); |
2464 | $this->webtestFillDate($fieldId, $value, TRUE); | |
06dfe3b5 | 2465 | } |
2466 | else { | |
8a65f8da | 2467 | $this->clickAt("xpath=//*[@id='$fieldId']/../div/ul//li/input"); |
06dfe3b5 | 2468 | $this->waitForElementPresent("xpath=//ul[@class='select2-results']"); |
2469 | $this->clickAt("xpath=//ul[@class='select2-results']//li/div[text()='$value']"); | |
8a65f8da | 2470 | $this->assertElementContainsText("xpath=//*[@id='$fieldId']/preceding-sibling::div[1]/", $value); |
06dfe3b5 | 2471 | } |
f1690d4a | 2472 | } |
e739afc3 CW |
2473 | // Wait a sec for select2 to update the original element |
2474 | sleep(1); | |
f1690d4a | 2475 | } |
c41b442d CW |
2476 | |
2477 | /** | |
5c88df60 | 2478 | * Check for unobtrusive status message as set by CRM.status |
1e1fdcf6 | 2479 | * @param null $text |
c41b442d | 2480 | */ |
6c6e6187 | 2481 | public function checkCRMStatus($text = NULL) { |
c41b442d | 2482 | $this->waitForElementPresent("css=.crm-status-box-outer.status-success"); |
5c88df60 CW |
2483 | if ($text) { |
2484 | $this->assertElementContainsText("css=.crm-status-box-outer.status-success", $text); | |
2485 | } | |
c41b442d | 2486 | } |
5c88df60 | 2487 | |
dcba1580 | 2488 | /** |
5c88df60 | 2489 | * Check for obtrusive status message as set by CRM.alert |
1e1fdcf6 EM |
2490 | * @param $text |
2491 | * @param string $type | |
dcba1580 | 2492 | */ |
6c6e6187 | 2493 | public function checkCRMAlert($text, $type = 'success') { |
5c88df60 CW |
2494 | $this->waitForElementPresent("css=div.ui-notify-message.$type"); |
2495 | $this->waitForText("css=div.ui-notify-message.$type", $text); | |
9c5c0056 CW |
2496 | // We got the message, now let's close it so the webtest doesn't get confused by lots of open alerts |
2497 | $this->click('css=.ui-notify-cross'); | |
dcba1580 | 2498 | } |
5c88df60 | 2499 | |
d8d3508a | 2500 | /** |
100fef9d | 2501 | * Enable or disable Pop-ups via Display Preferences |
b7d77cba | 2502 | * @param bool $enabled |
d8d3508a | 2503 | */ |
00be9182 | 2504 | public function enableDisablePopups($enabled = TRUE) { |
d8d3508a DG |
2505 | $this->openCiviPage('admin/setting/preferences/display', 'reset=1'); |
2506 | $isChecked = $this->isChecked('ajaxPopupsEnabled'); | |
2507 | if (($isChecked && !$enabled) || (!$isChecked && $enabled)) { | |
6c6e6187 | 2508 | $this->click('ajaxPopupsEnabled'); |
d8d3508a DG |
2509 | } |
2510 | if ($enabled) { | |
5c88df60 | 2511 | $this->assertChecked('ajaxPopupsEnabled'); |
d8d3508a DG |
2512 | } |
2513 | else { | |
2514 | $this->assertNotChecked('ajaxPopupsEnabled'); | |
2515 | } | |
c41b442d | 2516 | $this->clickLink("_qf_Display_next-bottom"); |
d8d3508a | 2517 | } |
b50973e8 CW |
2518 | |
2519 | /** | |
eceb18cc | 2520 | * Attempt to get information about what went wrong if we encounter an error when loading a page. |
b50973e8 | 2521 | */ |
00be9182 | 2522 | public function checkForErrorsOnPage() { |
b50973e8 | 2523 | foreach (array('Access denied', 'Page not found') as $err) { |
037454ae CW |
2524 | if ($this->isElementPresent("xpath=//h1[contains(., '$err')]")) { |
2525 | $this->fail("'$err' encountered at " . $this->getLocation() . "\nwhile logged in as '{$this->loggedInAs}'"); | |
b50973e8 CW |
2526 | } |
2527 | } | |
2528 | if ($this->isElementPresent("xpath=//span[text()='Sorry but we are not able to provide this at the moment.']")) { | |
2529 | $msg = '"Fatal Error" encountered at ' . $this->getLocation(); | |
2530 | if ($this->isElementPresent('css=div.crm-section.crm-error-message')) { | |
2531 | $msg .= "\nError Message: " . $this->getText('css=div.crm-section.crm-error-message'); | |
2532 | } | |
2533 | $this->fail($msg); | |
2534 | } | |
2535 | } | |
96025800 | 2536 | |
ef9cbdb7 TO |
2537 | /** |
2538 | * @return array | |
2539 | * Contact record (per APIv3). | |
2540 | */ | |
2541 | public function webtestGetLoggedInContact() { | |
2542 | $result = $this->rest_civicrm_api('Contact', 'get', array( | |
2543 | 'id' => 'user_contact_id', | |
2544 | )); | |
2545 | $this->assertAPISuccess($result, 'Load logged-in contact'); | |
2546 | return CRM_Utils_Array::first($result['values']); | |
2547 | } | |
2548 | ||
2549 | public function assertAPISuccess($apiResult, $prefix = '') { | |
2550 | if (!empty($prefix)) { | |
2551 | $prefix .= ': '; | |
2552 | } | |
2553 | $errorMessage = empty($apiResult['error_message']) ? '' : " " . $apiResult['error_message']; | |
2554 | ||
2555 | if (!empty($apiResult['debug_information'])) { | |
2556 | $errorMessage .= "\n " . print_r($apiResult['debug_information'], TRUE); | |
2557 | } | |
2558 | if (!empty($apiResult['trace'])) { | |
2559 | $errorMessage .= "\n" . print_r($apiResult['trace'], TRUE); | |
2560 | } | |
2561 | $this->assertFalse(civicrm_error($apiResult), $prefix . $errorMessage); | |
2562 | //$this->assertEquals(0, $apiResult['is_error']); | |
2563 | } | |
2564 | ||
7051f2e5 WA |
2565 | /** |
2566 | * Add a pledge | |
2567 | * | |
2568 | * @return array | |
2569 | */ | |
2570 | public function webtestStandalonePledgeAdd() { | |
2571 | $this->webtestLogin(); | |
2572 | ||
2573 | $this->openCiviPage('pledge/add', 'reset=1&context=standalone', '_qf_Pledge_upload'); | |
2574 | ||
2575 | // create new contact using dialog | |
2576 | $contact = $this->createDialogContact(); | |
2577 | ||
2578 | $this->type('amount', '100'); | |
2579 | $this->type('installments', '10'); | |
2580 | $this->select('frequency_unit', 'value=week'); | |
2581 | $this->type('frequency_day', '2'); | |
2582 | ||
2583 | $this->webtestFillDate('acknowledge_date', 'now'); | |
d48ea865 | 2584 | $this->waitForElementPresent('contribution_page_id'); |
7051f2e5 | 2585 | $this->select('contribution_page_id', 'value=3'); |
d48ea865 | 2586 | $this->waitForAjaxContent(); |
7051f2e5 WA |
2587 | |
2588 | //PaymentReminders | |
2589 | $this->click('PaymentReminders'); | |
2590 | $this->waitForElementPresent('additional_reminder_day'); | |
2591 | $this->type('initial_reminder_day', '4'); | |
2592 | $this->type('max_reminders', '2'); | |
2593 | $this->type('additional_reminder_day', '4'); | |
2594 | ||
2595 | $this->click('_qf_Pledge_upload-bottom'); | |
2596 | ||
2597 | $this->waitForText('crm-notification-container', "Pledge has been recorded and the payment schedule has been created."); | |
2598 | ||
2599 | // verify if Pledge is created | |
2600 | $this->waitForElementPresent("xpath=//div[@class='view-content']//table//tbody/tr[1]/td[10]/span/a[text()='View']"); | |
2601 | ||
2602 | //click through to the Pledge view screen | |
2603 | $this->click("xpath=//div[@class='view-content']//table//tbody/tr[1]/td[10]/span/a[text()='View']"); | |
2604 | $this->waitForElementPresent('_qf_PledgeView_next-bottom'); | |
2605 | $pledgeDate = date('F jS, Y', strtotime('now')); | |
2606 | ||
2607 | $this->webtestVerifyTabularData(array( | |
2608 | 'Pledge By' => $contact['display_name'], | |
2609 | 'Total Pledge Amount' => '$ 100.00', | |
2610 | 'To be paid in' => '10 installments of $ 10.00 every 1 week(s)', | |
2611 | 'Payments are due on the' => '2 day of the period', | |
2612 | 'Pledge Made' => $pledgeDate, | |
2613 | 'Financial Type' => 'Donation', | |
2614 | 'Pledge Status' => 'Pending', | |
2615 | 'Initial Reminder Day' => '4 days prior to schedule date', | |
2616 | 'Maximum Reminders Send' => 2, | |
2617 | 'Send additional reminders' => '4 days after the last one sent', | |
2618 | ) | |
2619 | ); | |
e2414672 | 2620 | $this->clickLink('_qf_PledgeView_next-bottom', "xpath=//div[@class='view-content']//table[@class='selector row-highlight']//tbody/tr[1]/td[1]/a", FALSE); |
7051f2e5 | 2621 | $this->waitForAjaxContent(); |
16dc87ac WA |
2622 | $this->click("xpath=//form[@class='CRM_Pledge_Form_Search crm-search-form']//div[@class='view-content']//table[@class='selector row-highlight']//tbody/tr[1]/td[1]/a"); |
2623 | $this->waitForElementPresent("xpath=//form[@class='CRM_Pledge_Form_Search crm-search-form']//div[@class='view-content']//table//tbody/tr[2]/td/div/table/tbody/tr[2]/td[8]/a[text()='Record Payment']"); | |
7051f2e5 WA |
2624 | return $contact; |
2625 | } | |
2626 | ||
b9fdba0a WA |
2627 | /** |
2628 | * Add a contact via profile | |
2629 | */ | |
2630 | public function webtestAddViaCreateProfile() { | |
2631 | $this->webtestLogin(); | |
2632 | ||
2633 | $this->openCiviPage('profile/create', 'reset=1&gid=1', '_qf_Edit_next'); | |
2634 | ||
2635 | $firstName = 'Jo' . substr(sha1(rand()), 0, 4); | |
2636 | $lastName = 'Ad' . substr(sha1(rand()), 0, 7); | |
2637 | ||
2638 | //contact details section | |
2639 | //fill in first name | |
2640 | $this->type("first_name", $firstName); | |
2641 | ||
2642 | //fill in last name | |
2643 | $this->type("last_name", $lastName); | |
2644 | ||
2645 | //address section | |
9fdcdf6f | 2646 | $this->waitForElementPresent('street_address-1'); |
b9fdba0a | 2647 | $this->type("street_address-1", "902C El Camino Way SW"); |
9fdcdf6f | 2648 | $this->waitForElementPresent('city-1'); |
b9fdba0a WA |
2649 | $this->type("city-1", "Dumfries"); |
2650 | $this->type("postal_code-1", "1234"); | |
2651 | $this->assertSelected('country-1', "UNITED STATES"); | |
2652 | $this->select("state_province-1", "value=1019"); | |
2653 | ||
2654 | // Clicking save. | |
2655 | $this->click("_qf_Edit_next"); | |
2656 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
2657 | ||
2658 | $this->assertElementContainsText('css=.msg-text', "Your information has been saved."); | |
2659 | } | |
2660 | ||
65c1908a | 2661 | } |