webform_civicrm-8.x-5.0-beta3/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php

tests/src/FunctionalJavascript/WebformCivicrmTestBase.php
<?php

namespace Drupal\Tests\webform_civicrm\FunctionalJavascript;

use Behat\Mink\Element\NodeElement;
use Drupal\Tests\webform\Traits\WebformBrowserTestTrait;
use Behat\Mink\Exception\ElementNotFoundException;
use Behat\Mink\Exception\ExpectationException;
use Drupal\Core\Url;
use Drupal\webform\WebformInterface;

abstract class WebformCivicrmTestBase extends CiviCrmTestBase {

  use WebformBrowserTestTrait;
  use \Drupal\Tests\mink_civicrm_helpers\Traits\Utils;
  use \Drupal\Tests\system\Traits\OffCanvasTestTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'webform',
    'webform_ui',
    'webform_civicrm',
    'token',
    'ckeditor5',
    'off_canvas_test',
    'mink_civicrm_helpers',
  ];

  /**
   * {@inheritdoc}
   *
   * During tests configuration schema is validated. This module does not
   * provide schema definitions for its handler.
   *
   * To fix: webform.webform.civicrm_webform_test:handlers.webform_civicrm.settings
   *
   * @see \Drupal\Core\Test\TestSetupTrait::getConfigSchemaExclusions
   */
  protected static $configSchemaCheckerExclusions = [
    'webform.webform.civicrm_webform_test',
  ];

  /**
   * The test webform.
   *
   * @var \Drupal\webform\WebformInterface
   */
  protected $webform;

  /**
   * The test admin user.
   *
   * @var \Drupal\user\Entity\User
   */
  protected $adminUser;

  /**
   * @var \Drupal\webform_civicrm\UtilsInterface
   */
  protected $utils;

  /**
   * @var int
   */
  protected $rootUserCid;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->utils = \Drupal::service('webform_civicrm.utils');

    // Make sure we are using distinct default and administrative themes for
    // the duration of these tests.
    \Drupal::service('theme_installer')->install(['olivero', 'claro']);
    $this->config('system.theme')
      ->set('default', 'olivero')
      ->set('admin', 'claro')
      ->save();

    $this->adminUser = $this->createUser([
      'access content',
      'administer CiviCRM',
      'access CiviCRM',
      'access administration pages',
      'access webform overview',
      'administer webform',
      'edit all contacts',
      'view all activities',
    ]);
    // Retrieve CiviCRM version
    $result = civicrm_api3('System', 'get', [
      'sequential' => 1,
    ]);
    $CiviCRM_version = $result['values'][0]['version'];
    $this->webform = $this->createWebform([
      'id' => 'civicrm_webform_test',
      'title' => 'CiviCRM Webform Test.' . $CiviCRM_version,
    ]);
    if (version_compare(\CRM_Core_BAO_Domain::version(), '5.79.alpha1', '<')) {
      $this->rootUserCid = $this->createIndividual()['id'];
      // Create CiviCRM contact for rootUser.
      $this->utils->wf_civicrm_api('UFMatch', 'create', [
        'uf_id' => $this->rootUser->id(),
        'uf_name' => $this->rootUser->getAccountName(),
        'contact_id' => $this->rootUserCid,
      ]);
    }
    else {
      $this->rootUserCid = $this->getUFMatchRecord($this->rootUser->id())['contact_id'];
    }
  }

  protected function tearDown(): void {
    // store the civi log in the downloadable artifacts
    $logfile = \Civi::$statics['CRM_Core_Error']['logger_file'] ?? NULL;
    if ($logfile && file_exists($logfile)) {
      copy($logfile, '/home/runner/drupal/web/sites/simpletest/browser_output/' . \CRM_Utils_File::makeFilenameWithUnicode($this->getName()) . '.log');
    }
    parent::tearDown();
  }

  /**
   * Redirect civicrm emails to database.
   */
  public function redirectEmailsToDB() {
    $url = Url::fromUri('internal:/civicrm/admin/setting/smtp', [
      'absolute' => TRUE,
      'query' => ['reset' => 1]
    ])->toString();
    $this->drupalGet($url);

    $this->getSession()->getPage()->selectFieldOption('outBound_option', 5);

    $this->getSession()->getPage()->pressButton('_qf_Smtp_next');
  }

  /**
   * @return string
   */
  public function getMostRecentEmail() {
    $msg = '';
    $result = \Drupal::database()->query("SELECT headers, body FROM civicrm_mailing_spool ORDER BY id DESC LIMIT 1");
    while ($content = $result->fetchAssoc()) {
      $msg = $content['headers'] . "\n\n" . $content['body'];
    }
    return $msg;
  }

  /**
   * Create Membership Type
   */
  protected function createMembershipType($amount = 0, $autoRenew = FALSE, $name = 'Basic', $financialTypeId = 'Member Dues') {
    $result = civicrm_api3('MembershipType', 'create', [
      'member_of_contact_id' => 1,
      'financial_type_id' => $financialTypeId,
      'duration_unit' => "year",
      'duration_interval' => 1,
      'period_type' => "rolling",
      'minimum_fee' => $amount,
      'name' => $name,
      'auto_renew' => $autoRenew,
    ]);
    $this->assertEquals(0, $result['is_error']);
    $this->assertEquals(1, $result['count']);
    return array_pop($result['values']);
  }

  /**
   * Create Financial Type
   */
  protected function createFinancialType($name) {
    $result = civicrm_api3('FinancialType', 'create', [
      'name' => $name,
      'is_active' => 1,
    ]);
    $this->assertEquals(0, $result['is_error']);
    $this->assertEquals(1, $result['count']);
    return array_pop($result['values']);
  }

  protected function setupSalesTax(int $financialTypeId, $accountParams = [], $tax_rate= 5) {
    $params = array_merge([
      'name' => 'Sales tax account ' . substr(sha1(rand()), 0, 4),
      'financial_account_type_id' => key(\CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name LIKE 'Liability' ")),
      'is_tax' => 1,
      'tax_rate' => $tax_rate,
      'is_active' => 1,
    ], $accountParams);
    $account = \CRM_Financial_BAO_FinancialAccount::writeRecord($params);
    $entityParams = [
      'entity_table' => 'civicrm_financial_type',
      'entity_id' => $financialTypeId,
      'account_relationship' => key(\CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Sales Tax Account is' ")),
    ];

    \Civi::$statics['CRM_Core_PseudoConstant']['taxRates'][$financialTypeId] = $params['tax_rate'];

    $dao = new \CRM_Financial_DAO_EntityFinancialAccount();
    $dao->copyValues($entityParams);
    $dao->find();
    if ($dao->fetch()) {
      $entityParams['id'] = $dao->id;
    }
    $entityParams['financial_account_id'] = $account->id;

    return \CRM_Financial_BAO_FinancialTypeAccount::add($entityParams);
  }

  /**
   * Create custom group.
   */
  protected function createCustomGroup($params = [], $extends = 'Individual') {
    $params = array_merge([
      'title' => "Custom",
      'extends' => $extends,
    ], $params);
    return $this->utils->wf_civicrm_api('CustomGroup', 'create', $params);
  }

  /**
   * {@inheritdoc}
   */
  protected function initFrontPage() {
    parent::initFrontPage();
    // Fix hidden columns on build page.
    $this->getSession()->resizeWindow(1440, 900);
  }

  /**
   * Configure contribution tab on civicrm settings page.
   *
   * @param array $params
   */
  protected function configureContributionTab($params = []) {
    //Configure Contribution tab.
    $this->getSession()->getPage()->clickLink('Contribution');
    $this->getSession()->getPage()->selectFieldOption('civicrm_1_contribution_1_contribution_enable_contribution', 1);
    $this->assertSession()->assertWaitOnAjaxRequest();
    $this->assertSession()->pageTextContains('You must enable an email field for Contact 1 in order to process transactions.');
    $this->getSession()->getPage()->pressButton('Enable It');
    $this->assertSession()->assertWaitOnAjaxRequest();
    $this->getSession()->getPage()->selectFieldOption('Currency', 'USD');
    $this->getSession()->getPage()->selectFieldOption('Financial Type', $params['financial_type_id'] ?? 1);
    $this->assertSession()->assertWaitOnAjaxRequest();

    if (!empty($params['payment_processor_id'])) {
      $this->getSession()->getPage()->selectFieldOption('Payment Processor', $params['payment_processor_id']);
    }
    if (!empty($params['soft'])) {
      $this->getSession()->getPage()->selectFieldOption('Soft Credit To', $params['soft']);
      $this->getSession()->getPage()->selectFieldOption('Soft Credit Type', $params['soft_credit_type_id']);
    }

    if (!empty($params['receipt'])) {
      $this->getSession()->getPage()->selectFieldOption('Enable Receipt?', 'Yes');
      $this->assertSession()->assertWaitOnAjaxRequest();
      foreach ($params['receipt'] as $k => $v) {
        $this->getSession()->getPage()->fillField("receipt_1_number_of_receipt_{$k}", $v);
      }
    }
    else {
      $this->getSession()->getPage()->selectFieldOption('Enable Receipt?', 'No');
      $this->assertSession()->assertWaitOnAjaxRequest();
    }
  }

  /**
   * Send a key press to an element.
   *
   * @var \Behat\Mink\Element\NodeElement $element
   *   The element.
   * @var string|int $char
   *   The character or char key code
   * @var string $modifier
   *   The modifier (could be 'ctrl', 'alt', 'shift' or 'meta').
   */
  protected function sendKeyPress(NodeElement $element, $char, $modifier = '') {
    $element->keyDown($char, $modifier);
    $element->keyUp($char, $modifier);
    $element->blur();
  }

  /**
   * Asserts the page has no error messages.
   */
  protected function assertPageNoErrorMessages() {
    $error_messages = $this->getSession()->getPage()->findAll('css', '.messages.messages--error');
    $this->assertCount(0, $error_messages, implode(', ', array_map(static function(NodeElement $el) {
      return $el->getText();
    }, $error_messages)));
    // Check for fatal errors. Doing it this way so that the text itself which
    // contains the stack trace is automatically output to the github action
    // log.
    $the_text = $this->getSession()->getPage()->getText();
    $this->assertStringNotContainsString('The website encountered an unexpected error', $the_text);
  }

  /**
   * Copy of TraversableElement::fillField, but it replaces the existing value on the element rather than appending to it.
   *
   * Fills in field (input, textarea, select) with specified locator.
   *
   * @param string $locator input id, name or label
   * @param string $value   value
   *
   * @throws ElementNotFoundException
   *
   * @see NodeElement::setValue
   */
  public function addFieldValue($locator, $value) {
    $field = $this->getSession()->getPage()->findField($locator);
    if (null === $field) {
      throw new ElementNotFoundException($this->getDriver(), 'form field', 'id|name|label|value|placeholder', $locator);
    }
    $field->doubleClick();
    $field->setValue($value);
  }

  /**
   * Assert populated values on the field.
   * fieldValueEquals() fails for populated values on chromedriver > 91
   *
   * @param $selector
   * @param $value
   * @param $isRadio
   */
  public function assertFieldValue($selector, $value, $isRadio = FALSE) {
    $driver = $this->getSession()->getDriver();
    if ($isRadio) {
      $fieldVal = $driver->evaluateScript("document.querySelector(\"input[type=radio][name='{$selector}']:checked\").value;");
    }
    else {
      $fieldVal = $driver->evaluateScript("document.getElementById('{$selector}').value;");
    }
    $this->assertEquals($fieldVal, $value);
  }

  /**
   * Modify settings so the element displays as a checkbox
   *
   * @param string $selector
   * @param bool $multiple
   * @param bool $enableStatic
   *   TRUE if static radio option should be enabled.
   * @param bool $default
   * @param string $type
   *  possible values - checkboxes, radios, select, civicrm-options
   * @param string $singleOption
   *  TRUE if only one option is enabled on the element.
   * @param string $asList
   *  TRUE if element need to be rendered as select element.
   * @param string $secondarySelector
   *  optional secondary selector
   */
  protected function editCivicrmOptionElement($selector, $multiple = TRUE, $enableStatic = FALSE, $default = NULL, $type = NULL, $singleOption = FALSE, $asList = FALSE, $secondarySelector = 'li.edit') {
    $checkbox_edit_button = $this->assertSession()->elementExists('css', '[data-drupal-selector="' . $selector . '"] ' . ($secondarySelector ? "$secondarySelector " : '') . 'a.webform-ajax-link');
    $checkbox_edit_button->click();
    $this->waitForOffCanvasArea();
    $this->htmlOutput();
    if ($type) {
      $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-change-type"]')->click();
      $this->assertSession()->assertWaitOnAjaxRequest();
      $this->assertSession()->waitForElementVisible('css', "[data-drupal-selector='edit-elements-{$type}-operation']", 5000)->click();
      $this->assertSession()->waitForElementVisible('css', "[data-drupal-selector='edit-cancel']", 5000);
    }

    if ($enableStatic) {
      $this->getSession()->getPage()->selectFieldOption("properties[civicrm_live_options]", 0);
      $this->assertSession()->waitForField('properties[options][options][civicrm_option_1][enabled]', 5000);

      if ($singleOption) {
        $select_all_checkbox = $this->assertSession()->elementExists('css', '.select-all input.form-checkbox');
        $select_all_checkbox->click();
        $this->getSession()->wait(1000);
        $select_all_checkbox->click();
        $this->getSession()->wait(1000);

        $this->getSession()->getPage()->checkField('properties[options][options][civicrm_option_1][enabled]');
        $this->assertSession()->checkboxChecked('properties[options][options][civicrm_option_1][enabled]');
      }
    }
    if ($default) {
      $this->getSession()->getPage()->selectFieldOption("properties[options][default]", $default);
    }
    if (!$type || $type == 'civicrm-options') {
      if ($asList) {
        $this->getSession()->getPage()->checkField('properties[extra][aslist]');
        $this->assertSession()->checkboxChecked('properties[extra][aslist]');
        $this->htmlOutput();
      }
      else {
        $this->getSession()->getPage()->uncheckField('properties[extra][aslist]');
        $this->assertSession()->checkboxNotChecked('properties[extra][aslist]');
        $this->htmlOutput();
      }
      if (!$multiple) {
        $this->getSession()->getPage()->uncheckField('properties[extra][multiple]');
        $this->assertSession()->checkboxNotChecked('properties[extra][multiple]');
      }
    }
    if ($multiple) {
      $this->getSession()->getPage()->checkField('properties[extra][multiple]');
      $this->assertSession()->checkboxChecked('properties[extra][multiple]');
    }
    $this->htmlOutput();
    $this->getSession()->getPage()->pressButton('Save');
    $this->assertSession()->waitForText('has been updated.');
  }

  /**
   * Create Payment Processor.
   */
  protected function createPaymentProcessor() {
    $params = [
      'domain_id' => 1,
      'name' => 'Dummy',
      'payment_processor_type_id' => 'Dummy',
      'is_active' => 1,
      'is_default' => 1,
      'is_test' => 0,
      'user_name' => 'foo',
      'url_site' => 'http://dummy.com',
      'url_recur' => 'http://dummy.com',
      'class_name' => 'Payment_Dummy',
      'billing_mode' => 1,
      'is_recur' => 1,
      'payment_instrument_id' => 'Credit Card',
    ];
    $result = $this->utils->wf_civicrm_api('payment_processor', 'create', $params);
    $this->assertEquals(0, $result['is_error']);
    $this->assertEquals(1, $result['count']);
    return current($result['values']);
  }

  /**
   * Enables CiviCRM on the webform.
   */
  public function enableCivicrmOnWebform() {
    $this->assertSession()->waitForText('Enable CiviCRM Processing');
    $this->assertSession()->waitForField('nid');
    $this->htmlOutput();
    $this->getSession()->getPage()->checkField('nid');
    $this->getSession()->getPage()->selectFieldOption('1_contact_type', 'individual');
  }

  /**
   * Save the settings configured on the civicrm tab.
   *
   * @param boolean $fieldDeleted
   */
  public function saveCiviCRMSettings($fieldDeleted = FALSE) {
    $this->getSession()->getPage()->pressButton('Save Settings');
    if (!$fieldDeleted) {
      $this->assertSession()->pageTextContains('Saved CiviCRM settings');
    }
    $this->assertPageNoErrorMessages();
  }

  /**
   * Return UF Match record.
   *
   * @param int $ufID
   */
  protected function getUFMatchRecord($ufID) {
    return $this->utils->wf_civicrm_api('UFMatch', 'getsingle', [
      'uf_id' => $ufID,
    ]);
  }

  /**
   * Set default value on webform element.
   */
  protected function setDefaultValue($selector, $value) {
    $this->assertSession()->elementExists('css', "[data-drupal-selector='{$selector}'] a.webform-ajax-link")->click();
    $this->htmlOutput();
    $this->assertSession()->waitForElementVisible('xpath', '//a[contains(@id, "--advanced")]');
    $this->assertSession()->elementExists('xpath', '//a[contains(@id, "--advanced")]')->click();
    $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-default"]')->click();
    $this->getSession()->getPage()->fillField('properties[default_value]', $value);
    $this->getSession()->getPage()->pressButton('Save');
    $this->assertSession()->assertWaitOnAjaxRequest();
    $this->assertSession()->pageTextContains(' has been updated');
  }

  /**
   * Edit contact element on the build form.
   *
   * @param array $params
   *   Example Usage -
   *    $params = [
   *     'selector' => 'edit-webform-ui-elements-civicrm-4-contact-1-contact-existing-operations',
   *     'widget' => 'Static',
   *     'default' => 'relationship',
   *     'filter' => [
   *        'group' => group_id,
   *      ],
   *     'default_relationship' => [
   *       'default_relationship_to' => 'Contact 3',
   *       'default_relationship' => 'Child of Contact 3',
   *     ],
   *   ];
   */
  protected function editContactElement($params) {
    $this->assertSession()->waitForElementVisible('css', "[data-drupal-selector=\"{$params['selector']}\"] a.webform-ajax-link");

    $contactElementEdit = $this->assertSession()->elementExists('css', "[data-drupal-selector=\"{$params['selector']}\"] a.webform-ajax-link");
    $contactElementEdit->click();
    $this->htmlOutput();

    $this->assertSession()->waitForElementVisible('css', "button.webform-details-toggle-state");
    $expandLink = $this->cssSelect('button.webform-details-toggle-state')[0];
    if ($expandLink->getText() == 'Expand all') {
      $expandLink->click();
    }
    if (!empty($params['title'])) {
      $this->getSession()->getPage()->fillField('title', $params['title']);
    }
    if (!empty($params['description'])) {
      $this->fillCKEditor('properties[description][value]', $params['description']);
    }
    if (!empty($params['hide_fields'])) {
      $this->getSession()->getPage()->selectFieldOption('properties[hide_fields][]', $params['hide_fields']);
    }
    if (!empty($params['hide_method'])) {
      $this->getSession()->getPage()->selectFieldOption('properties[hide_method]', $params['hide_method']);
    }
    if (!empty($params['submit_disabled'])) {
      $this->getSession()->getPage()->checkField("properties[submit_disabled]");
    }
    if (!empty($params['no_hide_blank'])) {
      $this->getSession()->getPage()->checkField("properties[no_hide_blank]");
    }

    $this->assertSession()->waitForElementVisible('xpath', '//select[@name="properties[widget]"]');
    if ($params['widget'] == 'Static') {
      try {
        $this->getSession()->getPage()->selectFieldOption('properties[show_hidden_contact]', 1);
      }
      catch (\WebDriver\Exception\ElementNotVisible $e) {
        // for some reason the section didn't open probably - click it again ??
        $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-form"]')->click();
        $this->getSession()->getPage()->selectFieldOption('properties[show_hidden_contact]', 1);
      }
    }
    else {
      $this->getSession()->getPage()->selectFieldOption('Form Widget', $params['widget']);
      $this->assertSession()->assertWaitOnAjaxRequest();
      if ($params['widget'] == 'Autocomplete') {
        $this->assertSession()->waitForElementVisible('css', '[data-drupal-selector="edit-properties-search-prompt"]');
        $this->getSession()->getPage()->fillField('Search Prompt', '- Select Contact -');
      }
    }
    $this->htmlOutput();
    if (!empty($params['results_display'])) {
      $this->addFieldValue('properties[results_display][]', $params['results_display']);
    }

    if (!empty($params['default'])) {
      $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-contact-defaults"]')->click();
      $this->assertSession()->assertWaitOnAjaxRequest();
      $this->getSession()->getPage()->selectFieldOption('Set default contact from', $params['default']);

      if ($params['default'] == 'Specified Contact') {
        $this->getSession()->getPage()->fillField('default-contact-id', $params['default_contact_id']);
      }

      if ($params['default'] == 'relationship') {
        $this->getSession()->getPage()->selectFieldOption('properties[default_relationship_to]', $params['default_relationship']['default_relationship_to']);
        $this->assertSession()->assertWaitOnAjaxRequest();
        $this->getSession()->getPage()->selectFieldOption('properties[default_relationship][]', $params['default_relationship']['default_relationship']);
      }
    }

    // Apply contact filter.
    if (!empty($params['filter'])) {
      $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-filters"]')->click();
      if (!empty($params['filter']['group'])) {
        $this->getSession()->getPage()->selectFieldOption('Groups', $params['filter']['group']);
      }
      if (!empty($params['filter']['filter_relationship_types'])) {
        $this->getSession()->getPage()->selectFieldOption('properties[filter_relationship_types][]', $params['filter']['filter_relationship_types']);
      }
      if (isset($params['filter']['check_permissions']) && empty($params['filter']['check_permissions'])) {
        $this->getSession()->getPage()->uncheckField('properties[check_permissions]');
      }
    }

    if (!empty($params['remove_default_url'])) {
      $this->getSession()->getPage()->uncheckField('properties[allow_url_autofill]');
    }
    if (!empty($params['required'])) {
      $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-validation"]')->click();
      $this->getSession()->getPage()->checkField('properties[required]');
    }

    // Wait for ajax message from previous click of Save button to no longer be
    // visible to avoid falling through the following waitForElementVisible
    // prematurely.
    do {
      $ajax_message_visible = $this->assertSession()->waitForElementVisible('css', '.webform-ajax-messages', 100);
    } while ($ajax_message_visible);

    $this->getSession()->getPage()->pressButton('Save');
    $this->assertSession()->waitForElementVisible('css', '.webform-ajax-messages');
  }

  /**
   * Fill Contact Autocomplete widget.
   *
   * @param string $id
   * @param string $value
   */
  protected function fillContactAutocomplete($id, $value) {
    $page = $this->getSession()->getPage();
    $driver = $this->getSession()->getDriver()->getWebDriverSession();
    $elementXpath = $page->findField($id)->getXpath();

    $this->assertSession()->elementExists('css', "#" . $id)->click();
    $driver->element('xpath', $elementXpath)->postValue(['value' => [$value]]);

    $this->assertSession()->waitForElementVisible('xpath', '//li[contains(@class, "token-input-dropdown")][1]');
    // $this->createScreenshot($this->htmlOutputDirectory . '/autocomplete.png');

    $page->find('xpath', '//li[contains(@class, "token-input-dropdown")][1]')->click();
    $this->assertSession()->assertWaitOnAjaxRequest();
  }

  /**
   * Asserts that a select option in the current page is checked.
   *
   * @param string $id
   *   ID of select field to assert.
   * @param string $option
   *   Option to assert.
   * @param string $message
   *   (optional) A message to display with the assertion. Do not translate
   *   messages with t(). If left blank, a default message will be displayed.
   */
  protected function assertOptionSelected($id, $option, $message = NULL) {
    $option_field = $this->assertSession()->optionExists($id, $option);
    $message = $message ?: "Option $option for field $id is not selected.";
    $this->assertTrue($option_field->hasAttribute('selected'), $message);
  }

  /**
   * Create test contact of type individual.
   */
  protected function createIndividual($params = []) {
    $params = array_merge([
      'contact_type' => 'Individual',
      'first_name' => substr(sha1(rand()), 0, 7),
      'last_name' => substr(sha1(rand()), 0, 7),
    ], $params);
    return current($this->utils->wf_civicrm_api('contact', 'create', $params)['values']);
  }

  /**
   * Create test contact of type individual.
   */
  protected function createHousehold($params = []) {
    $params = array_merge([
      'contact_type' => 'Household',
      'household_name' => substr(sha1(rand()), 0, 7),
    ], $params);
    return current($this->utils->wf_civicrm_api('contact', 'create', $params)['values']);
  }

  /**
   * Enable Component in CiviCRM.
   *
   * @param string $componentName
   */
  protected function enableComponent($componentName) {
    $enabledComponents = $this->utils->wf_crm_get_civi_setting('enable_components');
    if (in_array($componentName, $enabledComponents)) {
      // component is already enabled
      return;
    }
    $enabledComponents[] = $componentName;
    $this->utils->wf_civicrm_api('Setting', 'create', [
      'enable_components' => $enabledComponents,
    ]);
  }

  /**
   * Enable Billing Section on the contribution tab.
   */
  protected function enableBillingSection() {
    $this->getSession()->getPage()->selectFieldOption('Enable Billing Address?', 'Yes');
    $this->assertSession()->assertWaitOnAjaxRequest();
    $this->htmlOutput();
    $this->assertSession()->checkboxChecked("Billing First Name");
    $this->assertSession()->checkboxNotChecked("Billing Middle Name");
    $this->assertSession()->checkboxChecked("Billing Last Name");
    $this->assertSession()->checkboxChecked("Street Address");
    $this->assertSession()->checkboxChecked("Postal Code");
    $this->assertSession()->checkboxChecked("City");
    $this->assertSession()->checkboxChecked("Country");
    $this->assertSession()->checkboxChecked("State/Province");
  }

  /**
   * Insert values in billing fields.
   *
   * @param array $params
   */
  protected function fillBillingFields($params) {
    $this->getSession()->getPage()->fillField('Billing First Name', $params['first_name']);
    $this->getSession()->getPage()->fillField('Billing Last Name', $params['last_name']);
    $this->getSession()->getPage()->fillField('Street Address', $params['street_address']);
    $this->getSession()->getPage()->fillField('City', $params['city']);

    $this->getSession()->getPage()->selectFieldOption('Country', $params['country']);
    $this->getSession()->wait(1000);
    $this->getSession()->getPage()->selectFieldOption('State/Province', $params['state_province']);

    $this->getSession()->getPage()->fillField('Postal Code', $params['postal_code']);
  }

  /**
   * Fill Card Details and submit.
   *
   * @param array $billingValues
   *  Assert values populated in billing address fields after sameas checkbox is enabled.
   */
  protected function fillCardAndSubmit($billingValues = []) {
    if (!empty($billingValues)) {
      $this->getSession()->getPage()->checkField("civicrm_1_contribution_1_contribution_billing_address_same_as");
      $this->getSession()->wait(1000);

      // Verify populated values for billing fields.
      foreach ($billingValues as $key => $val) {
        $billingKey = 'civicrm_1_contribution_1_contribution_billing_address_' . $key;
        $this->assertSession()->fieldValueEquals($billingKey, $val);
      }
    }
    else {
      $billingValues = [
        'first_name' => 'Frederick',
        'last_name' => 'Pabst',
        'street_address' => '123 Milwaukee Ave',
        'city' => 'Milwaukee',
        'country' => '1228',
        'state_province' => '1048',
        'postal_code' => '53177',
      ];
      $this->fillBillingFields($billingValues);
    }
    // Wait for the credit card form to load in.
    $this->assertSession()->waitForField('credit_card_number');
    $this->getSession()->getPage()->fillField('credit_card_number', '4222222222222220');
    $this->getSession()->getPage()->fillField('cvv2', '123');
    $this->getSession()->getPage()->selectFieldOption($this->getCreditCardMonthFieldName(), '11');
    $this_year = date('Y');
    $this->getSession()->getPage()->selectFieldOption('credit_card_exp_date[Y]', $this_year + 1);

    $this->getSession()->getPage()->pressButton('Submit');
    $this->htmlOutput();
    $this->assertPageNoErrorMessages();
    $this->assertSession()->waitForText('New submission added to CiviCRM Webform Test.');
  }

  /**
   * Fill CKEditor field.
   *
   * @param string $locator
   * @param string $value
   */
  public function fillCKEditor($locator, $value) {
    $format = \Drupal::config('webform.settings')->get('html_editor.element_format');
    if ($format === 'webform_default') {
      $locator .= '[value]';
    }

    $el = $this->getSession()->getPage()->findField($locator);
    if (empty($el)) {
      throw new ExpectationException('Could not find WYSIWYG with locator: ' . $locator, $this->getSession()->getDriver());
    }
    $fieldId = $el->getAttribute('id');
    if (empty($fieldId)) {
      throw new Exception('Could not find an id for field with locator: ' . $locator);
    }

    // Fill value on the wysiwyg editor.
    $this->getSession()->executeScript("
      const element = document.getElementById(\"$fieldId\");
      const editor = Drupal.CKEditor5Instances.get(
        element.getAttribute('data-ckeditor5-id'),
      );
      editor.setData(\"$value\");
    ");
  }

  /**
   * Add email handler
   *
   * @param array $params
   */
  protected function addEmailHandler($params) {
    $this->drupalGet("admin/structure/webform/manage/civicrm_webform_test/handlers/add/email");
    if (!empty($params['to_mail'])) {
      $this->getSession()->getPage()->selectFieldOption('settings[to_mail][select]', $params['to_mail']);
    }

    $this->getSession()->getPage()->selectFieldOption('edit-settings-body', '_other_');
    $this->fillCKEditor('settings[body_custom_html][value]', $params['body']);
    $this->getSession()->getPage()->pressButton('Save');
  }

  /**
   * Returns the ID of the last submission on a given webform.
   *
   * @param \Drupal\webform\WebformInterface $webform
   *   The webform entity object.
   *
   * @return int|null
   *   The ID of the last submission on the webform, or null if there are no
   *   submissions.
   */
  protected function getLastSubmissionId(WebformInterface $webform) {
    $submission_ids = \Drupal::entityQuery('webform_submission')
      ->accessCheck(TRUE)
      ->condition('webform_id', $webform->id())
      ->sort('created', 'DESC')
      ->range(0, 1)
      ->execute();
    return reset($submission_ids);
  }

  /**
   * Can remove this once only testing 5.65+
   */
  protected function getCreditCardMonthFieldName(): string {
    if (version_compare(\CRM_Core_BAO_Domain::version(), '5.65.alpha1', '<')) {
      return 'credit_card_exp_date[M]';
    }
    return 'credit_card_exp_date[m]';
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc