*/
define('CIVICRM_SETTINGS_PATH', __DIR__ . '/civicrm.settings.dist.php');
define('CIVICRM_SETTINGS_LOCAL_PATH', __DIR__ . '/civicrm.settings.local.php');
+define('CIVICRM_WEBTEST', 1);
if (file_exists(CIVICRM_SETTINGS_LOCAL_PATH)) {
require_once CIVICRM_SETTINGS_LOCAL_PATH;
* of that class to decide how to set up the test.
*
* @param string $name
- * @param array $data
+ * @param array $data
* @param string $dataName
+ * @param array $browser
*/
function __construct($name = NULL, array$data = array(), $dataName = '', array$browser = array()) {
parent::__construct($name, $data, $dataName, $browser);
}
}
+ protected function prepareTestSession() {
+ $result = parent::prepareTestSession();
+
+ // Set any cookies required by local installation
+ // Note: considered doing this in setUp(), but the Selenium session wasn't yet initialized.
+ if (property_exists($this->settings, 'cookies')) {
+ // We don't really care about this page, but it seems we need
+ // to open a page before setting a cookie.
+ $this->open($this->sboxPath);
+ $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->setCookies($this->settings->cookies);
+ }
+ return $result;
+ }
+
+ /**
+ * @param array $cookies each item is an array with keys:
+ * - name: string
+ * - value: string; note that RFC's don't define particular encoding scheme, so
+ * you must pick one yourself and pre-encode; does not allow values with
+ * commas, semicolons, or whitespace
+ * - path: string; default: '/'
+ * - max_age: int; default: 1 week (7*24*60*60)
+ */
+ protected function setCookies($cookies) {
+ foreach ($cookies as $cookie) {
+ if (!isset($cookie['path'])) {
+ $cookie['path'] = '/';
+ }
+ if (!isset($cookie['max_age'])) {
+ $cookie['max_age'] = 7*24*60*60;
+ }
+ $this->deleteCookie($cookie['name'], $cookie['path']);
+ $optionExprs = array();
+ foreach ($cookie as $key => $value) {
+ if ($key != 'name' && $key != 'value') {
+ $optionExprs[] = "$key=$value";
+ }
+ }
+ $this->createCookie("{$cookie['name']}={$cookie['value']}", implode(', ', $optionExprs));
+ }
+ }
+
protected function tearDown() {
}
return json_decode($result, TRUE);
}
+ /**
+ * @param $option_group_name
+ *
+ * @return array|int
+ */
function webtestGetFirstValueForOptionGroup($option_group_name) {
$result = $this->webtest_civicrm_api("OptionValue", "getvalue", array(
'option_group_name' => $option_group_name,
return $result;
}
+ /**
+ * @return mixed
+ */
function webtestGetValidCountryID() {
static $_country_id;
if (is_null($_country_id)) {
return $_country_id;
}
+ /**
+ * @param $entity
+ *
+ * @return mixed|null
+ */
function webtestGetValidEntityID($entity) {
// michaelmcandrew: would like to use getvalue but there is a bug
// for e.g. group where option.limit not working at the moment CRM-9110
return NULL;
}
+ /**
+ * @param $field
+ *
+ * @return mixed
+ */
function webtestGetConfig($field) {
static $_config_backend;
if (is_null($_config_backend)) {
*
* @param string $fname contact’s first name
* @param string $lname contact’s last name
- * @param mixed $email contact’s email (when string) or random email (when true) or no email (when null)
+ * @param mixed $email contact’s email (when string) or random email (when true) or no email (when null)
+ *
+ * @param null $contactSubtype
*
* @return mixed either a string with the (either generated or provided) email or null (if no email)
*/
return $email;
}
+ /**
+ * @param string $householdName
+ * @param null $email
+ *
+ * @return null|string
+ */
function webtestAddHousehold($householdName = "Smith's Home", $email = NULL) {
$this->openCiviPage("contact/add", "reset=1&ct=Household");
return $email;
}
+ /**
+ * @param string $organizationName
+ * @param null $email
+ * @param null $contactSubtype
+ *
+ * @return null|string
+ */
function webtestAddOrganization($organizationName = "Organization XYZ", $email = NULL, $contactSubtype = NULL) {
$url = $this->sboxPath . 'civicrm/contact/add?reset=1&ct=Organization';
* webtestFillDate('start_date',"next Thursday")
* webtestFillDate('start_date',"last Monday")
*/
+ /**
+ * @param $dateElement
+ * @param null $strToTimeArgs
+ */
function webtestFillDate($dateElement, $strToTimeArgs = NULL) {
$timeStamp = strtotime($strToTimeArgs ? $strToTimeArgs : '+1 month');
}
// 1. set both date and time.
+ /**
+ * @param $dateElement
+ * @param null $strToTimeArgs
+ */
function webtestFillDateTime($dateElement, $strToTimeArgs = NULL) {
$this->webtestFillDate($dateElement, $strToTimeArgs);
*
* @return void
*/
- function fillRichTextField($fieldName, $text = 'Typing this text into editor.', $editor = 'CKEditor') {
+ function fillRichTextField($fieldName, $text = 'Typing this text into editor.', $editor = 'CKEditor', $compressed = FALSE) {
// make sure cursor focuses on the field
$this->fireEvent($fieldName, 'focus');
if ($editor == 'CKEditor') {
+ if ($compressed) {
+ $this->click("{$fieldName}-plain");
+ }
$this->waitForElementPresent("xpath=//div[@id='cke_{$fieldName}']//iframe");
$this->runScript("CKEDITOR.instances['{$fieldName}'].setData('<p>{$text}</p>');");
}
*
* @strings array array of strings or a single string
*
+ * @param $strings
* @return void
*/
function assertStringsPresent($strings) {
*
* @url string url to parse or retrieve current url if null
*
+ * @param null $url
* @return array returns an associative array containing any of the various components
* of the URL that are present. Querystring elements are returned in sub-array (elements.queryString)
* http://php.net/manual/en/function.parse-url.php
- *
*/
function parseURL($url = NULL) {
if (!$url) {
*
* @param string $processorName Name assigned to new processor
* @param string $processorType Name for processor type (e.g. PayPal, Dummy, etc.)
- * @param array $processorSettings Array of fieldname => value for required settings for the processor
+ * @param array $processorSettings Array of fieldname => value for required settings for the processor
*
+ * @param string $financialAccount
+ * @throws PHPUnit_Framework_AssertionFailedError
* @return void
*/
$this->select('credit_card_exp_date[Y]', 'label=2019');
}
+ /**
+ * @param null $firstName
+ * @param null $middleName
+ * @param null $lastName
+ *
+ * @return array
+ */
function webtestAddBillingDetails($firstName = NULL, $middleName = NULL, $lastName = NULL) {
if (!$firstName) {
$firstName = 'John';
$this->type('billing_street_address-5', '234 Lincoln Ave');
$this->type('billing_city-5', 'San Bernadino');
+ $this->select('billing_country_id-5', 'value=1228');
$this->click('billing_state_province_id-5');
$this->select('billing_state_province_id-5', 'label=California');
- $this->select('billing_country_id-5', 'value=1228');
$this->type('billing_postal_code-5', '93245');
return array($firstName, $middleName, $lastName);
}
+ /**
+ * @param $fieldLocator
+ * @param null $filePath
+ *
+ * @return null|string
+ */
function webtestAttachFile($fieldLocator, $filePath = NULL) {
if (!$filePath) {
$filePath = '/tmp/testfile_' . substr(sha1(rand()), 0, 7) . '.txt';
return $filePath;
}
+ /**
+ * @param $headers
+ * @param $rows
+ * @param null $filePath
+ *
+ * @return null|string
+ */
function webtestCreateCSV($headers, $rows, $filePath = NULL) {
if (!$filePath) {
$filePath = '/tmp/testcsv_' . substr(sha1(rand()), 0, 7) . '.csv';
* Create new online contribution page w/ user specified params or defaults.
* FIXME: this function take an absurd number of params - very unwieldy :(
*
- * @param User can define pageTitle, hash and rand values for later data verification
+ * @param null $hash
+ * @param null $rand
+ * @param null $pageTitle
+ * @param array $processor
+ * @param bool $amountSection
+ * @param bool $payLater
+ * @param bool $onBehalf
+ * @param bool $pledges
+ * @param bool $recurring
+ * @param bool $membershipTypes
+ * @param null $memPriceSetId
+ * @param bool $friend
+ * @param int $profilePreId
+ * @param int $profilePostId
+ * @param bool $premiums
+ * @param bool $widget
+ * @param bool $pcp
+ * @param bool $isAddPaymentProcessor
+ * @param bool $isPcpApprovalNeeded
+ * @param bool $isSeparatePayment
+ * @param bool $honoreeSection
+ * @param bool $allowOtherAmount
+ * @param bool $isConfirmEnabled
+ * @param string $financialType
+ * @param bool $fixedAmount
+ * @param bool $membershipsRequired
+ * @internal param \can $User define pageTitle, hash and rand values for later data verification
*
- * @return $pageId of newly created online contribution page.
+ * @return null $pageId of newly created online contribution page.
*/
function webtestAddContributionPage($hash = NULL,
$rand = NULL,
$isPcpApprovalNeeded = FALSE,
$isSeparatePayment = FALSE,
$honoreeSection = TRUE,
- $allowOtherAmmount = TRUE,
+ $allowOtherAmount = TRUE,
$isConfirmEnabled = TRUE,
$financialType = 'Donation',
$fixedAmount = TRUE,
if ($onBehalf) {
$this->click('is_organization');
- $this->select('onbehalf_profile_id', 'label=On Behalf Of Organization');
+ $this->select("xpath=//*[@class='crm-contribution-onbehalf_profile_id']//span[@class='crm-profile-selector-select']//select", 'label=On Behalf Of Organization');
$this->type('for_organization', "On behalf $hash");
if ($onBehalf == 'required') {
$this->click("is_recur_interval");
$this->click("is_recur_installments");
}
- if ($allowOtherAmmount) {
+ if ($allowOtherAmount) {
$this->click('is_allow_other_amount');
//$this->type('min_amount', $rand / 2);
//$this->type('max_amount', $rand * 10);
}
- if ($fixedAmount || !$allowOtherAmmount) {
+ if ($fixedAmount || !$allowOtherAmount) {
$this->type('label_1', "Label $hash");
$this->type('value_1', "$rand");
}
* Function to update default strict rule.
*
* @params string $contactType Contact type
- * @param array $fields Fields to be set for strict rule
- * @param Integer $threshold Rule's threshold value
+ * @param string $contactType
+ * @param array $fields Fields to be set for strict rule
+ * @param Integer $threshold Rule's threshold value
*/
function webtestStrictDedupeRuleDefault($contactType = 'Individual', $fields = array(), $threshold = 10) {
// set default strict rule.
$this->waitForPageToLoad($this->getTimeoutMsec());
}
+ /**
+ * @param string $period_type
+ * @param int $duration_interval
+ * @param string $duration_unit
+ * @param string $auto_renew
+ *
+ * @return array
+ */
function webtestAddMembershipType($period_type = 'rolling', $duration_interval = 1, $duration_unit = 'year', $auto_renew = 'no') {
$membershipTitle = substr(sha1(rand()), 0, 7);
$membershipOrg = $membershipTitle . ' memorg';
return $memTypeParams;
}
+ /**
+ * @param null $groupName
+ * @param null $parentGroupName
+ *
+ * @return null|string
+ */
function WebtestAddGroup($groupName = NULL, $parentGroupName = NULL) {
$this->openCiviPage('group/add', 'reset=1', '_qf_Edit_upload-bottom');
return $groupName;
}
+ /**
+ * @param string $activityType
+ *
+ * @return null
+ */
function WebtestAddActivity($activityType = "Meeting") {
// Adding Adding contact with randomized first name for test testContactContextActivityAdd
// We're using Quick Add block on the main page for this.
$this->select("other_activity", "label=Meeting");
$this->waitForElementPresent("_qf_Activity_upload-bottom");
+ $this->waitForElementPresent("s2id_target_contact_id");
$this->assertTrue($this->isTextPresent("Anderson, " . $firstName2), "Contact not found in line " . __LINE__);
// Typing contact's name into the field (using typeKeys(), not type()!)...
- $this->click("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id");
- $this->type("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id", $firstName1);
- $this->typeKeys("css=tr.crm-activity-form-block-assignee_contact_id input#token-input-assignee_contact_id", $firstName1);
-
- // ...waiting for drop down with results to show up...
- $this->waitForElementPresent("css=div.token-input-dropdown-facebook");
- $this->waitForElementPresent("css=li.token-input-input-token-facebook");
-
- //.need to use mouseDown on first result (which is a li element), click does not work
- // 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>.
- $this->waitForElementPresent("css=div.token-input-dropdown-facebook li");
- $this->mouseDown("css=div.token-input-dropdown-facebook li");
-
- // ...again, waiting for the box with contact name to show up...
- $this->waitForElementPresent("css=tr.crm-activity-form-block-assignee_contact_id td ul li span.token-input-delete-token-facebook");
+ $this->select2("assignee_contact_id", $firstName1, TRUE);
// ...and verifying if the page contains properly formatted display name for chosen contact.
$this->assertTrue($this->isTextPresent("Summerson, " . $firstName1), "Contact not found in line " . __LINE__);
// Clicking save.
$this->click("_qf_Activity_upload-bottom");
- $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->waitForElementPresent("xpath=//div[@id='crm-notification-container']");
// Is status message correct?
- $this->assertTrue($this->isTextPresent("Activity '$subject' has been saved."), "Status message didn't show up after saving!");
+ $this->waitForText('crm-notification-container', "Activity '$subject' has been saved.");
- $this->waitForElementPresent("xpath=//div[@id='Activities']//table/tbody/tr[2]/td[8]/span/a[text()='View']");
+ $this->waitForElementPresent("xpath=//div[@id='contact-activity-selector-activity_wrapper']//table/tbody/tr[2]/td[8]/span/a[text()='View']");
// click through to the Activity view screen
- $this->click("xpath=//div[@id='Activities']//table/tbody/tr[2]/td[8]/span/a[text()='View']");
+ $this->click("xpath=//div[@id='contact-activity-selector-activity_wrapper']//table/tbody/tr[2]/td[8]/span/a[text()='View']");
$this->waitForElementPresent('_qf_Activity_cancel-bottom');
// parse URL to grab the activity id
return $this->urlArg('id');
}
+ /**
+ * @return bool
+ */
static
function checkDoLocalDBTest() {
if (defined('CIVICRM_WEBTEST_LOCAL_DB') &&
}
// Request a record from the DB by seachColumn+searchValue. Success if a record is found.
+ /**
+ * @param $daoName
+ * @param $searchValue
+ * @param $returnColumn
+ * @param $searchColumn
+ * @param $message
+ *
+ * @return null|string
+ */
function assertDBNotNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) {
if (!self::checkDoLocalDBTest()) {
return;
}
// Request a record from the DB by seachColumn+searchValue. Success if returnColumn value is NULL.
+ /**
+ * @param $daoName
+ * @param $searchValue
+ * @param $returnColumn
+ * @param $searchColumn
+ * @param $message
+ */
function assertDBNull($daoName, $searchValue, $returnColumn, $searchColumn, $message) {
if (!self::checkDoLocalDBTest()) {
return;
}
// Request a record from the DB by id. Success if row not found.
+ /**
+ * @param $daoName
+ * @param $id
+ * @param $message
+ */
function assertDBRowNotExist($daoName, $id, $message) {
if (!self::checkDoLocalDBTest()) {
return;
}
// Compare a single column value in a retrieved DB record to an expected value
+ /**
+ * @param $daoName
+ * @param $searchValue
+ * @param $returnColumn
+ * @param $searchColumn
+ * @param $expectedValue
+ * @param string $message
+ */
function assertDBCompareValue($daoName, $searchValue, $returnColumn, $searchColumn,
$expectedValue, $message
) {
}
// Compare all values in a single retrieved DB record to an array of expected values
+ /**
+ * @param $daoName
+ * @param $searchParams
+ * @param $expectedValues
+ */
function assertDBCompareValues($daoName, $searchParams, $expectedValues) {
if (!self::checkDoLocalDBTest()) {
return;
return CiviDBAssert::assertDBCompareValues($this, $daoName, $searchParams, $expectedValues);
}
+ /**
+ * @param $expectedValues
+ * @param $actualValues
+ */
function assertAttributesEquals(&$expectedValues, &$actualValues) {
if (!self::checkDoLocalDBTest()) {
return;
return CiviDBAssert::assertAttributesEquals($expectedValues, $actualValues);
}
+ /**
+ * @param $expected
+ * @param $actual
+ * @param string $message
+ */
function assertType($expected, $actual, $message = '') {
return $this->assertInternalType($expected, $actual, $message);
}
}
}
+ /**
+ * @param $verifySelectFieldData
+ */
function _assertSelectVerify($verifySelectFieldData) {
foreach ($verifySelectFieldData as $key => $expectedvalue) {
$actualvalue = $this->getSelectedLabel($key);
}
}
+ /**
+ * @param $financialType
+ * @param string $option
+ */
function addeditFinancialType($financialType, $option = 'new') {
$this->openCiviPage("admin/financial/financialType", "reset=1");
$this->assertTrue($this->isTextPresent('The changes have been saved.'));
}
+ /**
+ * @param $profileTitle
+ * @param $profileFields
+ */
function addProfile($profileTitle, $profileFields) {
$this->openCiviPage('admin/uf/group', "reset=1");
}
}
+ /**
+ * @param $name
+ * @param $sku
+ * @param $amount
+ * @param $price
+ * @param $cost
+ * @param $financialType
+ */
function addPremium($name, $sku, $amount, $price, $cost, $financialType) {
$this->waitForElementPresent("_qf_ManagePremiums_upload-bottom");
$this->type("name", $name);
$this->waitForPageToLoad($this->getTimeoutMsec());
}
+ /**
+ * @param $label
+ * @param $financialAccount
+ */
function addPaymentInstrument($label, $financialAccount) {
$this->openCiviPage('admin/options/payment_instrument', 'action=add&reset=1', "_qf_Options_next-bottom");
$this->type("label", $label);
}
}
+ /**
+ * @param $customSets
+ *
+ * @return array
+ */
function addCustomGroupField($customSets) {
foreach ($customSets as $customSet) {
$this->openCiviPage("admin/custom/group", "action=add&reset=1");
$fieldLabel = "custom_field_for_{$customSet['entity']}_{$customSet['subEntity']}" . substr(sha1(rand()), 0, 4);
$this->type('label', $fieldLabel);
- $this->click('_qf_Field_next-bottom');
+ $this->click('_qf_Field_next_new-bottom');
$this->waitForPageToLoad($this->getTimeoutMsec());
$customGroupTitle = preg_replace('/\s/', '_', trim($customGroupTitle));
/**
* function to type and select first occurance of autocomplete
*/
- function select2($fieldName,$label, $multiple = FALSE) {
+ function select2($fieldName,$label, $multiple = FALSE, $xpath=FALSE) {
if ($multiple) {
- $this->clickAt("//*[@id='$fieldName']/../div/ul/li[1]");
- $this->keyDown("//*[@id='$fieldName']/../div/ul/li[1]/input", " ");
- $this->type("//*[@id='$fieldName']/../div/ul/li[1]/input", $label);
- $this->typeKeys("//*[@id='$fieldName']/../div/ul/li[1]/input", $label);
+ $this->clickAt("//*[@id='$fieldName']/../div/ul/li");
+ $this->keyDown("//*[@id='$fieldName']/../div/ul/li//input", " ");
+ $this->type("//*[@id='$fieldName']/../div/ul/li//input", $label);
+ $this->typeKeys("//*[@id='$fieldName']/../div/ul/li//input", $label);
$this->waitForElementPresent("//*[@class='select2-result-label']");
$this->clickAt("//*[@class='select2-results']/li[1]/div");
}
else {
- $this->clickAt("//*[@id='$fieldName']/../div/a");
+ if ($xpath)
+ $this->clickAt($fieldName);
+ else
+ $this->clickAt("//*[@id='$fieldName']/../div/a");
$this->waitForElementPresent("//*[@id='select2-drop']/div/input");
$this->keyDown("//*[@id='select2-drop']/div/input", " ");
$this->type("//*[@id='select2-drop']/div/input", $label);
$this->typeKeys("//*[@id='select2-drop']/div/input", $label);
$this->waitForElementPresent("//*[@class='select2-result-label']");
- $this->clickAt("//*[@class='select2-result-label']");
+ $this->clickAt("//*[contains(@class,'select2-result-selectable')]/div[contains(@class, 'select2-result-label')]");
+ }
+ }
+
+ /**
+ * function to select multiple options
+ */
+ function multiselect2($fieldid, $params) {
+ foreach($params as $value) {
+ $this->clickAt("xpath=//*[@id='$fieldid']/../div/ul//li/input");
+ $this->waitForElementPresent("xpath=//ul[@class='select2-results']");
+ $this->clickAt("xpath=//ul[@class='select2-results']//li/div[text()='$value']");
+ $this->waitForText("xpath=//*[@id='$fieldid']/../div", $value);
}
}
}