Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 4.3 | | |
5 | +--------------------------------------------------------------------+ | |
6 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
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 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | ||
29 | require_once 'PHPUnit/Extensions/SeleniumTestCase.php'; | |
30 | ||
31 | /** | |
32 | * Include configuration | |
33 | */ | |
34 | define('CIVICRM_SETTINGS_PATH', __DIR__ . '/civicrm.settings.dist.php'); | |
35 | define('CIVICRM_SETTINGS_LOCAL_PATH', __DIR__ . '/civicrm.settings.local.php'); | |
36 | ||
37 | if (file_exists(CIVICRM_SETTINGS_LOCAL_PATH)) { | |
38 | require_once CIVICRM_SETTINGS_LOCAL_PATH; | |
39 | } | |
40 | require_once CIVICRM_SETTINGS_PATH; | |
41 | ||
42 | /** | |
43 | * Base class for CiviCRM Selenium tests | |
44 | * | |
45 | * Common functions for unit tests | |
46 | * @package CiviCRM | |
47 | */ | |
48 | class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase { | |
49 | ||
50 | // protected $coverageScriptUrl = 'http://tests.dev.civicrm.org/drupal/phpunit_coverage.php'; | |
51 | ||
52 | /** | |
53 | * Constructor | |
54 | * | |
55 | * Because we are overriding the parent class constructor, we | |
56 | * need to show the same arguments as exist in the constructor of | |
57 | * PHPUnit_Framework_TestCase, since | |
58 | * PHPUnit_Framework_TestSuite::createTest() creates a | |
59 | * ReflectionClass of the Test class and checks the constructor | |
60 | * of that class to decide how to set up the test. | |
61 | * | |
62 | * @param string $name | |
63 | * @param array $data | |
64 | * @param string $dataName | |
65 | */ | |
66 | function __construct($name = NULL, array$data = array(), $dataName = '', array$browser = array()) { | |
67 | parent::__construct($name, $data, $dataName, $browser); | |
68 | ||
69 | require_once 'CiviSeleniumSettings.php'; | |
70 | $this->settings = new CiviSeleniumSettings(); | |
71 | ||
72 | // autoload | |
73 | require_once 'CRM/Core/ClassLoader.php'; | |
74 | CRM_Core_ClassLoader::singleton()->register(); | |
75 | ||
76 | // also initialize a connection to the db | |
77 | $config = CRM_Core_Config::singleton(); | |
78 | } | |
79 | ||
80 | protected function setUp() { | |
81 | $this->setBrowser($this->settings->browser); | |
82 | // Make sure that below strings have path separator at the end | |
83 | $this->setBrowserUrl($this->settings->sandboxURL); | |
84 | $this->sboxPath = $this->settings->sandboxPATH; | |
85 | } | |
86 | ||
87 | protected function tearDown() { | |
88 | // $this->open( $this->settings->sandboxPATH . "logout?reset=1"); | |
89 | } | |
90 | ||
91 | /** | |
92 | * Authenticate as drupal user | |
93 | * @param $admin: (bool) use admin user/pass instead of normal user | |
94 | */ | |
95 | function webtestLogin($admin = FALSE) { | |
96 | $this->open("{$this->sboxPath}user"); | |
97 | $password = $admin ? $this->settings->adminPassword : $this->settings->password; | |
98 | $username = $admin ? $this->settings->adminUsername : $this->settings->username; | |
99 | // Make sure login form is available | |
100 | $this->waitForElementPresent('edit-submit'); | |
101 | $this->type('edit-name', $username); | |
102 | $this->type('edit-pass', $password); | |
103 | $this->click('edit-submit'); | |
104 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
105 | } | |
106 | ||
107 | /** | |
108 | * Open an internal path beginning with 'civicrm/' | |
109 | * | |
110 | * @param $url (str) omit the 'civicrm/' it will be added for you | |
111 | * @param $args (str|array) optional url arguments | |
112 | * @param $waitFor - page element to wait for - using this is recommended to ensure the document is fully loaded | |
113 | * | |
114 | * Although it doesn't seem to do much now, using this function is recommended for | |
115 | * opening all civi pages, and using the $args param is also strongly encouraged | |
116 | * This will make it much easier to run webtests in other CMSs in the future | |
117 | */ | |
0bd37c06 | 118 | function openCiviPage($url, $args = NULL, $waitFor = 'civicrm-footer') { |
6a488035 TO |
119 | // Construct full url with args |
120 | // This could be extended in future to work with other CMS style urls | |
121 | if ($args) { | |
122 | if (is_array($args)) { | |
123 | $sep = '?'; | |
124 | foreach ($args as $key => $val) { | |
125 | $url .= $sep . $key . '=' . $val; | |
126 | $sep = '&'; | |
127 | } | |
128 | } | |
129 | else { | |
130 | $url .= "?$args"; | |
131 | } | |
132 | } | |
133 | $this->open("{$this->sboxPath}civicrm/$url"); | |
134 | $this->waitForPageToLoad(); | |
135 | if ($waitFor) { | |
136 | $this->waitForElementPresent($waitFor); | |
137 | } | |
138 | } | |
139 | ||
140 | /** | |
141 | * Call the API on the local server | |
142 | * (kind of defeats the point of a webtest - see CRM-11889) | |
143 | */ | |
144 | function webtest_civicrm_api($entity, $action, $params) { | |
145 | if (!isset($params['version'])) { | |
146 | $params['version'] = 3; | |
147 | } | |
148 | ||
149 | $result = civicrm_api($entity, $action, $params); | |
150 | $this->assertTrue(!civicrm_error($result), 'Civicrm api error.'); | |
151 | return $result; | |
152 | } | |
153 | ||
154 | /** | |
155 | * Call the API on the remote server | |
156 | * Experimental - currently only works if permissions on remote site allow anon user to access ajax api | |
157 | * @see CRM-11889 | |
158 | */ | |
159 | function rest_civicrm_api($entity, $action, $params = array()) { | |
160 | $params += array( | |
161 | 'version' => 3, | |
162 | ); | |
163 | $url = "{$this->settings->sandboxURL}/{$this->sboxPath}civicrm/ajax/rest?entity=$entity&action=$action&json=" . json_encode($params); | |
164 | $request = array( | |
165 | 'http' => array( | |
166 | 'method' => 'POST', | |
167 | // Naughty sidestep of civi's security checks | |
168 | 'header' => "X-Requested-With: XMLHttpRequest", | |
169 | ), | |
170 | ); | |
171 | $ctx = stream_context_create($request); | |
172 | $result = file_get_contents($url, FALSE, $ctx); | |
173 | return json_decode($result, TRUE); | |
174 | } | |
175 | ||
176 | function webtestGetFirstValueForOptionGroup($option_group_name) { | |
177 | $result = $this->webtest_civicrm_api("OptionValue", "getvalue", array( | |
178 | 'option_group_name' => $option_group_name, | |
179 | 'option.limit' => 1, | |
180 | 'return' => 'value' | |
181 | )); | |
182 | return $result; | |
183 | } | |
184 | ||
185 | function webtestGetValidCountryID() { | |
186 | static $_country_id; | |
187 | if (is_null($_country_id)) { | |
188 | $config_backend = $this->webtestGetConfig('countryLimit'); | |
189 | $_country_id = current($config_backend); | |
190 | } | |
191 | return $_country_id; | |
192 | } | |
193 | ||
194 | function webtestGetValidEntityID($entity) { | |
195 | // michaelmcandrew: would like to use getvalue but there is a bug | |
196 | // for e.g. group where option.limit not working at the moment CRM-9110 | |
197 | $result = $this->webtest_civicrm_api($entity, "get", array('option.limit' => 1, 'return' => 'id')); | |
198 | if (!empty($result['values'])) { | |
199 | return current(array_keys($result['values'])); | |
200 | } | |
201 | return NULL; | |
202 | } | |
203 | ||
204 | function webtestGetConfig($field) { | |
205 | static $_config_backend; | |
206 | if (is_null($_config_backend)) { | |
207 | $result = $this->webtest_civicrm_api("Domain", "getvalue", array( | |
208 | 'current_domain' => 1, | |
209 | 'option.limit' => 1, | |
210 | 'return' => 'config_backend' | |
211 | )); | |
212 | $_config_backend = unserialize($result); | |
213 | } | |
214 | return $_config_backend[$field]; | |
215 | } | |
216 | ||
1fbd57f8 CW |
217 | /** |
218 | * Ensures the required CiviCRM components are enabled | |
219 | */ | |
220 | function enableComponents($components) { | |
221 | $this->openCiviPage("admin/setting/component", "reset=1", "_qf_Component_next-bottom"); | |
222 | $enabledComponents = $this->getSelectOptions("enableComponents-t"); | |
223 | $added = FALSE; | |
224 | foreach ((array) $components as $comp) { | |
225 | if (!in_array($comp, $enabledComponents)) { | |
0bd37c06 | 226 | $this->addSelection("enableComponents-f", "label=$comp"); |
1fbd57f8 CW |
227 | $this->click("//option[@value='$comp']"); |
228 | $this->click("add"); | |
229 | $added = TRUE; | |
230 | } | |
231 | } | |
232 | if ($added) { | |
233 | $this->click("_qf_Component_next-bottom"); | |
234 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
235 | $this->assertElementContainsText("crm-notification-container", "Saved"); | |
236 | } | |
237 | } | |
238 | ||
6a488035 TO |
239 | /** |
240 | * Add a contact with the given first and last names and either a given email | |
241 | * (when specified), a random email (when true) or no email (when unspecified or null). | |
242 | * | |
243 | * @param string $fname contact’s first name | |
244 | * @param string $lname contact’s last name | |
245 | * @param mixed $email contact’s email (when string) or random email (when true) or no email (when null) | |
246 | * | |
247 | * @return mixed either a string with the (either generated or provided) email or null (if no email) | |
248 | */ | |
249 | function webtestAddContact($fname = 'Anthony', $lname = 'Anderson', $email = NULL, $contactSubtype = NULL) { | |
250 | $url = $this->sboxPath . 'civicrm/contact/add?reset=1&ct=Individual'; | |
251 | if ($contactSubtype) { | |
252 | $url = $url . "&cst={$contactSubtype}"; | |
253 | } | |
254 | $this->open($url); | |
255 | $this->waitForElementPresent('_qf_Contact_upload_view-bottom'); | |
256 | $this->type('first_name', $fname); | |
257 | $this->type('last_name', $lname); | |
258 | if ($email === TRUE) { | |
259 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
260 | } | |
261 | if ($email) { | |
262 | $this->type('email_1_email', $email); | |
263 | } | |
264 | $this->waitForElementPresent('_qf_Contact_upload_view-bottom'); | |
265 | $this->click('_qf_Contact_upload_view-bottom'); | |
266 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
267 | return $email; | |
268 | } | |
269 | ||
270 | function webtestAddHousehold($householdName = "Smith's Home", $email = NULL) { | |
271 | ||
272 | $this->open($this->sboxPath . 'civicrm/contact/add?reset=1&ct=Household'); | |
273 | $this->click('household_name'); | |
274 | $this->type('household_name', $householdName); | |
275 | ||
276 | if ($email === TRUE) { | |
277 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
278 | } | |
279 | if ($email) { | |
280 | $this->type('email_1_email', $email); | |
281 | } | |
282 | ||
283 | $this->click('_qf_Contact_upload_view'); | |
284 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
285 | return $email; | |
286 | } | |
287 | ||
288 | function webtestAddOrganization($organizationName = "Organization XYZ", $email = NULL) { | |
289 | ||
290 | $this->open($this->sboxPath . 'civicrm/contact/add?reset=1&ct=Organization'); | |
291 | $this->click('organization_name'); | |
292 | $this->type('organization_name', $organizationName); | |
293 | ||
294 | if ($email === TRUE) { | |
295 | $email = substr(sha1(rand()), 0, 7) . '@example.org'; | |
296 | } | |
297 | if ($email) { | |
298 | $this->type('email_1_email', $email); | |
299 | } | |
300 | $this->click('_qf_Contact_upload_view'); | |
301 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
302 | return $email; | |
303 | } | |
304 | ||
305 | /** | |
306 | */ | |
307 | function webtestFillAutocomplete($sortName) { | |
308 | $this->click('contact_1'); | |
309 | $this->type('contact_1', $sortName); | |
310 | $this->typeKeys('contact_1', $sortName); | |
311 | $this->waitForElementPresent("css=div.ac_results-inner li"); | |
312 | $this->click("css=div.ac_results-inner li"); | |
313 | $this->assertContains($sortName, $this->getValue('contact_1'), "autocomplete expected $sortName but didn’t find it in " . $this->getValue('contact_1')); | |
314 | } | |
315 | ||
316 | /** | |
317 | */ | |
318 | function webtestOrganisationAutocomplete($sortName) { | |
319 | $this->type('contact_name', $sortName); | |
320 | $this->click('contact_name'); | |
321 | $this->waitForElementPresent("css=div.ac_results-inner li"); | |
322 | $this->click("css=div.ac_results-inner li"); | |
323 | //$this->assertContains($sortName, $this->getValue('contact_1'), "autocomplete expected $sortName but didn’t find it in " . $this->getValue('contact_1')); | |
324 | } | |
325 | ||
326 | ||
327 | /* | |
328 | * 1. By default, when no strtotime arg is specified, sets date to "now + 1 month" | |
329 | * 2. Does not set time. For setting both date and time use webtestFillDateTime() method. | |
330 | * 3. Examples of $strToTime arguments - | |
331 | * webtestFillDate('start_date',"now") | |
332 | * webtestFillDate('start_date',"10 September 2000") | |
333 | * webtestFillDate('start_date',"+1 day") | |
334 | * webtestFillDate('start_date',"+1 week") | |
335 | * webtestFillDate('start_date',"+1 week 2 days 4 hours 2 seconds") | |
336 | * webtestFillDate('start_date',"next Thursday") | |
337 | * webtestFillDate('start_date',"last Monday") | |
338 | */ | |
339 | function webtestFillDate($dateElement, $strToTimeArgs = NULL) { | |
340 | $timeStamp = strtotime($strToTimeArgs ? $strToTimeArgs : '+1 month'); | |
341 | ||
342 | $year = date('Y', $timeStamp); | |
343 | // -1 ensures month number is inline with calender widget's month | |
344 | $mon = date('n', $timeStamp) - 1; | |
345 | $day = date('j', $timeStamp); | |
346 | ||
347 | $this->click("{$dateElement}_display"); | |
348 | $this->waitForElementPresent("css=div#ui-datepicker-div.ui-datepicker div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-month"); | |
349 | $this->select("css=div#ui-datepicker-div.ui-datepicker div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-month", "value=$mon"); | |
350 | $this->select("css=div#ui-datepicker-div div.ui-datepicker-header div.ui-datepicker-title select.ui-datepicker-year", "value=$year"); | |
351 | $this->click("link=$day"); | |
352 | } | |
353 | ||
354 | // 1. set both date and time. | |
355 | function webtestFillDateTime($dateElement, $strToTimeArgs = NULL) { | |
356 | $this->webtestFillDate($dateElement, $strToTimeArgs); | |
357 | ||
358 | $timeStamp = strtotime($strToTimeArgs ? $strToTimeArgs : '+1 month'); | |
359 | $hour = date('h', $timeStamp); | |
360 | $min = date('i', $timeStamp); | |
361 | $meri = date('A', $timeStamp); | |
362 | ||
363 | $this->type("{$dateElement}_time", "{$hour}:{$min}{$meri}"); | |
364 | } | |
365 | ||
366 | /** | |
367 | * Verify that given label/value pairs are in *sibling* td cells somewhere on the page. | |
368 | * | |
369 | * @param array $expected Array of key/value pairs (like Status/Registered) to be checked | |
370 | * @param string $xpathPrefix Pass in an xpath locator to "get to" the desired table or tables. Will be prefixed to xpath | |
371 | * table path. Include leading forward slashes (e.g. "//div[@id='activity-content']"). | |
372 | * @param string $tableId Pass in the id attribute of a table to be verified if you want to only check a specific table | |
373 | * on the web page. | |
374 | */ | |
375 | function webtestVerifyTabularData($expected, $xpathPrefix = NULL, $tableId = NULL) { | |
376 | $tableLocator = ""; | |
377 | if ($tableId) { | |
378 | $tableLocator = "[@id='$tableId']"; | |
379 | } | |
380 | foreach ($expected as $label => $value) { | |
381 | if ($xpathPrefix) { | |
0054ead7 | 382 | $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td{$xpathPrefix}[text()='{$label}']/../following-sibling::td", preg_quote($value), 'In line ' . __LINE__); |
6a488035 TO |
383 | } |
384 | else { | |
0054ead7 | 385 | $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td[text()='{$label}']/following-sibling::td", preg_quote($value), 'In line ' . __LINE__); |
6a488035 TO |
386 | } |
387 | } | |
388 | } | |
389 | ||
390 | /** | |
391 | * Types text into a ckEditor rich text field in a form | |
392 | * | |
393 | * @param string $fieldName form field name (as assigned by PHP buildForm class) | |
394 | * @param string $text text to type into the field | |
395 | * @param string $editor which text editor (valid values are 'CKEditor', 'TinyMCE') | |
396 | * | |
397 | * @return void | |
398 | */ | |
399 | function fillRichTextField($fieldName, $text = 'Typing this text into editor.', $editor = 'CKEditor') { | |
400 | // make sure cursor focuses on the field | |
401 | $this->fireEvent($fieldName, 'focus'); | |
402 | if ($editor == 'CKEditor') { | |
403 | $this->waitForElementPresent("xpath=//div[@id='cke_{$fieldName}']//iframe"); | |
404 | $this->runScript("CKEDITOR.instances['{$fieldName}'].setData('<p>{$text}</p>');"); | |
405 | } | |
406 | elseif ($editor == 'TinyMCE') { | |
407 | $this->selectFrame("xpath=//iframe[@id='{$fieldName}_ifr']"); | |
408 | $this->type("//html/body[@id='tinymce']", $text); | |
409 | } | |
410 | else { | |
411 | $this->fail("Unknown editor value: $editor, failing (in CiviSeleniumTestCase::fillRichTextField ..."); | |
412 | } | |
413 | $this->selectFrame('relative=top'); | |
414 | } | |
415 | ||
416 | /** | |
417 | * Types option label and name into a table of multiple choice options | |
418 | * (for price set fields of type select, radio, or checkbox) | |
419 | * TODO: extend for custom field multiple choice table input | |
420 | * | |
421 | * @param array $options form field name (as assigned by PHP buildForm class) | |
422 | * @param array $validateStrings appends label and name strings to this array so they can be validated later | |
423 | * | |
424 | * @return void | |
425 | */ | |
426 | function addMultipleChoiceOptions($options, &$validateStrings) { | |
427 | foreach ($options as $oIndex => $oValue) { | |
428 | $validateStrings[] = $oValue['label']; | |
429 | $validateStrings[] = $oValue['amount']; | |
430 | if (CRM_Utils_Array::value('membership_type_id', $oValue)) { | |
431 | $this->select("membership_type_id_{$oIndex}", "value={$oValue['membership_type_id']}"); | |
432 | } | |
433 | if (CRM_Utils_Array::value('financial_type_id', $oValue)) { | |
434 | $this->select("option_financial_type_id_{$oIndex}", "label={$oValue['financial_type_id']}"); | |
435 | } | |
436 | $this->type("option_label_{$oIndex}", $oValue['label']); | |
437 | $this->type("option_amount_{$oIndex}", $oValue['amount']); | |
438 | $this->click('link=another choice'); | |
439 | } | |
440 | } | |
441 | ||
442 | /** | |
443 | */ | |
444 | function webtestNewDialogContact($fname = 'Anthony', $lname = 'Anderson', $email = 'anthony@anderson.biz', $type = 4, $selectId = 'profiles_1', $row = 1) { | |
445 | // 4 - Individual profile | |
446 | // 5 - Organization profile | |
447 | // 6 - Household profile | |
448 | $this->select($selectId, "value={$type}"); | |
449 | ||
450 | // create new contact using dialog | |
451 | $this->waitForElementPresent("css=div#contact-dialog-{$row}"); | |
452 | $this->waitForElementPresent('_qf_Edit_next'); | |
453 | ||
454 | switch ($type) { | |
455 | case 4: | |
456 | $this->type('first_name', $fname); | |
457 | $this->type('last_name', $lname); | |
458 | break; | |
459 | ||
460 | case 5: | |
461 | $this->type('organization_name', $fname); | |
462 | break; | |
463 | ||
464 | case 6: | |
465 | $this->type('household_name', $fname); | |
466 | break; | |
467 | } | |
468 | ||
469 | $this->type('email-Primary', $email); | |
470 | $this->click('_qf_Edit_next'); | |
471 | ||
472 | // Is new contact created? | |
473 | if ($lname) { | |
474 | $this->assertTrue($this->isTextPresent("$lname, $fname has been created."), "Status message didn't show up after saving!"); | |
475 | } | |
476 | else { | |
477 | $this->assertTrue($this->isTextPresent("$fname has been created."), "Status message didn't show up after saving!"); | |
478 | } | |
479 | } | |
480 | ||
481 | /** | |
482 | * Generic function to check that strings are present in the page | |
483 | * | |
484 | * @strings array array of strings or a single string | |
485 | * | |
486 | * @return void | |
487 | */ | |
488 | function assertStringsPresent($strings) { | |
489 | foreach ((array) $strings as $string) { | |
490 | $this->assertTrue($this->isTextPresent($string), "Could not find $string on page"); | |
491 | } | |
492 | } | |
493 | ||
494 | /** | |
495 | * Generic function to parse a URL string into it's elements.extract a variable value from a string (url) | |
496 | * | |
497 | * @url string url to parse or retrieve current url if null | |
498 | * | |
499 | * @return array returns an associative array containing any of the various components | |
500 | * of the URL that are present. Querystring elements are returned in sub-array (elements.queryString) | |
501 | * http://php.net/manual/en/function.parse-url.php | |
502 | * | |
503 | */ | |
504 | function parseURL($url = NULL) { | |
505 | if (!$url) { | |
506 | $url = $this->getLocation(); | |
507 | } | |
508 | ||
509 | $elements = parse_url($url); | |
510 | if (!empty($elements['query'])) { | |
511 | $elements['queryString'] = array(); | |
512 | parse_str($elements['query'], $elements['queryString']); | |
513 | } | |
514 | return $elements; | |
515 | } | |
516 | ||
517 | /** | |
518 | * Define a payment processor for use by a webtest. Default is to create Dummy processor | |
519 | * which is useful for testing online public forms (online contribution pages and event registration) | |
520 | * | |
521 | * @param string $processorName Name assigned to new processor | |
522 | * @param string $processorType Name for processor type (e.g. PayPal, Dummy, etc.) | |
523 | * @param array $processorSettings Array of fieldname => value for required settings for the processor | |
524 | * | |
525 | * @return void | |
526 | */ | |
527 | ||
528 | function webtestAddPaymentProcessor($processorName, $processorType = 'Dummy', $processorSettings = NULL, $financialAccount = 'Deposit Bank Account') { | |
529 | if (!$processorName) { | |
530 | $this->fail("webTestAddPaymentProcessor requires $processorName."); | |
531 | } | |
532 | if ($processorType == 'Dummy') { | |
533 | $processorSettings = array( | |
534 | 'user_name' => 'dummy', | |
535 | 'url_site' => 'http://dummy.com', | |
536 | 'test_user_name' => 'dummytest', | |
537 | 'test_url_site' => 'http://dummytest.com', | |
538 | ); | |
539 | } | |
540 | elseif ($processorType == 'AuthNet') { | |
541 | // FIXME: we 'll need to make a new separate account for testing | |
542 | $processorSettings = array( | |
543 | 'test_user_name' => '5ULu56ex', | |
544 | 'test_password' => '7ARxW575w736eF5p', | |
545 | ); | |
546 | } | |
547 | elseif ($processorType == 'Google_Checkout') { | |
548 | // FIXME: we 'll need to make a new separate account for testing | |
549 | $processorSettings = array( | |
550 | 'test_user_name' => '559999327053114', | |
551 | 'test_password' => 'R2zv2g60-A7GXKJYl0nR0g', | |
552 | ); | |
553 | } | |
554 | elseif ($processorType == 'PayPal') { | |
555 | $processorSettings = array( | |
556 | 'test_user_name' => '559999327053114', | |
557 | 'test_password' => 'R2zv2g60-A7GXKJYl0nR0g', | |
558 | 'test_signature' => 'R2zv2g60-A7GXKJYl0nR0g', | |
559 | ); | |
560 | } | |
561 | elseif ($processorType == 'PayPal_Standard') { | |
562 | $processorSettings = array( | |
563 | 'test_user_name' => 'V18ki@9r5Bf.org', | |
564 | ); | |
565 | } | |
566 | elseif (empty($processorSettings)) { | |
567 | $this->fail("webTestAddPaymentProcessor requires $processorSettings array if processorType is not Dummy."); | |
568 | } | |
569 | $pid = CRM_Core_DAO::getFieldValue("CRM_Financial_DAO_PaymentProcessorType", $processorType, "id", "name"); | |
570 | if (empty($pid)) { | |
571 | $this->fail("$processorType processortype not found."); | |
572 | } | |
573 | $this->open($this->sboxPath . 'civicrm/admin/paymentProcessor?action=add&reset=1&pp=' . $pid); | |
574 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
575 | $this->type('name', $processorName); | |
576 | $this->select('financial_account_id', "label={$financialAccount}"); | |
577 | ||
578 | foreach ($processorSettings AS $f => $v) { | |
579 | $this->type($f, $v); | |
580 | } | |
581 | $this->click('_qf_PaymentProcessor_next-bottom'); | |
582 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
583 | // Is new processor created? | |
584 | $this->assertTrue($this->isTextPresent($processorName), 'Processor name not found in selector after adding payment processor (webTestAddPaymentProcessor).'); | |
585 | ||
586 | $paymentProcessorId = explode('&id=', $this->getAttribute("xpath=//table[@class='selector']//tbody//tr/td[text()='{$processorName}']/../td[7]/span/a[1]@href")); | |
587 | $paymentProcessorId = explode('&', $paymentProcessorId[1]); | |
588 | return $paymentProcessorId[0]; | |
589 | } | |
590 | ||
591 | function webtestAddCreditCardDetails() { | |
592 | $this->waitForElementPresent('credit_card_type'); | |
593 | $this->select('credit_card_type', 'label=Visa'); | |
594 | $this->type('credit_card_number', '4807731747657838'); | |
595 | $this->type('cvv2', '123'); | |
596 | $this->select('credit_card_exp_date[M]', 'label=Feb'); | |
597 | $this->select('credit_card_exp_date[Y]', 'label=2019'); | |
598 | } | |
599 | ||
600 | function webtestAddBillingDetails($firstName = NULL, $middleName = NULL, $lastName = NULL) { | |
601 | if (!$firstName) { | |
602 | $firstName = 'John'; | |
603 | } | |
604 | ||
605 | if (!$middleName) { | |
606 | $middleName = 'Apple'; | |
607 | } | |
608 | ||
609 | if (!$lastName) { | |
610 | $lastName = 'Smith_' . substr(sha1(rand()), 0, 7); | |
611 | } | |
612 | ||
613 | $this->type('billing_first_name', $firstName); | |
614 | $this->type('billing_middle_name', $middleName); | |
615 | $this->type('billing_last_name', $lastName); | |
616 | ||
617 | $this->type('billing_street_address-5', '234 Lincoln Ave'); | |
618 | $this->type('billing_city-5', 'San Bernadino'); | |
619 | $this->click('billing_state_province_id-5'); | |
620 | $this->select('billing_state_province_id-5', 'label=California'); | |
621 | $this->type('billing_postal_code-5', '93245'); | |
622 | ||
623 | return array($firstName, $middleName, $lastName); | |
624 | } | |
625 | ||
626 | function webtestAttachFile($fieldLocator, $filePath = NULL) { | |
627 | if (!$filePath) { | |
628 | $filePath = '/tmp/testfile_' . substr(sha1(rand()), 0, 7) . '.txt'; | |
629 | $fp = @fopen($filePath, 'w'); | |
630 | fputs($fp, 'Test file created by selenium test.'); | |
631 | @fclose($fp); | |
632 | } | |
633 | ||
634 | $this->assertTrue(file_exists($filePath), 'Not able to locate file: ' . $filePath); | |
635 | ||
636 | $this->attachFile($fieldLocator, "file://{$filePath}"); | |
637 | ||
638 | return $filePath; | |
639 | } | |
640 | ||
641 | function webtestCreateCSV($headers, $rows, $filePath = NULL) { | |
642 | if (!$filePath) { | |
643 | $filePath = '/tmp/testcsv_' . substr(sha1(rand()), 0, 7) . '.csv'; | |
644 | } | |
645 | ||
646 | $data = '"' . implode('", "', $headers) . '"' . "\r\n"; | |
647 | ||
648 | foreach ($rows as $row) { | |
649 | $temp = array(); | |
650 | foreach ($headers as $field => $header) { | |
651 | $temp[$field] = isset($row[$field]) ? '"' . $row[$field] . '"' : '""'; | |
652 | } | |
653 | $data .= implode(', ', $temp) . "\r\n"; | |
654 | } | |
655 | ||
656 | $fp = @fopen($filePath, 'w'); | |
657 | @fwrite($fp, $data); | |
658 | @fclose($fp); | |
659 | ||
660 | $this->assertTrue(file_exists($filePath), 'Not able to locate file: ' . $filePath); | |
661 | ||
662 | return $filePath; | |
663 | } | |
664 | ||
665 | /** | |
666 | * Create new relationship type w/ user specified params or default. | |
667 | * | |
668 | * @param $params array of required params. | |
669 | * | |
670 | * @return an array of saved params values. | |
671 | */ | |
672 | function webtestAddRelationshipType($params = array()) { | |
673 | $this->open($this->sboxPath . 'civicrm/admin/reltype?reset=1&action=add'); | |
674 | ||
675 | //build the params if not passed. | |
676 | if (!is_array($params) || empty($params)) { | |
677 | $params = array( | |
678 | 'label_a_b' => 'Test Relationship Type A - B -' . rand(), | |
679 | 'label_b_a' => 'Test Relationship Type B - A -' . rand(), | |
680 | 'contact_types_a' => 'Individual', | |
681 | 'contact_types_b' => 'Individual', | |
682 | 'description' => 'Test Relationship Type Description', | |
683 | ); | |
684 | } | |
685 | //make sure we have minimum required params. | |
686 | if (!isset($params['label_a_b']) || empty($params['label_a_b'])) { | |
687 | $params['label_a_b'] = 'Test Relationship Type A - B -' . rand(); | |
688 | } | |
689 | ||
690 | //start the form fill. | |
691 | $this->type('label_a_b', $params['label_a_b']); | |
692 | $this->type('label_b_a', $params['label_b_a']); | |
693 | $this->select('contact_types_a', "value={$params['contact_type_a']}"); | |
694 | $this->select('contact_types_b', "value={$params['contact_type_b']}"); | |
695 | $this->type('description', $params['description']); | |
696 | ||
697 | //save the data. | |
698 | $this->click('_qf_RelationshipType_next-bottom'); | |
699 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
700 | ||
701 | //does data saved. | |
702 | $this->assertTrue($this->isTextPresent('The Relationship Type has been saved.'), | |
703 | "Status message didn't show up after saving!" | |
704 | ); | |
705 | ||
706 | $this->open($this->sboxPath . 'civicrm/admin/reltype?reset=1'); | |
707 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
708 | ||
709 | //validate data on selector. | |
710 | $data = $params; | |
711 | if (isset($data['description'])) { | |
712 | unset($data['description']); | |
713 | } | |
714 | $this->assertStringsPresent($data); | |
715 | ||
716 | return $params; | |
717 | } | |
718 | ||
719 | /** | |
720 | * Create new online contribution page w/ user specified params or defaults. | |
721 | * | |
722 | * @param User can define pageTitle, hash and rand values for later data verification | |
723 | * | |
724 | * @return $pageId of newly created online contribution page. | |
725 | */ | |
726 | function webtestAddContributionPage($hash = NULL, | |
727 | $rand = NULL, | |
728 | $pageTitle = NULL, | |
729 | $processor = array('Dummy Processor' => 'Dummy'), | |
730 | $amountSection = TRUE, | |
731 | $payLater = TRUE, | |
732 | $onBehalf = TRUE, | |
733 | $pledges = TRUE, | |
734 | $recurring = FALSE, | |
735 | $membershipTypes = TRUE, | |
736 | $memPriceSetId = NULL, | |
737 | $friend = TRUE, | |
738 | $profilePreId = 1, | |
739 | $profilePostId = 7, | |
740 | $premiums = TRUE, | |
741 | $widget = TRUE, | |
742 | $pcp = TRUE, | |
743 | $isAddPaymentProcessor = TRUE, | |
744 | $isPcpApprovalNeeded = FALSE, | |
745 | $isSeparatePayment = FALSE, | |
746 | $honoreeSection = TRUE, | |
747 | $allowOtherAmmount = TRUE, | |
748 | $isConfirmEnabled = TRUE, | |
749 | $financialType = 'Donation' | |
750 | ) { | |
751 | if (!$hash) { | |
752 | $hash = substr(sha1(rand()), 0, 7); | |
753 | } | |
754 | if (!$pageTitle) { | |
755 | $pageTitle = 'Donate Online ' . $hash; | |
756 | } | |
757 | ||
758 | if (!$rand) { | |
759 | $rand = 2 * rand(2, 50); | |
760 | } | |
761 | ||
762 | // Create a new payment processor if requested | |
763 | if ($isAddPaymentProcessor) { | |
764 | while (list($processorName, $processorType) = each($processor)) { | |
765 | $this->webtestAddPaymentProcessor($processorName, $processorType); | |
766 | } | |
767 | } | |
768 | ||
769 | // go to the New Contribution Page page | |
770 | $this->open($this->sboxPath . 'civicrm/admin/contribute?action=add&reset=1'); | |
771 | $this->waitForPageToLoad(); | |
772 | ||
773 | // fill in step 1 (Title and Settings) | |
774 | $this->type('title', $pageTitle); | |
775 | ||
776 | //to select financial type | |
777 | $this->select('financial_type_id', "label={$financialType}"); | |
778 | ||
779 | if ($onBehalf) { | |
780 | $this->click('is_organization'); | |
781 | $this->select('onbehalf_profile_id', 'label=On Behalf Of Organization'); | |
782 | $this->type('for_organization', "On behalf $hash"); | |
783 | ||
784 | if ($onBehalf == 'required') { | |
785 | $this->click('CIVICRM_QFID_2_4'); | |
786 | } | |
787 | elseif ($onBehalf == 'optional') { | |
788 | $this->click('CIVICRM_QFID_1_2'); | |
789 | } | |
790 | } | |
791 | ||
792 | $this->fillRichTextField('intro_text', 'This is introductory message for ' . $pageTitle, 'CKEditor'); | |
793 | $this->fillRichTextField('footer_text', 'This is footer message for ' . $pageTitle, 'CKEditor'); | |
794 | ||
795 | $this->type('goal_amount', 10 * $rand); | |
796 | ||
797 | // FIXME: handle Start/End Date/Time | |
798 | if ($honoreeSection) { | |
799 | $this->click('honor_block_is_active'); | |
800 | $this->type('honor_block_title', "Honoree Section Title $hash"); | |
801 | $this->type('honor_block_text', "Honoree Introductory Message $hash"); | |
802 | } | |
803 | ||
804 | // is confirm enabled? it starts out enabled, so uncheck it if false | |
805 | if (!$isConfirmEnabled) { | |
806 | $this->click("id=is_confirm_enabled"); | |
807 | } | |
808 | ||
809 | // go to step 2 | |
810 | $this->click('_qf_Settings_next'); | |
811 | $this->waitForElementPresent('_qf_Amount_next-bottom'); | |
812 | ||
813 | // fill in step 2 (Processor, Pay Later, Amounts) | |
814 | if (!empty($processor)) { | |
815 | reset($processor); | |
816 | while (list($processorName) = each($processor)) { | |
817 | // select newly created processor | |
818 | $xpath = "xpath=//label[text() = '{$processorName}']/preceding-sibling::input[1]"; | |
819 | $this->assertTrue($this->isTextPresent($processorName)); | |
820 | $this->check($xpath); | |
821 | } | |
822 | } | |
823 | ||
824 | if ($amountSection && !$memPriceSetId) { | |
825 | if ($payLater) { | |
826 | $this->click('is_pay_later'); | |
827 | $this->type('pay_later_text', "Pay later label $hash"); | |
828 | $this->type('pay_later_receipt', "Pay later instructions $hash"); | |
829 | } | |
830 | ||
831 | if ($pledges) { | |
832 | $this->click('is_pledge_active'); | |
833 | $this->click('pledge_frequency_unit[week]'); | |
834 | $this->click('is_pledge_interval'); | |
835 | $this->type('initial_reminder_day', 3); | |
836 | $this->type('max_reminders', 2); | |
837 | $this->type('additional_reminder_day', 1); | |
838 | } | |
839 | elseif ($recurring) { | |
840 | $this->click('is_recur'); | |
841 | $this->click("is_recur_interval"); | |
842 | $this->click("is_recur_installments"); | |
843 | } | |
844 | if ($allowOtherAmmount) { | |
845 | ||
846 | $this->click('is_allow_other_amount'); | |
847 | ||
848 | // there shouldn't be minimums and maximums on test contribution forms unless you specify it | |
849 | //$this->type('min_amount', $rand / 2); | |
850 | //$this->type('max_amount', $rand * 10); | |
851 | } | |
852 | ||
853 | $this->type('label_1', "Label $hash"); | |
854 | $this->type('value_1', "$rand"); | |
855 | $this->click('CIVICRM_QFID_1_2'); | |
856 | } | |
857 | else { | |
858 | $this->click('amount_block_is_active'); | |
859 | } | |
860 | ||
861 | $this->click('_qf_Amount_next'); | |
862 | $this->waitForElementPresent('_qf_Amount_next-bottom'); | |
863 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
864 | $text = "'Amount' information has been saved."; | |
865 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
866 | ||
867 | if ($memPriceSetId || (($membershipTypes === TRUE) || (is_array($membershipTypes) && !empty($membershipTypes)))) { | |
868 | // go to step 3 (memberships) | |
869 | $this->click('link=Memberships'); | |
870 | $this->waitForElementPresent('_qf_MembershipBlock_next-bottom'); | |
871 | ||
872 | // fill in step 3 (Memberships) | |
873 | $this->click('member_is_active'); | |
874 | $this->waitForElementPresent('displayFee'); | |
875 | $this->type('new_title', "Title - New Membership $hash"); | |
876 | $this->type('renewal_title', "Title - Renewals $hash"); | |
877 | ||
878 | if ($memPriceSetId) { | |
879 | $this->click('member_price_set_id'); | |
880 | $this->select('member_price_set_id', "value={$memPriceSetId}"); | |
881 | } | |
882 | else { | |
883 | if ($membershipTypes === TRUE) { | |
884 | $membershipTypes = array(array('id' => 2)); | |
885 | } | |
886 | ||
887 | // FIXME: handle Introductory Message - New Memberships/Renewals | |
888 | foreach ($membershipTypes as $mType) { | |
889 | $this->click("membership_type_{$mType['id']}"); | |
890 | if (array_key_exists('default', $mType)) { | |
891 | // FIXME: | |
892 | } | |
893 | if (array_key_exists('auto_renew', $mType)) { | |
894 | $this->select("auto_renew_{$mType['id']}", "label=Give option"); | |
895 | } | |
896 | } | |
897 | ||
898 | $this->click('is_required'); | |
899 | $this->waitForElementPresent('CIVICRM_QFID_2_4'); | |
900 | $this->click('CIVICRM_QFID_2_4'); | |
901 | if ($isSeparatePayment) { | |
902 | $this->click('is_separate_payment'); | |
903 | } | |
904 | } | |
905 | $this->click('_qf_MembershipBlock_next'); | |
906 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
907 | $this->waitForElementPresent('_qf_MembershipBlock_next-bottom'); | |
908 | $text = "'MembershipBlock' information has been saved."; | |
909 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
910 | } | |
911 | ||
912 | // go to step 4 (thank-you and receipting) | |
913 | $this->click('link=Receipt'); | |
914 | $this->waitForElementPresent('_qf_ThankYou_next-bottom'); | |
915 | ||
916 | // fill in step 4 | |
917 | $this->type('thankyou_title', "Thank-you Page Title $hash"); | |
918 | // FIXME: handle Thank-you Message/Page Footer | |
919 | $this->type('receipt_from_name', "Receipt From Name $hash"); | |
920 | $this->type('receipt_from_email', "$hash@example.org"); | |
921 | $this->type('receipt_text', "Receipt Message $hash"); | |
922 | $this->type('cc_receipt', "$hash@example.net"); | |
923 | $this->type('bcc_receipt', "$hash@example.com"); | |
924 | ||
925 | $this->click('_qf_ThankYou_next'); | |
926 | $this->waitForElementPresent('_qf_ThankYou_next-bottom'); | |
927 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
928 | $text = "'ThankYou' information has been saved."; | |
929 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
930 | ||
931 | if ($friend) { | |
932 | // fill in step 5 (Tell a Friend) | |
933 | $this->click('link=Tell a Friend'); | |
934 | $this->waitForElementPresent('_qf_Contribute_next-bottom'); | |
935 | $this->click('tf_is_active'); | |
936 | $this->type('tf_title', "TaF Title $hash"); | |
937 | $this->type('intro', "TaF Introduction $hash"); | |
938 | $this->type('suggested_message', "TaF Suggested Message $hash"); | |
939 | $this->type('general_link', "TaF Info Page Link $hash"); | |
940 | $this->type('tf_thankyou_title', "TaF Thank-you Title $hash"); | |
941 | $this->type('tf_thankyou_text', "TaF Thank-you Message $hash"); | |
942 | ||
943 | //$this->click('_qf_Contribute_next'); | |
944 | $this->click('_qf_Contribute_next-bottom'); | |
945 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
946 | $text = "'Friend' information has been saved."; | |
947 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
948 | } | |
949 | ||
950 | if ($profilePreId || $profilePostId) { | |
951 | // fill in step 6 (Include Profiles) | |
952 | $this->click('css=li#tab_custom a'); | |
953 | $this->waitForElementPresent('_qf_Custom_next-bottom'); | |
954 | ||
955 | if ($profilePreId) { | |
956 | $this->select('custom_pre_id', "value={$profilePreId}"); | |
957 | } | |
958 | ||
959 | if ($profilePostId) { | |
960 | $this->select('custom_post_id', "value={$profilePostId}"); | |
961 | } | |
962 | ||
963 | $this->click('_qf_Custom_next-bottom'); | |
964 | //$this->waitForElementPresent('_qf_Custom_next-bottom'); | |
965 | ||
966 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
967 | $text = "'Custom' information has been saved."; | |
968 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
969 | } | |
970 | ||
971 | if ($premiums) { | |
972 | // fill in step 7 (Premiums) | |
973 | $this->click('link=Premiums'); | |
974 | $this->waitForElementPresent('_qf_Premium_next-bottom'); | |
975 | $this->click('premiums_active'); | |
976 | $this->type('premiums_intro_title', "Prem Title $hash"); | |
977 | $this->type('premiums_intro_text', "Prem Introductory Message $hash"); | |
978 | $this->type('premiums_contact_email', "$hash@example.info"); | |
979 | $this->type('premiums_contact_phone', rand(100000000, 999999999)); | |
980 | $this->click('premiums_display_min_contribution'); | |
981 | $this->type('premiums_nothankyou_label', 'No thank-you'); | |
982 | $this->click('_qf_Premium_next'); | |
983 | $this->waitForElementPresent('_qf_Premium_next-bottom'); | |
984 | ||
985 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
986 | $text = "'Premium' information has been saved."; | |
987 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
988 | } | |
989 | ||
990 | ||
991 | if ($widget) { | |
992 | // fill in step 8 (Widget Settings) | |
993 | $this->click('link=Widgets'); | |
994 | $this->waitForElementPresent('_qf_Widget_next-bottom'); | |
995 | ||
996 | $this->click('is_active'); | |
997 | $this->type('url_logo', "URL to Logo Image $hash"); | |
998 | $this->type('button_title', "Button Title $hash"); | |
999 | // Type About text in ckEditor (fieldname, text to type, editor) | |
1000 | $this->fillRichTextField('about', 'This is for ' . $pageTitle, 'CKEditor'); | |
1001 | ||
1002 | $this->click('_qf_Widget_next'); | |
1003 | $this->waitForElementPresent('_qf_Widget_next-bottom'); | |
1004 | ||
1005 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1006 | $text = "'Widget' information has been saved."; | |
1007 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1008 | } | |
1009 | ||
1010 | if ($pcp) { | |
1011 | // fill in step 9 (Enable Personal Campaign Pages) | |
1012 | $this->click('link=Personal Campaigns'); | |
1013 | $this->waitForElementPresent('_qf_Contribute_next-bottom'); | |
1014 | $this->click('pcp_active'); | |
1015 | if (!$isPcpApprovalNeeded) { | |
1016 | $this->click('is_approval_needed'); | |
1017 | } | |
1018 | $this->type('notify_email', "$hash@example.name"); | |
1019 | $this->select('supporter_profile_id', 'value=2'); | |
1020 | $this->type('tellfriend_limit', 7); | |
1021 | $this->type('link_text', "'Create Personal Campaign Page' link text $hash"); | |
1022 | ||
1023 | $this->click('_qf_Contribute_next-bottom'); | |
1024 | //$this->waitForElementPresent('_qf_PCP_next-bottom'); | |
1025 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1026 | $text = "'Pcp' information has been saved."; | |
1027 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1028 | } | |
1029 | ||
1030 | // parse URL to grab the contribution page id | |
1031 | $elements = $this->parseURL(); | |
1032 | $pageId = $elements['queryString']['id']; | |
1033 | ||
1034 | // pass $pageId back to any other tests that call this class | |
1035 | return $pageId; | |
1036 | } | |
1037 | ||
1038 | /** | |
1039 | * Function to update default strict rule. | |
1040 | * | |
1041 | * @params string $contactType Contact type | |
1042 | * @param array $fields Fields to be set for strict rule | |
1043 | * @param Integer $threshold Rule's threshold value | |
1044 | */ | |
1045 | function webtestStrictDedupeRuleDefault($contactType = 'Individual', $fields = array(), $threshold = 10) { | |
1046 | // set default strict rule. | |
1047 | $strictRuleId = 4; | |
1048 | if ($contactType == 'Organization') { | |
1049 | $strictRuleId = 5; | |
1050 | } | |
1051 | elseif ($contactType == 'Household') { | |
1052 | $strictRuleId = 6; | |
1053 | } | |
1054 | ||
1055 | // Default dedupe fields for each Contact type. | |
1056 | if (empty($fields)) { | |
1057 | $fields = array('civicrm_email.email' => 10); | |
1058 | if ($contactType == 'Organization') { | |
1059 | $fields = array( | |
1060 | 'civicrm_contact.organization_name' => 10, | |
1061 | 'civicrm_email.email' => 10, | |
1062 | ); | |
1063 | } | |
1064 | elseif ($contactType == 'Household') { | |
1065 | $fields = array( | |
1066 | 'civicrm_contact.household_name' => 10, | |
1067 | 'civicrm_email.email' => 10, | |
1068 | ); | |
1069 | } | |
1070 | } | |
1071 | ||
1072 | $this->open($this->sboxPath . 'civicrm/contact/deduperules?action=update&id=' . $strictRuleId); | |
1073 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1074 | $this->waitForElementPresent('_qf_DedupeRules_next-bottom'); | |
1075 | ||
1076 | $count = 0; | |
1077 | foreach ($fields as $field => $weight) { | |
1078 | $this->select("where_{$count}", "value={$field}"); | |
1079 | $this->type("length_{$count}", ''); | |
1080 | $this->type("weight_{$count}", $weight); | |
1081 | $count++; | |
1082 | } | |
1083 | ||
1084 | if ($count > 4) { | |
1085 | $this->type('threshold', $threshold); | |
1086 | // click save | |
1087 | $this->click('_qf_DedupeRules_next-bottom'); | |
1088 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1089 | return; | |
1090 | } | |
1091 | ||
1092 | for ($i = $count; $i <= 4; $i++) { | |
1093 | $this->select("where_{$i}", 'label=- none -'); | |
1094 | $this->type("length_{$i}", ''); | |
1095 | $this->type("weight_{$i}", ''); | |
1096 | } | |
1097 | ||
1098 | $this->type('threshold', $threshold); | |
1099 | ||
1100 | // click save | |
1101 | $this->click('_qf_DedupeRules_next-bottom'); | |
1102 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1103 | } | |
1104 | ||
1105 | function webtestAddMembershipType($period_type = 'rolling', $duration_interval = 1, $duration_unit = 'year', $auto_renew = 'no') { | |
1106 | $membershipTitle = substr(sha1(rand()), 0, 7); | |
1107 | $membershipOrg = $membershipTitle . ' memorg'; | |
1108 | $this->webtestAddOrganization($membershipOrg, TRUE); | |
1109 | ||
1110 | $title = 'Membership Type ' . substr(sha1(rand()), 0, 7); | |
1111 | $memTypeParams = array( | |
1112 | 'membership_type' => $title, | |
1113 | 'member_of_contact' => $membershipOrg, | |
1114 | 'financial_type' => 2, | |
1115 | 'period_type' => $period_type, | |
1116 | ); | |
1117 | ||
1118 | $this->open($this->sboxPath . 'civicrm/admin/member/membershipType/add?action=add&reset=1'); | |
1119 | $this->waitForElementPresent('_qf_MembershipType_cancel-bottom'); | |
1120 | ||
1121 | $this->type('name', $memTypeParams['membership_type']); | |
1122 | ||
1123 | // if auto_renew optional or required - a valid payment processor must be created first (e.g Auth.net) | |
1124 | // select the radio first since the element id changes after membership org search results are loaded | |
1125 | switch ($auto_renew) { | |
1126 | case 'optional': | |
1127 | $this->click("xpath=//div[@id='membership_type_form']//table/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'Give option, but not required')]"); | |
1128 | break; | |
1129 | ||
1130 | case 'required': | |
1131 | $this->click("xpath=//div[@id='membership_type_form']//table/tbody/tr[6]/td/label[contains(text(), 'Auto-renew Option')]/../../td[2]/label[contains(text(), 'Auto-renew required')]"); | |
1132 | break; | |
1133 | ||
1134 | default: | |
1135 | //check if for the element presence (the Auto renew options can be absent when proper payment processor not configured) | |
1136 | 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')]")) { | |
1137 | $this->click("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')]"); | |
1138 | } | |
1139 | break; | |
1140 | } | |
1141 | ||
1142 | $this->type('member_of_contact', $membershipTitle); | |
1143 | $this->click('member_of_contact'); | |
1144 | $this->waitForElementPresent("css=div.ac_results-inner li"); | |
1145 | $this->click("css=div.ac_results-inner li"); | |
1146 | ||
1147 | $this->type('minimum_fee', '100'); | |
1148 | $this->select('financial_type_id', "value={$memTypeParams['financial_type']}"); | |
1149 | ||
1150 | $this->type('duration_interval', $duration_interval); | |
1151 | $this->select('duration_unit', "label={$duration_unit}"); | |
1152 | ||
1153 | $this->select('period_type', "label={$period_type}"); | |
1154 | ||
1155 | $this->click('_qf_MembershipType_upload-bottom'); | |
1156 | $this->waitForElementPresent('link=Add Membership Type'); | |
1157 | $this->assertTrue($this->isTextPresent("The membership type '$title' has been saved.")); | |
1158 | ||
1159 | return $memTypeParams; | |
1160 | } | |
1161 | ||
1162 | function WebtestAddGroup($groupName = NULL, $parentGroupName = NULL) { | |
1163 | $this->openCiviPage('group/add', 'reset=1', '_qf_Edit_upload-bottom'); | |
1164 | ||
1165 | // fill group name | |
1166 | if (!$groupName) { | |
1167 | $groupName = 'group_' . substr(sha1(rand()), 0, 7); | |
1168 | } | |
1169 | $this->type('title', $groupName); | |
1170 | ||
1171 | // fill description | |
1172 | $this->type('description', 'Adding new group.'); | |
1173 | ||
1174 | // check Access Control | |
1175 | $this->click('group_type[1]'); | |
1176 | ||
1177 | // check Mailing List | |
1178 | $this->click('group_type[2]'); | |
1179 | ||
1180 | // select Visibility as Public Pages | |
1181 | $this->select('visibility', 'value=Public Pages'); | |
1182 | ||
1183 | // select parent group | |
1184 | if ($parentGroupName) { | |
1185 | $this->select('parents', "*$parentGroupName"); | |
1186 | } | |
1187 | ||
1188 | // Clicking save. | |
1189 | $this->click('_qf_Edit_upload-bottom'); | |
1190 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1191 | ||
1192 | // Is status message correct? | |
1193 | $this->assertElementContainsText('crm-notification-container', "$groupName"); | |
1194 | return $groupName; | |
1195 | } | |
1196 | ||
1197 | function WebtestAddActivity($activityType = "Meeting") { | |
1198 | // Adding Adding contact with randomized first name for test testContactContextActivityAdd | |
1199 | // We're using Quick Add block on the main page for this. | |
1200 | $firstName1 = substr(sha1(rand()), 0, 7); | |
1201 | $this->webtestAddContact($firstName1, "Summerson", $firstName1 . "@summerson.name"); | |
1202 | $firstName2 = substr(sha1(rand()), 0, 7); | |
1203 | $this->webtestAddContact($firstName2, "Anderson", $firstName2 . "@anderson.name"); | |
1204 | ||
1205 | // Go directly to the URL of the screen that you will be testing (Activity Tab). | |
1206 | $this->click("css=li#tab_activity a"); | |
1207 | ||
1208 | // waiting for the activity dropdown to show up | |
1209 | $this->waitForElementPresent("other_activity"); | |
1210 | ||
1211 | // Select the activity type from the activity dropdown | |
1212 | $this->select("other_activity", "label=Meeting"); | |
1213 | ||
1214 | $this->waitForElementPresent("_qf_Activity_upload-bottom"); | |
1215 | ||
1216 | $this->assertTrue($this->isTextPresent("Anderson, " . $firstName2), "Contact not found in line " . __LINE__); | |
1217 | ||
1218 | // Typing contact's name into the field (using typeKeys(), not type()!)... | |
1219 | $this->click("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id"); | |
1220 | $this->type("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id", $firstName1); | |
1221 | $this->typeKeys("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id", $firstName1); | |
1222 | ||
1223 | // ...waiting for drop down with results to show up... | |
1224 | $this->waitForElementPresent("css=div.token-input-dropdown-facebook"); | |
1225 | $this->waitForElementPresent("css=li.token-input-input-token-facebook"); | |
1226 | ||
1227 | //.need to use mouseDown on first result (which is a li element), click does not work | |
1228 | // Note that if you are using firebug this appears at the bottom of the html source, before the closing </body> tag, not where the <li> referred to above is, which is a different <li>. | |
1229 | $this->waitForElementPresent("css=div.token-input-dropdown-facebook li"); | |
1230 | $this->mouseDown("css=div.token-input-dropdown-facebook li"); | |
1231 | ||
1232 | // ...again, waiting for the box with contact name to show up... | |
1233 | $this->waitForElementPresent("css=tr.crm-activity-form-block-assignee_contact_id td ul li span.token-input-delete-token-facebook"); | |
1234 | ||
1235 | // ...and verifying if the page contains properly formatted display name for chosen contact. | |
1236 | $this->assertTrue($this->isTextPresent("Summerson, " . $firstName1), "Contact not found in line " . __LINE__); | |
1237 | ||
1238 | // Putting the contents into subject field - assigning the text to variable, it'll come in handy later | |
1239 | $subject = "This is subject of test activity being added through activity tab of contact summary screen."; | |
1240 | // For simple input fields we can use field id as selector | |
1241 | $this->type("subject", $subject); | |
1242 | $this->type("location", "Some location needs to be put in this field."); | |
1243 | ||
1244 | $this->webtestFillDateTime('activity_date_time', '+1 month 11:10PM'); | |
1245 | ||
1246 | // Setting duration. | |
1247 | $this->type("duration", "30"); | |
1248 | ||
1249 | // Putting in details. | |
1250 | $this->type("details", "Really brief details information."); | |
1251 | ||
1252 | // Making sure that status is set to Scheduled (using value, not label). | |
1253 | $this->select("status_id", "value=1"); | |
1254 | ||
1255 | // Setting priority. | |
1256 | $this->select("priority_id", "value=1"); | |
1257 | ||
1258 | // Scheduling follow-up. | |
1259 | $this->click("css=.crm-activity-form-block-schedule_followup div.crm-accordion-header"); | |
1260 | $this->select("followup_activity_type_id", "value=1"); | |
1261 | $this->webtestFillDateTime('followup_date', '+2 month 11:10PM'); | |
1262 | $this->type("followup_activity_subject", "This is subject of schedule follow-up activity"); | |
1263 | ||
1264 | // Clicking save. | |
1265 | $this->click("_qf_Activity_upload-bottom"); | |
1266 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1267 | ||
1268 | // Is status message correct? | |
1269 | $this->assertTrue($this->isTextPresent("Activity '$subject' has been saved."), "Status message didn't show up after saving!"); | |
1270 | ||
1271 | $this->waitForElementPresent("xpath=//div[@id='Activities']//table/tbody/tr[2]/td[9]/span/a[text()='View']"); | |
1272 | ||
1273 | // click through to the Activity view screen | |
1274 | $this->click("xpath=//div[@id='Activities']//table/tbody/tr[2]/td[9]/span/a[text()='View']"); | |
1275 | $this->waitForElementPresent('_qf_Activity_cancel-bottom'); | |
1276 | $elements = $this->parseURL(); | |
1277 | $activityID = $elements['queryString']['id']; | |
1278 | return $activityID; | |
1279 | } | |
1280 | ||
1281 | static | |
1282 | function checkDoLocalDBTest() { | |
1283 | if (defined('CIVICRM_WEBTEST_LOCAL_DB') && | |
1284 | CIVICRM_WEBTEST_LOCAL_DB | |
1285 | ) { | |
1286 | require_once 'tests/phpunit/CiviTest/CiviDBAssert.php'; | |
1287 | return TRUE; | |
1288 | } | |
1289 | return FALSE; | |
1290 | } | |
1291 | ||
1292 | /** | |
1293 | * Generic function to compare expected values after an api call to retrieved | |
1294 | * DB values. | |
1295 | * | |
1296 | * @daoName string DAO Name of object we're evaluating. | |
1297 | * @id int Id of object | |
1298 | * @match array Associative array of field name => expected value. Empty if asserting | |
1299 | * that a DELETE occurred | |
1300 | * @delete boolean True if we're checking that a DELETE action occurred. | |
1301 | */ | |
1302 | function assertDBState($daoName, $id, $match, $delete = FALSE) { | |
1303 | if (!self::checkDoLocalDBTest()) { | |
1304 | return; | |
1305 | } | |
1306 | ||
1307 | return CiviDBAssert::assertDBState($this, $daoName, $id, $match, $delete); | |
1308 | } | |
1309 | ||
1310 | // Request a record from the DB by seachColumn+searchValue. Success if a record is found. | |
1311 | function assertDBNotNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) { | |
1312 | if (!self::checkDoLocalDBTest()) { | |
1313 | return; | |
1314 | } | |
1315 | ||
1316 | return CiviDBAssert::assertDBNotNull($this, $daoName, $searchValue, $returnColumn, $searchColumn, $message); | |
1317 | } | |
1318 | ||
1319 | // Request a record from the DB by seachColumn+searchValue. Success if returnColumn value is NULL. | |
1320 | function assertDBNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) { | |
1321 | if (!self::checkDoLocalDBTest()) { | |
1322 | return; | |
1323 | } | |
1324 | ||
1325 | return CiviDBAssert::assertDBNull($this, $daoName, $searchValue, $returnColumn, $searchColumn, $message); | |
1326 | } | |
1327 | ||
1328 | // Request a record from the DB by id. Success if row not found. | |
1329 | function assertDBRowNotExist($daoName, $id, $message) { | |
1330 | if (!self::checkDoLocalDBTest()) { | |
1331 | return; | |
1332 | } | |
1333 | ||
1334 | return CiviDBAssert::assertDBRowNotExist($this, $daoName, $id, $message); | |
1335 | } | |
1336 | ||
1337 | // Compare a single column value in a retrieved DB record to an expected value | |
1338 | function assertDBCompareValue($daoName, $searchValue, $returnColumn, $searchColumn, | |
1339 | $expectedValue, $message | |
1340 | ) { | |
1341 | if (!self::checkDoLocalDBTest()) { | |
1342 | return; | |
1343 | } | |
1344 | ||
1345 | return CiviDBAssert::assertDBCompareValue($daoName, $searchValue, $returnColumn, $searchColumn, | |
1346 | $expectedValue, $message | |
1347 | ); | |
1348 | } | |
1349 | ||
1350 | // Compare all values in a single retrieved DB record to an array of expected values | |
1351 | function assertDBCompareValues($daoName, $searchParams, $expectedValues) { | |
1352 | if (!self::checkDoLocalDBTest()) { | |
1353 | return; | |
1354 | } | |
1355 | ||
1356 | return CiviDBAssert::assertDBCompareValues($this, $daoName, $searchParams, $expectedValues); | |
1357 | } | |
1358 | ||
1359 | function assertAttributesEquals(&$expectedValues, &$actualValues) { | |
1360 | if (!self::checkDoLocalDBTest()) { | |
1361 | return; | |
1362 | } | |
1363 | ||
1364 | return CiviDBAssert::assertAttributesEquals($expectedValues, $actualValues); | |
1365 | } | |
1366 | ||
1367 | function assertType($expected, $actual, $message = '') { | |
1368 | return $this->assertInternalType($expected, $actual, $message); | |
1369 | } | |
1370 | ||
1371 | function changeAdminLinks() { | |
1372 | $version = 7; | |
1373 | if ($version == 7) { | |
1374 | $this->open("{$this->sboxPath}admin/people/permissions"); | |
1375 | } | |
1376 | else { | |
1377 | $this->open("{$this->sboxPath}admin/user/permissions"); | |
1378 | } | |
1379 | } | |
1380 | ||
1381 | ||
1382 | /** | |
1383 | * Add new Financial Account | |
1384 | */ | |
1385 | ||
1386 | function _testAddFinancialAccount($financialAccountTitle, | |
1387 | $financialAccountDescription = FALSE, | |
1388 | $accountingCode = FALSE, | |
1389 | $firstName = FALSE, | |
1390 | $financialAccountType = FALSE, | |
1391 | $taxDeductible = FALSE, | |
1392 | $isActive = FALSE, | |
1393 | $isTax = FALSE, | |
1394 | $taxRate = FALSE, | |
1395 | $isDefault = FALSE | |
1396 | ) { | |
1397 | ||
1398 | // Go directly to the URL | |
1399 | $this->open($this->sboxPath . "civicrm/admin/financial/financialAccount?reset=1"); | |
1400 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1401 | ||
1402 | $this->click("link=Add Financial Account"); | |
1403 | $this->waitForElementPresent('_qf_FinancialAccount_cancel-botttom'); | |
1404 | ||
1405 | // Financial Account Name | |
1406 | $this->type('name', $financialAccountTitle); | |
1407 | ||
1408 | // Financial Description | |
1409 | if ($financialAccountDescription) { | |
1410 | $this->type('description', $financialAccountDescription); | |
1411 | } | |
1412 | ||
1413 | //Accounting Code | |
1414 | if ($accountingCode) { | |
1415 | $this->type('accounting_code', $accountingCode); | |
1416 | } | |
1417 | ||
1418 | // Autofill Organization | |
1419 | if ($firstName) { | |
1420 | $this->webtestOrganisationAutocomplete($firstName); | |
1421 | } | |
1422 | ||
1423 | // Financial Account Type | |
1424 | if ($financialAccountType) { | |
1425 | $this->select('financial_account_type_id', "label={$financialAccountType}"); | |
1426 | } | |
1427 | ||
1428 | // Is Tax Deductible | |
1429 | if ($taxDeductible) { | |
1430 | $this->check('is_deductible'); | |
1431 | } | |
1432 | else { | |
1433 | $this->uncheck('is_deductible'); | |
1434 | } | |
1435 | // Is Active | |
1436 | if (!$isActive) { | |
1437 | $this->check('is_active'); | |
1438 | } | |
1439 | else { | |
1440 | $this->uncheck('is_active'); | |
1441 | } | |
1442 | // Is Tax | |
1443 | if ($isTax) { | |
1444 | $this->check('is_tax'); | |
1445 | } | |
1446 | else { | |
1447 | $this->uncheck('is_tax'); | |
1448 | } | |
1449 | // Tax Rate | |
1450 | if ($taxRate) { | |
1451 | $this->type('tax_rate', $taxRate); | |
1452 | } | |
1453 | ||
1454 | // Set Default | |
1455 | if ($isDefault) { | |
1456 | $this->check('is_default'); | |
1457 | } | |
1458 | else { | |
1459 | $this->uncheck('is_default'); | |
1460 | } | |
1461 | $this->click('_qf_FinancialAccount_next-botttom'); | |
1462 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1463 | } | |
1464 | ||
1465 | ||
1466 | /** | |
1467 | * Edit Financial Account | |
1468 | */ | |
1469 | function _testEditFinancialAccount($editfinancialAccount, | |
1470 | $financialAccountTitle = FALSE, | |
1471 | $financialAccountDescription = FALSE, | |
1472 | $accountingCode = FALSE, | |
1473 | $firstName = FALSE, | |
1474 | $financialAccountType = FALSE, | |
1475 | $taxDeductible = FALSE, | |
1476 | $isActive = TRUE, | |
1477 | $isTax = FALSE, | |
1478 | $taxRate = FALSE, | |
1479 | $isDefault = FALSE | |
1480 | ) { | |
1481 | if ($firstName) { | |
1482 | $this->open($this->sboxPath . "civicrm/admin/financial/financialAccount?reset=1"); | |
1483 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1484 | } | |
1485 | ||
1486 | $this->waitForElementPresent("xpath=//table/tbody//tr/td[1][text()='{$editfinancialAccount}']/../td[9]/span/a[text()='Edit']"); | |
1487 | $this->click("xpath=//table/tbody//tr/td[1][text()='{$editfinancialAccount}']/../td[9]/span/a[text()='Edit']"); | |
1488 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1489 | ||
1490 | $this->waitForElementPresent('_qf_FinancialAccount_cancel-botttom'); | |
1491 | ||
1492 | // Change Financial Account Name | |
1493 | if ($financialAccountTitle) { | |
1494 | $this->type('name', $financialAccountTitle); | |
1495 | } | |
1496 | ||
1497 | // Financial Description | |
1498 | if ($financialAccountDescription) { | |
1499 | $this->type('description', $financialAccountDescription); | |
1500 | } | |
1501 | ||
1502 | //Accounting Code | |
1503 | if ($accountingCode) { | |
1504 | $this->type('accounting_code', $accountingCode); | |
1505 | } | |
1506 | ||
1507 | ||
1508 | // Autofill Edit Organization | |
1509 | if ($firstName) { | |
1510 | $this->webtestOrganisationAutocomplete($firstName); | |
1511 | } | |
1512 | ||
1513 | // Financial Account Type | |
1514 | if ($financialAccountType) { | |
1515 | $this->select('financial_account_type_id', "label={$financialAccountType}"); | |
1516 | } | |
1517 | ||
1518 | // Is Tax Deductible | |
1519 | if ($taxDeductible) { | |
1520 | $this->check('is_deductible'); | |
1521 | } | |
1522 | else { | |
1523 | $this->uncheck('is_deductible'); | |
1524 | } | |
1525 | ||
1526 | // Is Tax | |
1527 | if ($isTax) { | |
1528 | $this->check('is_tax'); | |
1529 | } | |
1530 | else { | |
1531 | $this->uncheck('is_tax'); | |
1532 | } | |
1533 | ||
1534 | // Tax Rate | |
1535 | if ($taxRate) { | |
1536 | $this->type('tax_rate', $taxRate); | |
1537 | } | |
1538 | ||
1539 | // Set Default | |
1540 | if ($isDefault) { | |
1541 | $this->check('is_default'); | |
1542 | } | |
1543 | else { | |
1544 | $this->uncheck('is_default'); | |
1545 | } | |
1546 | ||
1547 | // Is Active | |
1548 | if ($isActive) { | |
1549 | $this->check('is_active'); | |
1550 | } | |
1551 | else { | |
1552 | $this->uncheck('is_active'); | |
1553 | } | |
1554 | $this->click('_qf_FinancialAccount_next-botttom'); | |
1555 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1556 | } | |
1557 | ||
1558 | ||
1559 | /** | |
1560 | * Delete Financial Account | |
1561 | */ | |
1562 | function _testDeleteFinancialAccount($financialAccountTitle) { | |
1563 | $this->click("xpath=//table/tbody//tr/td[1][text()='{$financialAccountTitle}']/../td[9]/span/a[text()='Delete']"); | |
1564 | $this->waitForElementPresent('_qf_FinancialAccount_next-botttom'); | |
1565 | $this->click('_qf_FinancialAccount_next-botttom'); | |
1566 | $this->waitForElementPresent('link=Add Financial Account'); | |
1567 | $this->assertTrue($this->isTextPresent("Selected Financial Account has been deleted.")); | |
1568 | } | |
1569 | ||
1570 | /** | |
1571 | * Verify data after ADD and EDIT | |
1572 | */ | |
1573 | function _assertFinancialAccount($verifyData) { | |
1574 | foreach ($verifyData as $key => $expectedValue) { | |
1575 | $actualValue = $this->getValue($key); | |
1576 | if ($key == 'parent_financial_account') { | |
1577 | $this->assertTrue((bool) preg_match("/^{$expectedValue}/", $actualValue)); | |
1578 | } | |
1579 | else { | |
1580 | $this->assertEquals($expectedValue, $actualValue); | |
1581 | } | |
1582 | } | |
1583 | } | |
1584 | ||
1585 | function _assertSelectVerify($verifySelectFieldData) { | |
1586 | foreach ($verifySelectFieldData as $key => $expectedvalue) { | |
1587 | $actualvalue = $this->getSelectedLabel($key); | |
1588 | $this->assertEquals($expectedvalue, $actualvalue); | |
1589 | } | |
1590 | } | |
1591 | ||
1592 | function addeditFinancialType($financialType, $option = 'new') { | |
1593 | $this->open($this->sboxPath . 'civicrm/admin/financial/financialType?reset=1'); | |
1594 | ||
1595 | if ($option == 'Delete') { | |
1596 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1][text()='$financialType[name]']/../td[7]/span[2]"); | |
1597 | $this->waitForElementPresent("css=span.btn-slide-active"); | |
1598 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1][text()='$financialType[name]']/../td[7]/span[2]/ul/li[2]/a"); | |
1599 | $this->waitForElementPresent("_qf_FinancialType_next"); | |
1600 | $this->click("_qf_FinancialType_next"); | |
1601 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1602 | $this->assertTrue($this->isTextPresent('Selected financial type has been deleted.'), 'Missing text: ' . 'Selected financial type has been deleted.'); | |
1603 | return; | |
1604 | } | |
1605 | if ($option == 'new') { | |
1606 | $this->click("link=Add Financial Type"); | |
1607 | } | |
1608 | else { | |
1609 | $this->click("xpath=id('ltype')/div/table/tbody/tr/td[1][text()='$financialType[oldname]']/../td[7]/span/a[text()='Edit']"); | |
1610 | } | |
1611 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1612 | $this->type('name', $financialType['name']); | |
1613 | if ($option == 'new') { | |
1614 | $this->type('description', $financialType['name'] . ' description'); | |
1615 | } | |
1616 | ||
1617 | if ($financialType['is_reserved']) { | |
1618 | $this->check('is_reserved'); | |
1619 | } | |
1620 | else { | |
1621 | $this->uncheck('is_reserved'); | |
1622 | } | |
1623 | ||
1624 | if ($financialType['is_deductible']) { | |
1625 | $this->check('is_deductible'); | |
1626 | } | |
1627 | else { | |
1628 | $this->uncheck('is_deductible'); | |
1629 | } | |
1630 | ||
1631 | $this->click('_qf_FinancialType_next'); | |
1632 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1633 | if ($option == 'new') { | |
1634 | $text = "The financial type '{$financialType['name']}' has been added. You can add Financial Accounts to this Financial Type now."; | |
1635 | } | |
1636 | else { | |
1637 | $text = "The financial type '{$financialType['name']}' has been saved."; | |
1638 | } | |
1639 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1640 | } | |
1641 | ||
1642 | ||
1643 | function changePermissions($permission) { | |
1644 | $this->open($this->sboxPath . "civicrm/logout?reset=1"); | |
1645 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1646 | $this->webtestLogin(TRUE); | |
1647 | $this->changeAdminLinks(); | |
1648 | $this->waitForElementPresent('edit-submit'); | |
0bd37c06 | 1649 | foreach ((array) $permission as $key => $value) { |
6a488035 TO |
1650 | $this->check($value); |
1651 | } | |
1652 | $this->click('edit-submit'); | |
1653 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1654 | $this->assertTrue($this->isTextPresent('The changes have been saved.')); | |
1655 | $this->open($this->sboxPath . "user/logout"); | |
1656 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1657 | $this->webtestLogin(); | |
6a488035 TO |
1658 | } |
1659 | ||
1660 | function addProfile($profileTitle, $profileFields) { | |
1661 | // Go directly to the URL of the screen that you will be testing (New Profile). | |
1662 | $this->open($this->sboxPath . "civicrm/admin/uf/group?reset=1"); | |
1663 | ||
1664 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1665 | $this->click('link=Add Profile'); | |
1666 | ||
1667 | // Add membership custom data field to profile | |
1668 | $this->waitForElementPresent('_qf_Group_cancel-bottom'); | |
1669 | $this->type('title', $profileTitle); | |
1670 | $this->click('_qf_Group_next-bottom'); | |
1671 | ||
1672 | $this->waitForElementPresent('_qf_Field_cancel-bottom'); | |
1673 | //$this->assertTrue($this->isTextPresent("Your CiviCRM Profile '{$profileTitle}' has been added. You can add fields to this profile now.")); | |
1674 | ||
1675 | foreach ($profileFields as $field) { | |
1676 | $this->waitForElementPresent('field_name_0'); | |
1677 | // $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1678 | $this->click("id=field_name_0"); | |
1679 | $this->select("id=field_name_0", "label=" . $field['type']); | |
1680 | $this->waitForElementPresent('field_name_1'); | |
1681 | $this->click("id=field_name_1"); | |
1682 | $this->select("id=field_name_1", "label=" . $field['name']); | |
1683 | $this->waitForElementPresent('label'); | |
1684 | $this->type("id=label", $field['label']); | |
1685 | $this->click("id=_qf_Field_next_new-top"); | |
1686 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1687 | //$this->assertTrue($this->isTextPresent("Your CiviCRM Profile Field '" . $field['name'] . "' has been saved to '" . $profileTitle . "'. You can add another profile field.")); | |
1688 | } | |
1689 | } | |
1690 | ||
1691 | function _testAddFinancialType() { | |
1692 | // Add new Financial Account | |
1693 | $orgName = 'Alberta ' . substr(sha1(rand()), 0, 7); | |
1694 | $financialAccountTitle = 'Financial Account ' . substr(sha1(rand()), 0, 4); | |
1695 | $financialAccountDescription = "{$financialAccountTitle} Description"; | |
1696 | $accountingCode = 1033; | |
1697 | $financialAccountType = 'Revenue'; //Asset Revenue | |
1698 | $taxDeductible = FALSE; | |
1699 | $isActive = FALSE; | |
1700 | $isTax = TRUE; | |
1701 | $taxRate = 9.99999999; | |
1702 | $isDefault = FALSE; | |
1703 | ||
1704 | //Add new organisation | |
1705 | if ($orgName) { | |
1706 | $this->webtestAddOrganization($orgName); | |
1707 | } | |
1708 | ||
1709 | $this->_testAddFinancialAccount( | |
1710 | $financialAccountTitle, | |
1711 | $financialAccountDescription, | |
1712 | $accountingCode, | |
1713 | $orgName, | |
1714 | $financialAccountType, | |
1715 | $taxDeductible, | |
1716 | $isActive, | |
1717 | $isTax, | |
1718 | $taxRate, | |
1719 | $isDefault | |
1720 | ); | |
1721 | $this->waitForElementPresent("xpath=//table/tbody//tr/td[1][text()='{$financialAccountTitle}']/../td[8]/span/a[text()='Edit']"); | |
1722 | ||
1723 | //Add new Financial Type | |
1724 | $financialType['name'] = 'FinancialType ' . substr(sha1(rand()), 0, 4); | |
1725 | $financialType['is_deductible'] = TRUE; | |
1726 | $financialType['is_reserved'] = FALSE; | |
1727 | $this->addeditFinancialType($financialType); | |
1728 | ||
1729 | $accountRelationship = "Income Account is"; //Asset Account - of Income Account is | |
1730 | $expected[] = array( | |
1731 | 'financial_account' => $financialAccountTitle, | |
1732 | 'account_relationship' => $accountRelationship | |
1733 | ); | |
1734 | ||
1735 | $this->select('account_relationship', "label={$accountRelationship}"); | |
1736 | sleep(2); | |
1737 | $this->select('financial_account_id', "label={$financialAccountTitle}"); | |
1738 | $this->click('_qf_FinancialTypeAccount_next'); | |
1739 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1740 | $text = 'The financial type Account has been saved.'; | |
1741 | $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text); | |
1742 | return $financialType['name']; | |
1743 | } | |
1744 | ||
1745 | function addPremium($name, $sku, $amount, $price, $cost, $financialType) { | |
1746 | $this->waitForElementPresent("_qf_ManagePremiums_upload-bottom"); | |
1747 | $this->type("name", $name); | |
1748 | $this->type("sku", $sku); | |
1749 | $this->click("CIVICRM_QFID_noImage_16"); | |
1750 | $this->type("min_contribution", $amount); | |
1751 | $this->type("price", $price); | |
1752 | $this->type("cost", $cost); | |
1753 | if ($financialType) { | |
1754 | $this->select("financial_type_id", "label={$financialType}"); | |
1755 | } | |
1756 | $this->click("_qf_ManagePremiums_upload-bottom"); | |
1757 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1758 | } | |
1759 | ||
1760 | function addPaymentInstrument($label, $financialAccount) { | |
1761 | $this->open($this->sboxPath . "civicrm/admin/options/payment_instrument?group=payment_instrument&action=add&reset=1"); | |
1762 | $this->waitForElementPresent("_qf_Options_next-bottom"); | |
1763 | $this->type("label", $label); | |
1764 | $this->select("financial_account_id", "value=$financialAccount"); | |
1765 | $this->click("_qf_Options_next-bottom"); | |
1766 | $this->waitForPageToLoad($this->getTimeoutMsec()); | |
1767 | } | |
1768 | ||
1769 | /** | |
1770 | * Determine the default time-out in milliseconds. | |
1771 | * | |
1772 | * @return string, timeout expressed in milliseconds | |
1773 | */ | |
1774 | function getTimeoutMsec() { | |
1775 | // note: existing local versions of CiviSeleniumSettings may not declare $timeout, so use @ | |
1776 | $timeout = ($this->settings && @$this->settings->timeout) ? ($this->settings->timeout * 1000) : 30000; | |
1777 | return (string) $timeout; // don't know why, but all our old code used a string | |
1778 | } | |
1779 | } | |
1780 |