CRM-15031 Event Webtest Fix
[civicrm-core.git] / tests / phpunit / CiviTest / CiviSeleniumTestCase.php
index 44cda181bf0004ea233a297c0d7be326e823dfb1..a8f3853ccb808620629d5c52d899e7d9fd662f1f 100644 (file)
@@ -32,6 +32,7 @@ require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
  */
 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;
@@ -60,8 +61,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *  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);
@@ -103,6 +105,49 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
   }
 
+  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() {
   }
 
@@ -229,6 +274,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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,
@@ -238,6 +288,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     return $result;
   }
 
+  /**
+   * @return mixed
+   */
   function webtestGetValidCountryID() {
     static $_country_id;
     if (is_null($_country_id)) {
@@ -247,6 +300,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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
@@ -257,6 +315,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     return NULL;
   }
 
+  /**
+   * @param $field
+   *
+   * @return mixed
+   */
   function webtestGetConfig($field) {
     static $_config_backend;
     if (is_null($_config_backend)) {
@@ -298,7 +361,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *
    * @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)
    */
@@ -323,6 +388,12 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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");
@@ -341,6 +412,13 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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';
@@ -394,6 +472,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
      *        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');
 
@@ -410,6 +492,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 1. set both date and time.
+  /**
+   * @param $dateElement
+   * @param null $strToTimeArgs
+   */
   function webtestFillDateTime($dateElement, $strToTimeArgs = NULL) {
     $this->webtestFillDate($dateElement, $strToTimeArgs);
 
@@ -456,10 +542,13 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *
    * @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>');");
     }
@@ -544,6 +633,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *
    * @strings  array    array of strings or a single string
    *
+   * @param $strings
    * @return   void
    */
   function assertStringsPresent($strings) {
@@ -557,10 +647,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *
    * @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) {
@@ -589,8 +679,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    *
    * @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
    */
 
@@ -666,6 +758,13 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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';
@@ -685,14 +784,20 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
     $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';
@@ -708,6 +813,13 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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';
@@ -789,9 +901,35 @@ 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
+   * @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,
@@ -814,7 +952,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
                                       $isPcpApprovalNeeded = FALSE,
                                       $isSeparatePayment = FALSE,
                                       $honoreeSection = TRUE,
-                                      $allowOtherAmmount = TRUE,
+                                      $allowOtherAmount = TRUE,
                                       $isConfirmEnabled = TRUE,
                                       $financialType = 'Donation',
                                       $fixedAmount = TRUE,
@@ -849,7 +987,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
     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') {
@@ -918,7 +1056,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
         $this->click("is_recur_interval");
         $this->click("is_recur_installments");
       }
-      if ($allowOtherAmmount) {
+      if ($allowOtherAmount) {
 
         $this->click('is_allow_other_amount');
 
@@ -926,7 +1064,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
         //$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");
       }
@@ -1110,8 +1248,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
    * 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.
@@ -1171,6 +1310,14 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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';
@@ -1224,6 +1371,12 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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');
 
@@ -1258,6 +1411,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     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.
@@ -1275,25 +1433,12 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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__);
@@ -1326,15 +1471,15 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
     // 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
@@ -1342,6 +1487,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     return $this->urlArg('id');
   }
 
+  /**
+   * @return bool
+   */
   static
   function checkDoLocalDBTest() {
     if (defined('CIVICRM_WEBTEST_LOCAL_DB') &&
@@ -1372,6 +1520,15 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 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;
@@ -1381,6 +1538,13 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 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;
@@ -1390,6 +1554,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 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;
@@ -1399,6 +1568,14 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 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
   ) {
@@ -1412,6 +1589,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   }
 
   // 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;
@@ -1420,6 +1602,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     return CiviDBAssert::assertDBCompareValues($this, $daoName, $searchParams, $expectedValues);
   }
 
+  /**
+   * @param $expectedValues
+   * @param $actualValues
+   */
   function assertAttributesEquals(&$expectedValues, &$actualValues) {
     if (!self::checkDoLocalDBTest()) {
       return;
@@ -1428,6 +1614,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     return CiviDBAssert::assertAttributesEquals($expectedValues, $actualValues);
   }
 
+  /**
+   * @param $expected
+   * @param $actual
+   * @param string $message
+   */
   function assertType($expected, $actual, $message = '') {
     return $this->assertInternalType($expected, $actual, $message);
   }
@@ -1624,6 +1815,9 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
   }
 
+  /**
+   * @param $verifySelectFieldData
+   */
   function _assertSelectVerify($verifySelectFieldData) {
     foreach ($verifySelectFieldData as $key => $expectedvalue) {
       $actualvalue = $this->getSelectedLabel($key);
@@ -1631,6 +1825,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
   }
 
+  /**
+   * @param $financialType
+   * @param string $option
+   */
   function addeditFinancialType($financialType, $option = 'new') {
     $this->openCiviPage("admin/financial/financialType", "reset=1");
 
@@ -1696,6 +1894,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $this->assertTrue($this->isTextPresent('The changes have been saved.'));
   }
 
+  /**
+   * @param $profileTitle
+   * @param $profileFields
+   */
   function addProfile($profileTitle, $profileFields) {
     $this->openCiviPage('admin/uf/group', "reset=1");
 
@@ -1725,6 +1927,14 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
   }
 
+  /**
+   * @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);
@@ -1740,6 +1950,10 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     $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);
@@ -1835,6 +2049,11 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
     }
   }
 
+  /**
+   * @param $customSets
+   *
+   * @return array
+   */
   function addCustomGroupField($customSets) {
     foreach ($customSets as $customSet) {
       $this->openCiviPage("admin/custom/group", "action=add&reset=1");
@@ -1864,7 +2083,7 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
       $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));
 
@@ -1877,23 +2096,38 @@ class CiviSeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
   /**
    * 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);
     }
   }
 }