loggedInAs = NULL; require_once 'CiviSeleniumSettings.php'; $this->settings = new CiviSeleniumSettings(); if (property_exists($this->settings, 'serverStartupTimeOut') && $this->settings->serverStartupTimeOut) { global $CiviSeleniumTestCase_polled; if (!$CiviSeleniumTestCase_polled) { $CiviSeleniumTestCase_polled = TRUE; CRM_Utils_Network::waitForServiceStartup( $this->drivers[0]->getHost(), $this->drivers[0]->getPort(), $this->settings->serverStartupTimeOut ); } } // autoload require_once 'CRM/Core/ClassLoader.php'; CRM_Core_ClassLoader::singleton()->register(); // also initialize a connection to the db // FIXME: not necessary for most tests, consider moving into functions that need this $config = CRM_Core_Config::singleton(); } protected function setUp() { $this->setBrowser($this->settings->browser); // Make sure that below strings have path separator at the end $this->setBrowserUrl($this->settings->sandboxURL); $this->sboxPath = $this->settings->sandboxPATH; if (property_exists($this->settings, 'rcHost') && $this->settings->rcHost) { $this->setHost($this->settings->rcHost); } if (property_exists($this->settings, 'rcPort') && $this->settings->rcPort) { $this->setPort($this->settings->rcPort); } $this->settingCache = array(); } /** * @return string */ 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() { } /** * Authenticate as drupal user. * @param $user : (str) the key 'user' or 'admin', or a literal username * @param $pass : (str) if $user is a literal username and not 'user' or 'admin', supply the password */ public function webtestLogin($user = 'user', $pass = NULL) { // If already logged in as correct user, do nothing if ($this->loggedInAs === $user) { return; } // If we are logged in as a different user, log out first if ($this->loggedInAs) { $this->webtestLogout(); } $this->open("{$this->sboxPath}user"); // Lookup username & password if not supplied $username = $user; if ($pass === NULL) { $pass = $user == 'admin' ? $this->settings->adminPassword : $this->settings->password; $username = $user == 'admin' ? $this->settings->adminUsername : $this->settings->username; } // Make sure login form is available $this->waitForElementPresent('edit-submit'); $this->type('edit-name', $username); $this->type('edit-pass', $pass); $this->click('edit-submit'); $this->waitForPageToLoad($this->getTimeoutMsec()); $this->loggedInAs = $user; } public function webtestLogout() { if ($this->loggedInAs) { $this->open($this->sboxPath . "user/logout"); $this->waitForPageToLoad($this->getTimeoutMsec()); } $this->loggedInAs = NULL; } /** * Open an internal path beginning with 'civicrm/' * * @param string $url * omit the 'civicrm/' it will be added for you. * @param string|array $args * optional url arguments. * @param $waitFor * Page element to wait for - using this is recommended to ensure the document is fully loaded. * * Although it doesn't seem to do much now, using this function is recommended for * opening all civi pages, and using the $args param is also strongly encouraged * This will make it much easier to run webtests in other CMSs in the future */ public function openCiviPage($url, $args = NULL, $waitFor = 'civicrm-footer') { // Construct full url with args // This could be extended in future to work with other CMS style urls if ($args) { if (is_array($args)) { $sep = '?'; foreach ($args as $key => $val) { $url .= $sep . $key . '=' . $val; $sep = '&'; } } else { $url .= "?$args"; } } $this->open("{$this->sboxPath}civicrm/$url"); $this->waitForPageToLoad($this->getTimeoutMsec()); $this->checkForErrorsOnPage(); if ($waitFor) { $this->waitForElementPresent($waitFor); } } /** * Click on a link or button. * Wait for the page to load * Wait for an element to be present * @param $element * @param string $waitFor * @param bool $waitForPageLoad */ public function clickLink($element, $waitFor = 'civicrm-footer', $waitForPageLoad = TRUE) { $this->click($element); // conditional wait for page load e.g for ajax form save if ($waitForPageLoad) { $this->waitForPageToLoad($this->getTimeoutMsec()); $this->checkForErrorsOnPage(); } if ($waitFor) { $this->waitForElementPresent($waitFor); } } /** * Click a link or button and wait for an ajax dialog to load. * @param string $element * @param string $waitFor */ public function clickPopupLink($element, $waitFor = NULL) { $this->clickAjaxLink($element, 'css=.ui-dialog'); if ($waitFor) { $this->waitForElementPresent($waitFor); } } /** * Click a link or button and wait for ajax content to load or refresh. * @param string $element * @param string $waitFor */ public function clickAjaxLink($element, $waitFor = NULL) { $this->click($element); if ($waitFor) { $this->waitForElementPresent($waitFor); } $this->waitForAjaxContent(); } /** * Force a link to open full-page, even if it would normally open in a popup * @note: works with links only, not buttons * @param string $element * @param string $waitFor */ public function clickLinkSuppressPopup($element, $waitFor = 'civicrm-footer') { $link = $this->getAttribute($element . '@href'); $this->open($link); $this->waitForPageToLoad($this->getTimeoutMsec()); if ($waitFor) { $this->waitForElementPresent($waitFor); } } /** * Wait for all ajax snippets to finish loading. */ public function waitForAjaxContent() { $this->waitForElementNotPresent('css=.blockOverlay'); // Some ajax calls happen in pairs (e.g. submit a popup form then refresh the underlying content) // So we'll wait a sec and recheck to see if any more stuff is loading sleep(1); if ($this->isElementPresent('css=.blockOverlay')) { $this->waitForAjaxContent(); } } /** * Call the API on the local server. * (kind of defeats the point of a webtest - see CRM-11889) * @param $entity * @param $action * @param $params * @return array|int */ public function webtest_civicrm_api($entity, $action, $params) { if (!isset($params['version'])) { $params['version'] = 3; } $result = civicrm_api($entity, $action, $params); $this->assertAPISuccess($result); return $result; } /** * Call the API on the remote server using the AJAX endpoint. * * @see CRM-11889 * @param $entity * @param $action * @param array $params * @return mixed */ public function rest_civicrm_api($entity, $action, $params = array()) { $params += array( 'version' => 3, ); static $reqId = 0; $reqId++; $jsCmd = ' setTimeout(function(){ CRM.api3("@entity", "@action", @params).then(function(a){ cj("