+--------------------------------------------------------------------+
*/
-
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
/**
*/
class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
- // protected $coverageScriptUrl = 'http://tests.dev.civicrm.org/drupal/phpunit_coverage.php';
+ // Current logged-in user
+ protected $loggedInAs = NULL;
/**
* Constructor
*/
function __construct($name = NULL, array$data = array(), $dataName = '', array$browser = array()) {
parent::__construct($name, $data, $dataName, $browser);
+ $this->loggedInAs = NULL;
require_once 'CiviSeleniumSettings.php';
$this->settings = new CiviSeleniumSettings();
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 tearDown() {
- // $this->open( $this->settings->sandboxPATH . "logout?reset=1");
}
/**
* Authenticate as drupal user
- * @param $admin: (bool) use admin user/pass instead of normal 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
*/
- function webtestLogin($admin = FALSE) {
+ 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");
- $password = $admin ? $this->settings->adminPassword : $this->settings->password;
- $username = $admin ? $this->settings->adminUsername : $this->settings->username;
+ // 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', $password);
+ $this->type('edit-pass', $pass);
$this->click('edit-submit');
$this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->loggedInAs = $user;
+ }
+
+ function webtestLogout() {
+ if ($this->loggedInAs) {
+ $this->open($this->sboxPath . "user/logout");
+ $this->waitForPageToLoad($this->getTimeoutMsec());
+ }
+ $this->loggedInAs = NULL;
}
/**
* 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
*/
- function openCiviPage($url, $args = NULL, $waitFor = NULL) {
+ 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) {
}
}
$this->open("{$this->sboxPath}civicrm/$url");
- $this->waitForPageToLoad();
+ $this->waitForPageToLoad($this->getTimeoutMsec());
+ if ($waitFor) {
+ $this->waitForElementPresent($waitFor);
+ }
+ }
+
+ /**
+ * Click on a link or button
+ * Wait for the page to load
+ * Wait for an element to be present
+ */
+ 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());
+ }
if ($waitFor) {
$this->waitForElementPresent($waitFor);
}
$added = FALSE;
foreach ((array) $components as $comp) {
if (!in_array($comp, $enabledComponents)) {
+ $this->addSelection("enableComponents-f", "label=$comp");
$this->click("//option[@value='$comp']");
$this->click("add");
$added = TRUE;
if ($added) {
$this->click("_qf_Component_next-bottom");
$this->waitForPageToLoad($this->getTimeoutMsec());
- $this->assertElementContainsText("crm-notification-container", "Saved");
+ $this->waitForText('crm-notification-container', "Saved");
}
}
function webtestAddHousehold($householdName = "Smith's Home", $email = NULL) {
- $this->open($this->sboxPath . 'civicrm/contact/add?reset=1&ct=Household');
+ $this->openCiviPage("contact/add", "reset=1&ct=Household");
$this->click('household_name');
$this->type('household_name', $householdName);
function webtestAddOrganization($organizationName = "Organization XYZ", $email = NULL) {
- $this->open($this->sboxPath . 'civicrm/contact/add?reset=1&ct=Organization');
+ $this->openCiviPage("contact/add", "reset=1&ct=Organization");
$this->click('organization_name');
$this->type('organization_name', $organizationName);
//$this->assertContains($sortName, $this->getValue('contact_1'), "autocomplete expected $sortName but didn’t find it in " . $this->getValue('contact_1'));
}
-
/*
* 1. By default, when no strtotime arg is specified, sets date to "now + 1 month"
* 2. Does not set time. For setting both date and time use webtestFillDateTime() method.
}
foreach ($expected as $label => $value) {
if ($xpathPrefix) {
- $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td{$xpathPrefix}[text()='{$label}']/../following-sibling::td", preg_quote($value));
+ $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td{$xpathPrefix}[text()='{$label}']/../following-sibling::td", preg_quote($value), 'In line ' . __LINE__);
}
else {
- $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td[text()='{$label}']/following-sibling::td", preg_quote($value));
+ $this->verifyText("xpath=//table{$tableLocator}/tbody/tr/td[text()='{$label}']/following-sibling::td", preg_quote($value), 'In line ' . __LINE__);
}
}
}
return $elements;
}
+ /**
+ * Returns a single argument from the url query
+ */
+ function urlArg($arg, $url = NULL) {
+ $elements = $this->parseURL($url);
+ return isset($elements['queryString'][$arg]) ? $elements['queryString'][$arg] : NULL;
+ }
+
/**
* Define a payment processor for use by a webtest. Default is to create Dummy processor
* which is useful for testing online public forms (online contribution pages and event registration)
* @return an array of saved params values.
*/
function webtestAddRelationshipType($params = array()) {
- $this->open($this->sboxPath . 'civicrm/admin/reltype?reset=1&action=add');
+ $this->openCiviPage("admin/reltype", "reset=1&action=add");
//build the params if not passed.
if (!is_array($params) || empty($params)) {
"Status message didn't show up after saving!"
);
- $this->open($this->sboxPath . 'civicrm/admin/reltype?reset=1');
- $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->openCiviPage("admin/reltype", "reset=1");
//validate data on selector.
$data = $params;
/**
* 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
*
$honoreeSection = TRUE,
$allowOtherAmmount = TRUE,
$isConfirmEnabled = TRUE,
- $financialType = 'Donation'
+ $financialType = 'Donation',
+ $fixedAmount = TRUE,
+ $membershipsRequired = TRUE
) {
if (!$hash) {
$hash = substr(sha1(rand()), 0, 7);
}
// go to the New Contribution Page page
- $this->open($this->sboxPath . 'civicrm/admin/contribute?action=add&reset=1');
- $this->waitForPageToLoad();
+ $this->openCiviPage('admin/contribute', 'action=add&reset=1');
// fill in step 1 (Title and Settings)
$this->type('title', $pageTitle);
$this->click("id=is_confirm_enabled");
}
- // go to step 2
- $this->click('_qf_Settings_next');
- $this->waitForElementPresent('_qf_Amount_next-bottom');
+ // Submit form
+ $this->clickLink('_qf_Settings_next', "_qf_Amount_next-bottom");
+
+ // Get contribution page id
+ $pageId = $this->urlArg('id');
// fill in step 2 (Processor, Pay Later, Amounts)
if (!empty($processor)) {
//$this->type('min_amount', $rand / 2);
//$this->type('max_amount', $rand * 10);
}
-
- $this->type('label_1', "Label $hash");
- $this->type('value_1', "$rand");
+ if ($fixedAmount || !$allowOtherAmmount) {
+ $this->type('label_1', "Label $hash");
+ $this->type('value_1', "$rand");
+ }
$this->click('CIVICRM_QFID_1_2');
}
else {
$this->select("auto_renew_{$mType['id']}", "label=Give option");
}
}
-
- $this->click('is_required');
+ if ($membershipsRequired) {
+ $this->click('is_required');
+ }
$this->waitForElementPresent('CIVICRM_QFID_2_4');
$this->click('CIVICRM_QFID_2_4');
if ($isSeparatePayment) {
$this->click('is_separate_payment');
}
}
- $this->click('_qf_MembershipBlock_next');
- $this->waitForPageToLoad($this->getTimeoutMsec());
- $this->waitForElementPresent('_qf_MembershipBlock_next-bottom');
+ $this->clickLink('_qf_MembershipBlock_next', '_qf_MembershipBlock_next-bottom');
$text = "'MembershipBlock' information has been saved.";
$this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text);
}
$this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text);
}
-
if ($widget) {
// fill in step 8 (Widget Settings)
$this->click('link=Widgets');
$this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text);
}
- // parse URL to grab the contribution page id
- $elements = $this->parseURL();
- $pageId = $elements['queryString']['id'];
-
- // pass $pageId back to any other tests that call this class
return $pageId;
}
}
}
- $this->open($this->sboxPath . 'civicrm/contact/deduperules?action=update&id=' . $strictRuleId);
- $this->waitForPageToLoad($this->getTimeoutMsec());
- $this->waitForElementPresent('_qf_DedupeRules_next-bottom');
+ $this->openCiviPage('contact/deduperules', "action=update&id=$strictRuleId", '_qf_DedupeRules_next-bottom');
$count = 0;
foreach ($fields as $field => $weight) {
'period_type' => $period_type,
);
- $this->open($this->sboxPath . 'civicrm/admin/member/membershipType/add?action=add&reset=1');
- $this->waitForElementPresent('_qf_MembershipType_cancel-bottom');
+ $this->openCiviPage("admin/member/membershipType/add", "action=add&reset=1", '_qf_MembershipType_cancel-bottom');
$this->type('name', $memTypeParams['membership_type']);
}
// Clicking save.
- $this->click('_qf_Edit_upload-bottom');
- $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->clickLink('_qf_Edit_upload-bottom');
// Is status message correct?
- $this->assertElementContainsText('crm-notification-container', "$groupName");
+ $this->waitForText('crm-notification-container', "$groupName");
return $groupName;
}
$firstName2 = substr(sha1(rand()), 0, 7);
$this->webtestAddContact($firstName2, "Anderson", $firstName2 . "@anderson.name");
- // Go directly to the URL of the screen that you will be testing (Activity Tab).
$this->click("css=li#tab_activity a");
// waiting for the activity dropdown to show up
// click through to the Activity view screen
$this->click("xpath=//div[@id='Activities']//table/tbody/tr[2]/td[9]/span/a[text()='View']");
$this->waitForElementPresent('_qf_Activity_cancel-bottom');
- $elements = $this->parseURL();
- $activityID = $elements['queryString']['id'];
- return $activityID;
+
+ // parse URL to grab the activity id
+ // pass id back to any other tests that call this class
+ return $this->urlArg('id');
}
static
return $this->assertInternalType($expected, $actual, $message);
}
- function changeAdminLinks() {
- $version = 7;
- if ($version == 7) {
- $this->open("{$this->sboxPath}admin/people/permissions");
- }
- else {
- $this->open("{$this->sboxPath}admin/user/permissions");
- }
- }
-
-
/**
* Add new Financial Account
*/
-
function _testAddFinancialAccount($financialAccountTitle,
$financialAccountDescription = FALSE,
$accountingCode = FALSE,
$isDefault = FALSE
) {
- // Go directly to the URL
- $this->open($this->sboxPath . "civicrm/admin/financial/financialAccount?reset=1");
- $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->openCiviPage("admin/financial/financialAccount", "reset=1");
$this->click("link=Add Financial Account");
$this->waitForElementPresent('_qf_FinancialAccount_cancel-botttom');
$this->waitForPageToLoad($this->getTimeoutMsec());
}
-
/**
* Edit Financial Account
*/
$isDefault = FALSE
) {
if ($firstName) {
- $this->open($this->sboxPath . "civicrm/admin/financial/financialAccount?reset=1");
- $this->waitForPageToLoad($this->getTimeoutMsec());
+ $this->openCiviPage("admin/financial/financialAccount", "reset=1");
}
$this->waitForElementPresent("xpath=//table/tbody//tr/td[1][text()='{$editfinancialAccount}']/../td[9]/span/a[text()='Edit']");
- $this->click("xpath=//table/tbody//tr/td[1][text()='{$editfinancialAccount}']/../td[9]/span/a[text()='Edit']");
- $this->waitForPageToLoad($this->getTimeoutMsec());
-
- $this->waitForElementPresent('_qf_FinancialAccount_cancel-botttom');
+ $this->clickLink("xpath=//table/tbody//tr/td[1][text()='{$editfinancialAccount}']/../td[9]/span/a[text()='Edit']", '_qf_FinancialAccount_cancel-botttom');
// Change Financial Account Name
if ($financialAccountTitle) {
$this->type('accounting_code', $accountingCode);
}
-
// Autofill Edit Organization
if ($firstName) {
$this->webtestOrganisationAutocomplete($firstName);
$this->waitForPageToLoad($this->getTimeoutMsec());
}
-
/**
* Delete Financial Account
*/
}
function addeditFinancialType($financialType, $option = 'new') {
- $this->open($this->sboxPath . 'civicrm/admin/financial/financialType?reset=1');
+ $this->openCiviPage("admin/financial/financialType", "reset=1");
if ($option == 'Delete') {
$this->click("xpath=id('ltype')/div/table/tbody/tr/td[1][text()='$financialType[name]']/../td[7]/span[2]");
$this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text);
}
-
+ /**
+ * Give the specified permissions
+ * Note: this function logs in as 'admin' (logging out if necessary)
+ */
function changePermissions($permission) {
- $this->open($this->sboxPath . "civicrm/logout?reset=1");
- $this->waitForPageToLoad($this->getTimeoutMsec());
- $this->webtestLogin(TRUE);
- $this->changeAdminLinks();
+ $this->webtestLogin('admin');
+ $this->open("{$this->sboxPath}admin/people/permissions");
$this->waitForElementPresent('edit-submit');
- foreach ($permission as $key => $value) {
- $this->check($value);
+ foreach ((array) $permission as $perm) {
+ $this->check($perm);
}
$this->click('edit-submit');
$this->waitForPageToLoad($this->getTimeoutMsec());
$this->assertTrue($this->isTextPresent('The changes have been saved.'));
- $this->open($this->sboxPath . "user/logout");
- $this->waitForPageToLoad($this->getTimeoutMsec());
- $this->webtestLogin();
- $this->waitForPageToLoad($this->getTimeoutMsec());
}
function addProfile($profileTitle, $profileFields) {
- // Go directly to the URL of the screen that you will be testing (New Profile).
- $this->open($this->sboxPath . "civicrm/admin/uf/group?reset=1");
+ $this->openCiviPage('admin/uf/group', "reset=1");
- $this->waitForPageToLoad($this->getTimeoutMsec());
$this->click('link=Add Profile');
// Add membership custom data field to profile
);
$this->select('account_relationship', "label={$accountRelationship}");
+ // Because it tends to cause problems, all uses of sleep() must be justified in comments
+ // Sleep should never be used for wait for anything to load from the server
+ // Justification for this instance: FIXME
sleep(2);
$this->select('financial_account_id', "label={$financialAccountTitle}");
$this->click('_qf_FinancialTypeAccount_next');
}
function addPaymentInstrument($label, $financialAccount) {
- $this->open($this->sboxPath . "civicrm/admin/options/payment_instrument?group=payment_instrument&action=add&reset=1");
- $this->waitForElementPresent("_qf_Options_next-bottom");
+ $this->openCiviPage('admin/options/payment_instrument', 'group=payment_instrument&action=add&reset=1', "_qf_Options_next-bottom");
$this->type("label", $label);
$this->select("financial_account_id", "value=$financialAccount");
$this->click("_qf_Options_next-bottom");
$this->waitForPageToLoad($this->getTimeoutMsec());
}
+ /**
+ * Ensure we have a default mailbox set up for CiviMail
+ */
+ function setupDefaultMailbox() {
+ $this->openCiviPage('admin/mailSettings', 'action=update&id=1&reset=1');
+ // Check if it hasn't already been set up
+ if (!$this->getSelectedValue('protocol')) {
+ $this->type('name', 'Test Domain');
+ $this->select('protocol', "IMAP");
+ $this->type('server', 'localhost');
+ $this->type('domain', 'example.com');
+ $this->click('_qf_MailSettings_next-top');
+ $this->waitForPageToLoad($this->getTimeoutMsec());
+ }
+ }
+
/**
* Determine the default time-out in milliseconds.
*