CRM-12193 - Use more descriptive example text
[civicrm-core.git] / tests / phpunit / CiviTest / CiviSeleniumTestCase.php
index 09026939aff22eecda4868762372a36fdfe65210..1146117e394a993a276dc1f8741f4260fcb31ce9 100644 (file)
@@ -25,7 +25,6 @@
  +--------------------------------------------------------------------+
 */
 
-
 require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
 
 /**
@@ -47,7 +46,8 @@ require_once CIVICRM_SETTINGS_PATH;
  */
 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
@@ -65,6 +65,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    */
   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();
@@ -74,6 +75,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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();
   }
 
@@ -85,23 +87,44 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   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;
   }
 
   /**
@@ -115,7 +138,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    * 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) {
@@ -131,7 +154,23 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       }
     }
     $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);
     }
@@ -223,6 +262,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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;
@@ -231,7 +271,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     if ($added) {
       $this->click("_qf_Component_next-bottom");
       $this->waitForPageToLoad($this->getTimeoutMsec());
-      $this->assertElementContainsText("crm-notification-container", "Saved");
+      $this->waitForText('crm-notification-container', "Saved");
     }
   }
 
@@ -268,7 +308,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
   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);
 
@@ -286,7 +326,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
   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);
 
@@ -322,7 +362,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     //$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.
@@ -378,10 +417,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
     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__);
       }
     }
   }
@@ -513,6 +552,14 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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)
@@ -669,7 +716,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    * @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)) {
@@ -702,8 +749,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       "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;
@@ -717,6 +763,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
   /**
    * 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
    *
@@ -745,7 +792,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
                                       $honoreeSection = TRUE,
                                       $allowOtherAmmount = TRUE,
                                       $isConfirmEnabled = TRUE,
-                                      $financialType = 'Donation'
+                                      $financialType = 'Donation',
+                                      $fixedAmount = TRUE,
+                                      $membershipsRequired = TRUE
   ) {
     if (!$hash) {
       $hash = substr(sha1(rand()), 0, 7);
@@ -766,8 +815,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
 
     // 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);
@@ -805,9 +853,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       $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)) {
@@ -848,9 +898,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
         //$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 {
@@ -893,17 +944,16 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
             $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);
     }
@@ -986,7 +1036,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       $this->assertTrue($this->isTextPresent($text), 'Missing text: ' . $text);
     }
 
-
     if ($widget) {
       // fill in step 8 (Widget Settings)
       $this->click('link=Widgets');
@@ -1026,11 +1075,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       $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;
   }
 
@@ -1068,9 +1112,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       }
     }
 
-    $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) {
@@ -1114,8 +1156,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       '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']);
 
@@ -1185,11 +1226,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
 
     // 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;
   }
 
@@ -1201,7 +1241,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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
@@ -1272,9 +1311,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     // 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
@@ -1367,21 +1407,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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,
@@ -1394,9 +1422,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
                                     $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');
@@ -1461,7 +1487,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $this->waitForPageToLoad($this->getTimeoutMsec());
   }
 
-
   /**
    * Edit Financial Account
    */
@@ -1478,15 +1503,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
                                      $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) {
@@ -1503,7 +1524,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
       $this->type('accounting_code', $accountingCode);
     }
 
-
     // Autofill Edit Organization
     if ($firstName) {
       $this->webtestOrganisationAutocomplete($firstName);
@@ -1554,7 +1574,6 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $this->waitForPageToLoad($this->getTimeoutMsec());
   }
 
-
   /**
    * Delete Financial Account
    */
@@ -1589,7 +1608,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   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]");
@@ -1638,30 +1657,25 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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
@@ -1733,6 +1747,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     );
 
     $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');
@@ -1758,14 +1775,29 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   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.
    *