diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 35d2aa473..d6323770b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,6 +61,13 @@ jobs: run: | sudo apt-get update sudo apt-get install sendmail + # Temp thing + - name: Downgrade chrome + run: | + curl -L -o chrome.deb http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_127.0.6533.119-1_amd64.deb + sudo apt-get install libu2f-udev + sudo dpkg -i chrome.deb + google-chrome-stable --version - name: Setup Drupal run: | COMPOSER_MEMORY_LIMIT=-1 composer create-project drupal/recommended-project:${{ matrix.drupal }} ~/drupal --no-interaction --no-install @@ -144,7 +151,7 @@ jobs: run: | mkdir -p ~/drupal/web/sites/default/files/civicrm/ext cd ~/drupal/web/sites/default/files/civicrm/ext - # Allow "unapproved" extensions + # Allow unapproved extensions /home/runner/civicrm-cv/cv ev '\Civi::settings()->set("ext_repo_url", "https://civicrm.org/extdir/ver={ver}|cms={uf}|ready=");' /home/runner/civicrm-cv/cv ev '\Civi::settings()->set("http_timeout", 60);' # Apparently we have to install it, otherwise stripe gives a dependency error even with install=0. I think that's a bug, but let's just do it. This is a fake install anyway. @@ -169,8 +176,11 @@ jobs: git apply 457.diff git apply 458.diff - uses: nanasess/setup-chromedriver@master + with: + # temporary to match downgraded chrome + chromedriver-version: '127.0.6533.119' - name: Run chromedriver - run: chromedriver & + run: chromedriver --port=9515 & - name: Run php built-in server run: php -S 127.0.0.1:8080 -t ~/drupal/web & - name: Run PHPUnit @@ -187,6 +197,7 @@ jobs: DEV_EXTENSION_DIR: /home/runner/drupal/web/sites/default/files/civicrm/ext DEV_EXTENSION_URL: http://127.0.0.1:8080/sites/default/files/civicrm/ext - name: Helper to make unique name for upload + if: ${{ failure() || success() }} run: | # doing this on multiple lines to avoid quote-hell cd ${{ runner.temp }} diff --git a/js/webform_civicrm_contact.js b/js/webform_civicrm_contact.js index a19f10ba0..df90e3d72 100644 --- a/js/webform_civicrm_contact.js +++ b/js/webform_civicrm_contact.js @@ -17,15 +17,19 @@ searchingText: "Searching...", enableHTML: true }; - wfCivi.existingInit( - field, - field.data('civicrm-contact'), - field.data('form-id'), - autocompleteUrl, - toHide, - tokenValues - ); } + else { + var tokenValues = false; + } + + wfCivi.existingInit( + field, + field.data('civicrm-contact'), + field.data('form-id'), + autocompleteUrl, + toHide, + tokenValues + ); field.change(function () { wfCivi.existingSelect( diff --git a/src/ContactComponent.php b/src/ContactComponent.php index 61c1bc31c..9a6110366 100644 --- a/src/ContactComponent.php +++ b/src/ContactComponent.php @@ -107,6 +107,7 @@ function wf_crm_contact_search($node, $element, $params, $contacts, $str = NULL) 'country' => ['address', 'country_id:label'], 'county' => ['address', 'county_id:label'], 'postal_code' => ['address', 'postal_code'], + 'street_address' => ['address', 'street_address'] ]; $joinedTables = []; foreach ($fieldMappings as $field => $type) { diff --git a/src/Fields.php b/src/Fields.php index fe2d96269..88a788f50 100644 --- a/src/Fields.php +++ b/src/Fields.php @@ -86,7 +86,7 @@ protected function getSets(array $components): array { } } $conditional_sets = [ - 'CiviCase' => ['entity_type' => 'case', 'label' => t('Case'), 'max_instances' => 30], + 'CiviCase' => ['entity_type' => 'case', 'label' => t('Case'), 'max_instances' => 50], 'CiviEvent' => ['entity_type' => 'participant', 'label' => t('Participant'), 'max_instances' => 9], 'CiviContribute' => ['entity_type' => 'contribution', 'label' => t('Contribution')], 'CiviMember' => ['entity_type' => 'membership', 'label' => t('Membership'), 'custom_fields' => 'combined'], @@ -260,11 +260,13 @@ protected function wf_crm_get_fields($var = 'fields') { 'type' => 'select', 'default_value' => $this->utils->wf_crm_get_civi_setting('lcMessages', 'en_US'), ]; - $default_communication_style = $this->utils->wf_crm_apivalues('OptionValue', 'get', [ - 'sequential' => 1, - 'option_group_id' => "communication_style", - 'is_default' => 1, - ], 'value')[0] ?? NULL; + $default_communication_style = $this->utils->wf_civicrm_api4('OptionValue', 'get', [ + 'where' => [ + ['option_group_id.name', '=', 'communication_style'], + ['is_default', '=', TRUE], + ], + 'select' => ['value'], + ])->first()['value'] ?? NULL; $fields['contact_communication_style_id'] = [ 'name' => t('Communication Style'), 'type' => 'select', diff --git a/src/Plugin/WebformElement/CivicrmContact.php b/src/Plugin/WebformElement/CivicrmContact.php index 310756f7b..10c6ea6c7 100644 --- a/src/Plugin/WebformElement/CivicrmContact.php +++ b/src/Plugin/WebformElement/CivicrmContact.php @@ -523,6 +523,7 @@ function wf_crm_results_display_options($contact_type) { 'state_province' => t("State/Province"), 'country' => t("Country"), 'postal_code' => t("Postal Code"), + 'street_address' => t("Street Address"), 'phone' => t("Phone"), ]; return $options; diff --git a/src/Plugin/WebformHandler/CivicrmWebformHandler.php b/src/Plugin/WebformHandler/CivicrmWebformHandler.php index 5c3a07911..556ba99ff 100644 --- a/src/Plugin/WebformHandler/CivicrmWebformHandler.php +++ b/src/Plugin/WebformHandler/CivicrmWebformHandler.php @@ -31,12 +31,20 @@ class CivicrmWebformHandler extends WebformHandlerBase { */ protected $civicrm; + /** + * The Token Manager service. + * + * @var \Drupal\webform\WebformTokenManager + */ + public $tokenManager; + /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); $instance->civicrm = $container->get('civicrm'); + $instance->tokenManager = $container->get('webform.token_manager'); return $instance; } diff --git a/src/Utils.php b/src/Utils.php index 4d67e12f8..f99c7437d 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -131,11 +131,15 @@ public function wf_crm_get_states($param = NULL) { * @return array */ function wf_crm_get_events($reg_options, $context) { - $ret = []; + static $ret = []; + if ($ret && $context !== 'config_form') { + return $ret; + } $format = wf_crm_aval($reg_options, 'title_display', 'title'); $sort_field = wf_crm_aval($reg_options, 'event_sort_field', 'start_date'); $sort_order = ($context == 'config_form' && $sort_field === 'start_date') ? ' DESC' : ''; $params = [ + 'return' => ['id', 'title', 'start_date', 'end_date', 'event_type_id', 'max_participants'], 'is_template' => 0, 'is_active' => 1, ]; @@ -628,9 +632,7 @@ function wf_civicrm_api4($entity, $operation, $params, $index = NULL) { if (!$entity) { return []; } - $params += [ - 'checkPermissions' => FALSE, - ]; + $params['checkPermissions'] = FALSE; $result = civicrm_api4($entity, $operation, $params, $index); return $result; } @@ -654,9 +656,7 @@ function wf_civicrm_api($entity, $operation, $params) { return []; } - $params += [ - 'check_permissions' => FALSE, - ]; + $params['check_permissions'] = FALSE; if ($operation == 'transact') { $utils = \Drupal::service('webform_civicrm.utils'); $result = $utils->wf_civicrm_api3_contribution_transact($params); diff --git a/src/WebformCivicrmBase.php b/src/WebformCivicrmBase.php index 55b20f5d1..2be773852 100644 --- a/src/WebformCivicrmBase.php +++ b/src/WebformCivicrmBase.php @@ -779,13 +779,18 @@ function addPaymentJs() { * Copies a drupal file into the Civi file system * * @param int $id: drupal file id + * @param string $filename drupal filename * @return int|null Civi file id */ - public static function saveDrupalFileToCivi($id) { + public static function saveDrupalFileToCivi($id, $filename = NULL) { $file = File::load($id); if ($file) { $config = \CRM_Core_Config::singleton(); - $path = \Drupal::service('file_system')->copy($file->getFileUri(), $config->customFileUploadDir); + $copyTo = $config->customFileUploadDir; + if(isset($filename)) { + $copyTo .= '/' . $filename; + } + $path = \Drupal::service('file_system')->copy($file->getFileUri(), $copyTo); if ($path) { $result = \Drupal::service('webform_civicrm.utils')->wf_civicrm_api('file', 'create', [ 'uri' => str_replace($config->customFileUploadDir, '', $path), diff --git a/src/WebformCivicrmPostProcess.php b/src/WebformCivicrmPostProcess.php index 9adfff5e3..90b8a864e 100644 --- a/src/WebformCivicrmPostProcess.php +++ b/src/WebformCivicrmPostProcess.php @@ -47,6 +47,11 @@ class WebformCivicrmPostProcess extends WebformCivicrmBase implements WebformCiv */ private $database; + /** + * @var \Drupal\webform_civicrm\Plugin\WebformHandler + */ + private $handler; + /** * @var \Drupal\webform\WebformSubmissionInterface */ @@ -85,10 +90,10 @@ function initialize(WebformSubmissionInterface $webform_submission) { $handler_collection = $this->node->getHandlers('webform_civicrm'); $instance_ids = $handler_collection->getInstanceIds(); - $handler = $handler_collection->get(reset($instance_ids)); + $this->handler = $handler_collection->get(reset($instance_ids)); $this->database = \Drupal::database(); - $this->settings = $handler->getConfiguration()['settings']; + $this->settings = $this->handler->getConfiguration()['settings']; $this->data = $this->settings['data']; $this->enabled = $this->utils->wf_crm_enabled_fields($this->node); $this->all_fields = $this->utils->wf_crm_get_fields(); @@ -1681,6 +1686,7 @@ private function processGrants() { * Calculate line-items for this webform submission */ private function tallyLineItems() { + $submittedFormValues = $this->form_state->getUserInput(); // Contribution $fid = 'civicrm_1_contribution_1_contribution_total_amount'; if (isset($this->enabled[$fid]) || $this->getData($fid) > 0) { @@ -1698,7 +1704,7 @@ private function tallyLineItems() { if (isset($this->enabled[$fid])) { foreach ($this->data['lineitem'][1]['contribution'] as $n => $lineitem) { $fid = "civicrm_1_lineitem_{$n}_contribution_line_total"; - if ($this->getData($fid) != 0) { + if (!isset($submittedFormValues[$fid]) || $this->getData($fid) != 0) { $this->line_items[] = [ 'qty' => 1, 'unit_price' => $lineitem['line_total'], @@ -1733,6 +1739,7 @@ private function tallyLineItems() { }; if ($price) { + $member_name = NULL; if (!empty($this->data['contact'][$c]['contact'][$n])) { $member_contact = $this->data['contact'][$c]['contact'][$n]; if (!empty($member_contact['first_name']) && !empty($member_contact['last_name'])) { @@ -2122,6 +2129,7 @@ private function submitIPNPayment() { } } } + // Ideally we would pass the correct id for the test processor through but that seems not to be the // case so load it here. if (!empty($params['is_test'])) { @@ -2131,6 +2139,28 @@ private function submitIPNPayment() { $i = $this->getContributionContactIndex(); $contact = $this->utils->wf_civicrm_api('contact', 'getsingle', ['id' => $this->ent['contact'][$i]['id']]); $params += $contact; + + // contact provides 'country' and 'country_id', but doPayment using PropertyBag expects 'billingCountry' with an iso_code + $countryName = $params['country'] ?? NULL; + $countryId = $params['country_id'] ?? NULL; + // providing country name throws deprecation warnings, + // which break the transaction so remove it + unset($params['country']); + + // country id seems more reliable, so use that first + if ($countryId) { + $params['billingCountry'] = $this->utils->wf_civicrm_api4('Country', 'get', [ + 'select' => ['iso_code'], + 'where' => [['id', '=', $countryId]] + ])->first()['iso_code'] ?? ''; + } + elseif ($countryName) { + $params['billingCountry'] = $this->utils->wf_civicrm_api4('Country', 'get', [ + 'select' => ['iso_code'], + 'where' => [['name', '=', $countryName]] + ])->first()['iso_code'] ?? ''; + } + $params['contributionID'] = $params['id'] = $this->ent['contribution'][1]['id']; if (!empty($this->ent['contribution_recur'][1]['id'])) { $params['is_recur'] = TRUE; @@ -2523,7 +2553,11 @@ private function fillDataFromSubmission() { } } elseif ($dataType == 'File') { - if (empty($val[0]) || !($val = $this->saveDrupalFileToCivi($val[0]))) { + // Replace filename (with tokens) if set. + if (isset($component['#file_name']) && $component['#file_name']) { + $newFilename = $this->handler->tokenManager->replace($component['#file_name'], $this->submission); + } + if (empty($val[0]) || !($val = $this->saveDrupalFileToCivi($val[0], $newFilename))) { // This field can't be emptied due to the nature of file uploads continue; } diff --git a/src/WebformCivicrmPreProcess.php b/src/WebformCivicrmPreProcess.php index 77d9a937e..762247727 100644 --- a/src/WebformCivicrmPreProcess.php +++ b/src/WebformCivicrmPreProcess.php @@ -574,7 +574,7 @@ private function fillForm(&$elements, $submitted = []) { if (!is_array($val) && !isset($element['#options'][$val])) { $val = NULL; } - if ((empty($val) || (is_array($val) && empty(array_filter($val)))) && !empty($this->form['#attributes']['data-form-defaults'])) { + if ((is_null($val) || (is_array($val) && empty(array_filter($val)))) && !empty($this->form['#attributes']['data-form-defaults'])) { $formDefaults = Json::decode($this->form['#attributes']['data-form-defaults']); $key = str_replace('_', '-', $element['#form_key']); if (isset($formDefaults[$key])) { diff --git a/tests/src/FunctionalJavascript/ExistingContactElementTest.php b/tests/src/FunctionalJavascript/ExistingContactElementTest.php index 8256239ce..fb0dc7b86 100644 --- a/tests/src/FunctionalJavascript/ExistingContactElementTest.php +++ b/tests/src/FunctionalJavascript/ExistingContactElementTest.php @@ -4,6 +4,9 @@ use Drupal\Core\Url; use Drupal\Core\Test\AssertMailTrait; +use Drupal\webform\Entity\WebformSubmission; +use Drupal\webform\Entity\Webform; +use Drupal\Core\Serialization\Yaml; /** * Tests submitting a Webform with CiviCRM: existing contact element. @@ -375,11 +378,18 @@ public function testTokensInEmail() { // Check if email was sent to contact 1. $this->assertStringContainsString('frederick@pabst.io', $sent_email[0]['to']); + // Something new in 10.3 + $weirdoExtraSpaces = version_compare(\Drupal::VERSION, '10.3.2', '>=') ? ' ' : ''; + // And now there is no longer a newline + $weirdoNewline = version_compare(\Drupal::VERSION, '10.3.2', '<') ? "\n" : ''; + // Verify tokens are rendered correctly. - $this->assertEquals("Submitted Values Are - + // We ignore newlines so that the length of the website's URL (appearing in + // $this->cidURL) doesn't cause a failure due to variations in line + // wrapping. + $this->assertEquals(strtr("Submitted Values Are - --------- Contact 1 ------------------------------------------------------------ +-------- Contact 1 {$weirdoNewline}----------------------------------------------------------- *Existing Contact* Frederick Pabst @@ -399,13 +409,626 @@ public function testTokensInEmail() { New Jersey *Email* frederick@pabst.io [1] -Existing Contact - Frederick Pabst. Activity 1 ID - {$actID1}. Activity 2 ID - {$actID2}. -Webform CiviCRM Contacts IDs - {$this->rootUserCid}. Webform CiviCRM Contacts Links - -{$cidURL} Country - United +Existing Contact - Frederick Pabst. Activity 1 ID - {$actID1}. Activity 2 ID - {$actID2}.{$weirdoExtraSpaces} +Webform CiviCRM Contacts IDs - {$this->rootUserCid}. Webform CiviCRM Contacts Links -{$weirdoExtraSpaces} +{$cidURL} Country - United{$weirdoExtraSpaces} States. State/Province - New Jersey. [1] mailto:frederick@pabst.io -", $sent_email[0]['body']); +", "\n", ' '), strtr($sent_email[0]['body'], "\n", ' ')); + } + + /** + * Define test-contact parameters and create a subset of them in Civi. + * + * @return array + * contains parameter arrays for each test-contact + */ + private function addcontactinfo2() { + $contact = [ + 0 => [ // cid = 3 (will overwrite existing contact) + 'contact_id' => 3, + 'first_name' => 'Jimmy', + 'last_name' => 'Page', + 'job_title' => "Guitarist", + 'contact_type' => 'Individual' + ], + 1 => [ // cid = 4 + 'first_name' => 'Robert', + 'last_name' => 'Plant', + 'job_title' => "Vocalist", + 'contact_type' => 'Individual' + ], + 2 => [ // cid = 5 + 'first_name' => 'John Paul', + 'last_name' => 'Jones', + 'job_title' => "Bassist", + 'contact_type' => 'Individual' + ], + 3 => [ // cid = 6 + 'first_name' => 'John', + 'last_name' => 'Bonham', + 'job_title' => "Drummer", + 'contact_type' => 'Individual' + ], + 4 => [ // cid = 7 + 'first_name' => 'Janis', + 'last_name' => 'Joplin', + 'job_title' => "Singer", + 'contact_type' => 'Individual' + ], + 5 => [ // not initiallly created + 'first_name' => 'Marvin', + 'last_name' => 'Gaye', + 'job_title' => "Vocals", + 'contact_type' => 'Individual' + ], + 6 => [ // not initiallly created + 'first_name' => 'Bob', + 'last_name' => 'Dylan', + 'job_title' => "Vocals, Harmonica", + 'contact_type' => 'Individual' + ], + 7 => [ // null contact, not initiallly created + 'first_name' => '', + 'last_name' => '', + 'job_title' => '', + 'contact_type' => 'Individual' + ], + 8 => [ // cid = 8 + 'first_name' => 'Prince', + 'last_name' => '', + 'job_title' => "Guitar, vocals", + 'contact_type' => 'Individual' + ], + 9 => [ // cid = 9 + 'first_name' => 'Madona', + 'last_name' => '', + 'job_title' => "Vocals, drummer", + 'contact_type' => 'Individual' + ], + ]; + $utils = \Drupal::service('webform_civicrm.utils'); + foreach ($contact as $key => $c) { + if (in_array($key, [0, 1, 2, 3, 4, 8, 9])) { + $result = $utils->wf_civicrm_api('Contact', 'create', $c); + $this->assertEquals(0, $result['is_error']); + $this->assertEquals(1, $result['count']); + } + } + return $contact; + } + + /** + * Sets the contact fields used by testNextPrevSaveLoad() + * + * @param array $contact + * contact parameters to be set + */ + private function setContactFields($contact) { + $this->getSession()->getPage()->fillField('First Name', $contact['first_name']); + $this->getSession()->getPage()->fillField('Last Name', $contact['last_name']); + $this->getSession()->getPage()->fillField('Job Title', $contact['job_title']); + } + + /** + * Checks the contact fields used by testNextPrevSaveLoad() + * + * @param array $contact + * contact parameters to be checked + */ + private function checkContactFields($contact) { + $this->assertSession()->fieldValueEquals('First Name', $contact['first_name']); + $this->assertSession()->fieldValueEquals('Last Name', $contact['last_name']); + $this->assertSession()->fieldValueEquals('Job Title', $contact['job_title']); } + /** + * Test locked/unlocked and blank/filled fields during Next/Previous/Save Draft/Load Draft/Submit operations + */ + public function testNextPrevSaveLoad() { + if (version_compare(\Drupal::VERSION, '10.3', '>=')) { + $this->markTestSkipped('retrieving $elements gives blank in 10.3 for some reason'); + return; + } + + $contact = $this->addcontactinfo2(); + + $this->drupalLogin($this->rootUser); + + $this->drupalGet(Url::fromRoute('entity.webform.civicrm', [ + 'webform' => $this->webform->id(), + ])); + $this->enableCivicrmOnWebform(); + + // Enable 3 contacts each with first name, last name, job title + $this->getSession()->getPage()->selectFieldOption("number_of_contacts", 3); + foreach ([1, 2, 3] as $c) { + $this->getSession()->getPage()->clickLink("Contact {$c}"); + $this->getSession()->getPage()->checkField("civicrm_{$c}_contact_1_contact_existing"); + $this->assertSession()->checkboxChecked("civicrm_{$c}_contact_1_contact_existing"); + $this->getSession()->getPage()->checkField("civicrm_{$c}_contact_1_contact_job_title"); + $this->assertSession()->checkboxChecked("civicrm_{$c}_contact_1_contact_job_title"); + } + + $this->saveCiviCRMSettings(); + + $this->drupalGet($this->webform->toUrl('edit-form')); + + // Edit contact element 1. + $editContact = [ + 'selector' => 'edit-webform-ui-elements-civicrm-1-contact-1-contact-existing-operations', + 'title' => 'Contact 1', + 'widget' => 'Select List', + 'hide_fields' => 'Name', + 'hide_method' => 'Disabled', + 'no_hide_blank' => TRUE, + 'submit_disabled' => TRUE, + 'default' => 'Specified Contact', + 'default_contact_id' => 3 + ]; + $this->editContactElement($editContact); + + // Edit contact element 2. + $editContact = [ + 'selector' => 'edit-webform-ui-elements-civicrm-2-contact-1-contact-existing-operations', + 'title' => 'Contact 2', + 'widget' => 'Select List', + 'hide_fields' => 'Name', + 'hide_method' => 'Disabled', + 'no_hide_blank' => TRUE, + 'submit_disabled' => TRUE, + 'default' => 'None', + //'default_contact_id' => 4 + ]; + $this->editContactElement($editContact); + + // Edit contact element 3. + $editContact = [ + 'selector' => 'edit-webform-ui-elements-civicrm-3-contact-1-contact-existing-operations', + 'title' => 'Contact 3', + 'widget' => 'Select List', + 'hide_fields' => 'Name', + 'hide_method' => 'Disabled', + 'no_hide_blank' => TRUE, + 'submit_disabled' => TRUE, + 'default' => 'Specified Contact', + 'default_contact_id' => 5 + ]; + $this->editContactElement($editContact); + + // Make first/last name required for all contacts + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_1_contact_1_contact_first_name][required]"); + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_2_contact_1_contact_first_name][required]"); + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_3_contact_1_contact_first_name][required]"); + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_1_contact_1_contact_last_name][required]"); + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_2_contact_1_contact_last_name][required]"); + $this->getSession()->getPage()->checkField("webform_ui_elements[civicrm_3_contact_1_contact_last_name][required]"); + $this->getSession()->getPage()->pressButton('Save elements'); + $this->assertSession()->assertWaitOnAjaxRequest(); + + $this->drupalGet($this->webform->toUrl('edit-form')); + $this->htmlOutput(); + + // Place fields for each contact on their own page and enable saving drafts + $webform = Webform::load($this->webform->getOriginalId()); + $elements = Yaml::decode($webform->get('elements')); + $elements_new = [ + 'page1' => ['#type' => 'webform_wizard_page', '#title' => 'Page 1', 'civicrm_1_contact_1_fieldset_fieldset' => $elements["civicrm_1_contact_1_fieldset_fieldset"]], + 'page2' => ['#type' => 'webform_wizard_page', '#title' => 'Page 2', 'civicrm_2_contact_1_fieldset_fieldset' => $elements["civicrm_2_contact_1_fieldset_fieldset"]], + 'page3' => ['#type' => 'webform_wizard_page', '#title' => 'Page 3', 'civicrm_3_contact_1_fieldset_fieldset' => $elements["civicrm_3_contact_1_fieldset_fieldset"]], + ]; + $webform->set('elements', Yaml::encode($elements_new)); + $webform->setSetting('draft', 'all'); + $webform->save(); + + $this->drupalGet($this->webform->toUrl('edit-form')); + $this->htmlOutput(); + + $this->drupalGet($this->webform->toUrl('canonical')); + + $this->assertPageNoErrorMessages(); + $this->htmlOutput(); + + + //** Setup complete Begin tests. ** + // "{Contacts: x, y, z}" below refers to the current form contents (three elements of $contacts[] array) + + // Page 1 {Contacts: 0, none, 2}: Check initial values. + $this->checkContactFields($contact[0]); + + // Confirm first name is disabled + $field_disabled = $this->getSession()->evaluateScript("document.getElementById('edit-civicrm-1-contact-1-contact-first-name').disabled"); + $this->assertEquals(true, $field_disabled, 'First name is disabled'); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 0, none, 2}: Check initial values. + $this->checkContactFields($contact[7]); // 7 is the blank contact + + // Page 2 {Contacts: 0, none, 2}: Confirm that locked blank fields can be modified + $this->getSession()->getPage()->fillField('First Name', 'FIRST'); + $this->assertSession()->fieldValueEquals('First Name', 'FIRST'); + + // Page 2 {Contacts: 0, none, 2}: Select $contact[1]. + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[1]['first_name']} {$contact[1]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[1]); + + // Page 2 {Contacts: 0, 1, 2}: Test that locked nonblank fields are disabled. + $field_disabled = $this->getSession()->evaluateScript("document.getElementById('edit-civicrm-2-contact-1-contact-first-name').disabled"); + $this->assertEquals(true, $field_disabled, 'First name is disabled'); + $this->getSession()->getPage()->pressButton('Next >'); + return; // @TODO: Additional parts of this test will be enabled in susbequent PRs + $this->assertPageNoErrorMessages(); + + // Page 3 {Contacts: 0, 1, 2}: Check initial values. + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 0, 1, 2}: Check entered contact data ($contact[1]). + $this->checkContactFields($contact[1]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 0, 1, 2}: check initial values. + $this->checkContactFields($contact[0]); + + // Page 1 {Contacts: 0, 1, 2}: Select $contact[3] + $this->getSession()->getPage()->selectFieldOption('civicrm_1_contact_1_contact_existing', "{$contact[3]['first_name']} {$contact[3]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 1, 2}: Check still has $contact[1] + $this->checkContactFields($contact[1]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1: {Contacts: 3, 1, 2}: Check still has $contact[3] + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 1, 2}: Check still has $contact[1] + $this->checkContactFields($contact[1]); + + // Page 2 {Contacts: 3, 1, 2}: Create a new contact ($contact[4]) + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "+ Create new +"); + $this->setContactFields($contact[4]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 3, 4, 2}: check still has $contact[3] + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 4, 2}: Check still has $contact[4] + $this->checkContactFields($contact[4]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 4, 2}: Check initial state + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 3, 4, 2}: check still has $contact[4] + $this->checkContactFields($contact[4]); + + // Page 2 {Contacts: 3, 4, 2}: Create a new contact ($contact[5]) + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "+ Create new +"); + $this->setContactFields($contact[5]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 5, 2}: Check initial state + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 3, 5, 2}: check still has $contact[5] + $this->checkContactFields($contact[5]); + + // Page 2 {Contacts: 3, 5, 2}: Create a new contact ($contact[6]) + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "+ Create new +"); + $this->setContactFields($contact[6]); + + // Page 2 {Contacts: 3, 6, 2}: Save draft + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + + // Page 2 {Contacts: 3, 6, 2}: Reload form, check still has $contact[6] + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + $this->checkContactFields($contact[6]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 3, 6, 2}: Check still has $contact[3] + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 6, 2}: Check still has $contact[6] + $this->checkContactFields($contact[6]); + + + //*** Test sequence: modify, prev, save draft, load, next, next, *** + // Page 2 {Contacts: 3, 6, 2}: Select $contact[1] + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[1]['first_name']} {$contact[1]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[1]); + + // Page 2 {Contacts: 3, 6, 2}: Modify the job field + $contact['1m'] = $contact[1]; + $contact['1m']['job_title'] = 'MODIFIED JOB TITLE 1'; + $this->getSession()->getPage()->fillField('Job Title', $contact['1m']['job_title']); + $this->getSession()->getPage()->pressButton('< Prev'); + $this->checkContactFields($contact[3]); + + // Page 1 {Contacts: 3, 1m, 2}: Save/load the draft + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + + // Page 1 {Contacts: 3, 1m, 2}: Confirm contact + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 1m, 2}: Confirm modified contact + $this->checkContactFields($contact['1m']); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 1m, 2}: Confirm the job is still modified + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 3, 1m, 2}: Confirm the contact + $this->checkContactFields($contact['1m']); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 3, 1m, 2}: Confirm the contact + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + + //*** Test sequence: modify, next, save, load draft, prev, prev, next, next *** + // Page 2 {Contacts: 3, 6, 2}: Select $contact[1] (must first select a different $contact) + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[0]['first_name']} {$contact[0]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[1]['first_name']} {$contact[1]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[1]); + + // Page 2 {Contacts: 3, 6, 2}: Modify the job field + $contact['1m'] = $contact[1]; + $contact['1m']['job_title'] = 'MODIFIED JOB TITLE 1A'; + $this->getSession()->getPage()->fillField('Job Title', $contact['1m']['job_title']); + $this->getSession()->getPage()->pressButton('Next >'); + $this->checkContactFields($contact[2]); + + // Page 3 {Contacts: 3, 1m, 2}: Save/load the draft + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + + // Page 3 {Contacts: 3, 1m, 2}: Confirm contact + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 3, 1m, 2}: Confirm modified contact + $this->checkContactFields($contact['1m']); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 3, 1m, 2}: Confirm the job is still modified + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 3, 1m, 2}: Confirm the contact + $this->checkContactFields($contact['1m']); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 1m, 2}: Confirm the job is still modified + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + + // Page 2 {Contacts: 3, 6, 2}: Select $contact[4] + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[4]['first_name']} {$contact[4]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[4]); + + // Page 2 {Contacts: 3, 4, 2}: Save draft + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + + // Page 2 {Contacts: 3, 4, 2}: Reload form, check still has $contact[4] + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + $this->checkContactFields($contact[4]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 4, 2}: Check initial state + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 2 {Contacts: 3, 4, 2}: Check still has $contact[4] + $this->checkContactFields($contact[4]); + + // Page 2 {Contacts: 3, 4, 2}: Create a new contact ($contact[5]) + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "+ Create new +"); + $this->setContactFields($contact[5]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 3, 5, 2}: Check initial state + $this->checkContactFields($contact[2]); + + // Page 3 {Contacts: 3, 5, 2}: create a new contact ($contact[6]) + $this->getSession()->getPage()->selectFieldOption('civicrm_3_contact_1_contact_existing', "+ Create new +"); + $this->setContactFields($contact[6]); + + // Page 3 {Contacts: 3, 5, 6}: Submit + $this->getSession()->getPage()->pressButton('Submit'); + $this->assertPageNoErrorMessages(); + $this->assertSession()->pageTextContains('New submission added to CiviCRM Webform Test.'); + + // Confirm existing $contact[3] is unchanged, and $contact[5,6] have been created in Civi + foreach ([3,5,6] as $key) { + $result = $this->utils->wf_civicrm_api('Contact', 'get', [ + 'first_name' => $contact[$key]['first_name'], + 'last_name' => $contact[$key]['last_name'], + 'job_title' => $contact[$key]['job_title'], + ]); + $this->assertEquals(0, $result['is_error']); + $this->assertEquals(1, $result['count']); + } + + + //*** Check handling of existing contact with blank required field *** + $this->drupalGet($this->webform->toUrl('canonical')); + + // Page 1 {Contacts: 0, none, 2}: Check initial values. + $this->assertSession()->pageTextContains('You have already submitted this webform. View your previous submission.'); + $this->checkContactFields($contact[0]); + + // Page 1 {Contacts: 0, none, 2}: Select $contact[8] (no last name) + $this->getSession()->getPage()->selectFieldOption('civicrm_1_contact_1_contact_existing', "{$contact[8]['first_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[8]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 1 {Contacts: 8, none, 2}: Still on Page 1 because Last Name is blank and required + $this->checkContactFields($contact[8]); + $field_valid = $this->getSession()->evaluateScript("document.getElementById('edit-civicrm-1-contact-1-contact-last-name').reportValidity()"); + $this->assertEquals(false, $field_valid, 'Last Name field is not invalid.'); + + $contact['8m'] = $contact[8]; + $contact['8m']['last_name'] = 'CONTACT 8 LAST NAME'; + $this->getSession()->getPage()->fillField('Last Name', $contact['8m']['last_name']); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 8m, none, 2}: Check $contact[7] (null contact) + $this->checkContactFields($contact[7]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 8m, none, 2}: Check $contact[8m] + $this->checkContactFields($contact['8m']); + + + //*** Check Draft Save/Load with blank required field *** + $this->drupalGet($this->webform->toUrl('canonical')); + + // Page 1 {Contacts: 0, none, 2}: Check initial values. + $this->assertSession()->pageTextContains('You have already submitted this webform. View your previous submission.'); + $this->checkContactFields($contact[0]); + + // Page 1 {Contacts: 0, none, 2}: Select $contact[8] (no last name) + $this->getSession()->getPage()->selectFieldOption('civicrm_1_contact_1_contact_existing', "{$contact[8]['first_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[8]); + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + + // Page 1 {Contacts: 8, none, 2}: Reload form, check still has $contact[8] + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + $this->checkContactFields($contact[8]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 1 {Contacts: 8, none, 2}: Still on Page 1 because Last Name is blank and required + $this->checkContactFields($contact[8]); + $field_valid = $this->getSession()->evaluateScript("document.getElementById('edit-civicrm-1-contact-1-contact-last-name').reportValidity()"); + $this->assertEquals(false, $field_valid, 'Last Name field is not invalid.'); + + // Page 1 {Contacts: 8, none, 2}: Add last name to $contact[8] + $contact['8m'] = $contact[8]; + $contact['8m']['last_name'] = 'CONTACT 8 LAST NAME'; + $this->getSession()->getPage()->fillField('Last Name', $contact['8m']['last_name']); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 8m, none, 2}: Check $contact[7] (null contact) + $this->checkContactFields($contact[7]); + $this->getSession()->getPage()->pressButton('< Prev'); + + // Page 1 {Contacts: 8m, none, 2}: Check $contact[8m] + $this->checkContactFields($contact['8m']); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 8m, none, 2}: Check $contact[7] (null contact) + $this->checkContactFields($contact[7]); + + // Page 2 {Contacts: 8m, none, 2}: Select $contact[5] + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[5]['first_name']} {$contact[5]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 8m, 5, 2}: Check initial state + $this->checkContactFields($contact[2]); + + // Page 3 {Contacts: 8m, 5, 2}: Select $contact[9] and submit + $this->getSession()->getPage()->selectFieldOption('civicrm_3_contact_1_contact_existing', "{$contact[9]['first_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact['9']); + $this->getSession()->getPage()->pressButton('Submit'); + + // Page 3 {Contacts: 8m, 5, 9}: Still on Page 3 because Last Name is blank and required + $this->checkContactFields($contact['9']); + $field_valid = $this->getSession()->evaluateScript("document.getElementById('edit-civicrm-3-contact-1-contact-last-name').reportValidity()"); + $this->assertEquals(false, $field_valid, 'Last Name field is not invalid.'); + + // Page 3 {Contacts: 8m, 5, 9}: Add last name and submit + $contact['9m'] = $contact[9]; + $contact['9m']['last_name'] = 'CONTACT 9 LAST NAME'; + $this->getSession()->getPage()->fillField('Last Name', $contact['9m']['last_name']); + $this->getSession()->getPage()->pressButton('Submit'); + $this->htmlOutput(); + + // Page 3 {Contacts: 8m, 5, 9m}: Confirm submit OK + $this->assertPageNoErrorMessages(); + $this->assertSession()->pageTextContains('New submission added to CiviCRM Webform Test.'); + + // Confirm existing $contact[5] is unchanged, and $contact[8,9] now have a last name. + foreach (['8m', 5, '9m'] as $key) { + $result = $this->utils->wf_civicrm_api('Contact', 'get', [ + 'first_name' => $contact[$key]['first_name'], + 'last_name' => $contact[$key]['last_name'], + 'job_title' => $contact[$key]['job_title'], + ]); + $this->assertEquals(0, $result['is_error']); + $this->assertEquals(1, $result['count']); + } + + + //*** Check Draft Save/Load, change selected contact, Submit *** + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertPageNoErrorMessages(); + + // Page 1 {Contacts: 0, none, 2}: Check initial values. + $this->checkContactFields($contact[0]); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 2 {Contacts: 0, none, 2}: Check initial values. + $this->checkContactFields($contact[7]); + + // Page 2 {Contacts: 0, none, 2}: Select $contact[5] + $this->getSession()->getPage()->selectFieldOption('civicrm_2_contact_1_contact_existing', "{$contact[5]['first_name']} {$contact[5]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->getSession()->getPage()->pressButton('Next >'); + + // Page 3 {Contacts: 0, 5, 2}: Check initial state, select $contact[3], save draft + $this->checkContactFields($contact[2]); + $this->getSession()->getPage()->selectFieldOption('civicrm_3_contact_1_contact_existing', "{$contact[3]['first_name']} {$contact[3]['last_name']}"); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Save Draft'); + $this->checkContactFields($contact[3]); + $this->assertSession()->pageTextContains('Submission saved. You may return to this form later and it will restore the current values.'); + $this->htmlOutput(); + + // Page 3 {Contacts: 0, 5, 3}: Reload form, check still has $contact[3] and submit + $this->drupalGet($this->webform->toUrl('canonical')); + $this->assertSession()->pageTextContains('A partially-completed form was found. Please complete the remaining portions.'); + $this->checkContactFields($contact[3]); + $this->getSession()->getPage()->pressButton('Submit'); + $this->assertPageNoErrorMessages(); + $this->assertSession()->pageTextContains('New submission added to CiviCRM Webform Test.'); + + $submission = WebformSubmission::load($this->getLastSubmissionId($this->webform)); + $sub_data = $submission->getData(); + $this->assertEquals($contact[3]['first_name'], $sub_data['civicrm_3_contact_1_contact_first_name'], 'Submission first name'); + $this->assertEquals($contact[3]['last_name'], $sub_data['civicrm_3_contact_1_contact_last_name'], 'Submission last name'); + $this->assertEquals($contact[3]['job_title'], $sub_data['civicrm_3_contact_1_contact_job_title'], 'Submission job title name'); + } } diff --git a/tests/src/FunctionalJavascript/MembershipSubmissionTest.php b/tests/src/FunctionalJavascript/MembershipSubmissionTest.php index 45adccadd..29e7db2e8 100644 --- a/tests/src/FunctionalJavascript/MembershipSubmissionTest.php +++ b/tests/src/FunctionalJavascript/MembershipSubmissionTest.php @@ -122,11 +122,12 @@ public function testSubmitWebform() { $this->saveCiviCRMSettings(); + $adminUserCid = $this->getUFMatchRecord($this->adminUser->id())['contact_id']; // Create two memberships with the same status with the first membership // having an end date after the second membership's end date. $this->utils->wf_civicrm_api('membership', 'create', [ 'membership_type_id' => 'Basic', - 'contact_id' => 2, + 'contact_id' => $adminUserCid, 'join_date' => '08/10/21', 'start_date' => '08/10/21', 'end_date' => '08/10/22', @@ -136,7 +137,7 @@ public function testSubmitWebform() { $this->utils->wf_civicrm_api('membership', 'create', [ 'membership_type_id' => 'Basic', - 'contact_id' => 2, + 'contact_id' => $adminUserCid, 'join_date' => '01/01/21', 'start_date' => '01/01/21', 'end_date' => '01/01/22', @@ -221,11 +222,13 @@ public function testSubmitMembershipQueryParams() { $fieldset->click(); $this->getSession()->getPage()->fillField('Default value', '[current-page:query:membership]'); $this->getSession()->getPage()->pressButton('Save'); + $this->assertSession()->assertWaitOnAjaxRequest(); + + $this->getSession()->getPage()->pressButton('Save elements'); $this->drupalLogout(); $this->drupalGet($this->webform->toUrl('canonical', ['query' => ['membership' => 2]])); $this->htmlOutput(); - // ToDo -> $this->assertPageNoErrorMessages(); $this->assertSession()->waitForField('First Name'); @@ -234,7 +237,6 @@ public function testSubmitMembershipQueryParams() { $this->assertSession()->pageTextContains('Basic Plus'); $this->getSession()->getPage()->pressButton('Submit'); $this->htmlOutput(); - // ToDo -> $this->assertPageNoErrorMessages(); $this->assertSession()->pageTextContains('New submission added to CiviCRM Webform Test.'); diff --git a/tests/src/FunctionalJavascript/StripeTest.php b/tests/src/FunctionalJavascript/StripeTest.php index af7dd9683..400f8e473 100644 --- a/tests/src/FunctionalJavascript/StripeTest.php +++ b/tests/src/FunctionalJavascript/StripeTest.php @@ -19,13 +19,7 @@ protected function setUp(): void { $this->setUpExtension('mjwshared,firewall,mjwpaymentapi,com.drastikbydesign.stripe'); - $params = []; - $result = $this->utils->wf_civicrm_api('Stripe', 'setuptest', $params); - $this->paymentProcessorID = $result['id']; - $this->utils->wf_civicrm_api('PaymentProcessor', 'create', [ - 'id' => $this->paymentProcessorID, - 'is_test' => 0, - ]); + $this->paymentProcessorID = $this->createStripeProcessor(); $this->utils->wf_civicrm_api('Setting', 'create', [ 'stripe_nobillingaddress' => 1, @@ -38,13 +32,14 @@ protected function setUp(): void { * Verifies the payment with 1 contribution and 2 line item amounts. */ public function testSubmitContribution() { - $this->markTestSkipped('Test Keys Expired.'); $this->drupalLogin($this->adminUser); $this->drupalGet(Url::fromRoute('entity.webform.civicrm', [ 'webform' => $this->webform->id(), ])); $this->setUpSettings(); + $this->drupalLogout(); + $this->drupalGet($this->webform->toUrl('canonical')); $this->assertPageNoErrorMessages(); $edit = [ @@ -78,7 +73,6 @@ public function testSubmitContribution() { * Test webform submission using stripe processor with AJAX enabled. */ public function testAjaxSubmitContribution() { - $this->markTestSkipped('Test Keys Expired.'); // Stripe payment logs a console ajax error. $this->failOnJavascriptConsoleErrors = FALSE; @@ -220,4 +214,29 @@ protected function setUpSettings() { $this->saveCiviCRMSettings(); } + private function createStripeProcessor(): int { + $params = [ + 'name' => 'Stripe', + 'domain_id' => \CRM_Core_Config::domainID(), + 'payment_processor_type_id' => 'Stripe', + 'title' => 'Stripe', + 'is_active' => 1, + 'is_default' => 0, + 'is_test' => 0, + 'is_recur' => 1, + 'user_name' => \CRM_Utils_Constant::value('STRIPE_PK_TEST', 'pk_test_PNlMrGPvqOxwLK6Y3A9B2EFn'), + 'password' => \CRM_Utils_Constant::value('STRIPE_SK_TEST', 'sk_test_WHbZbmFH97YpY2y4OpVfry9W'), + 'url_site' => 'https://api.stripe.com/v1', + 'url_recur' => 'https://api.stripe.com/v1', + 'class_name' => 'Payment_Stripe', + 'billing_mode' => 1 + ]; + // First see if it already exists. + $result = $this->utils->wf_civicrm_api('PaymentProcessor', 'get', $params); + if ($result['count'] != 1) { + $result = $this->utils->wf_civicrm_api('PaymentProcessor', 'create', $params); + } + return $result['id']; + } + } diff --git a/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php b/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php index 2ee8763ee..7a46c10e9 100644 --- a/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php +++ b/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php @@ -13,6 +13,7 @@ abstract class WebformCivicrmTestBase extends CiviCrmTestBase { use WebformBrowserTestTrait; use \Drupal\Tests\mink_civicrm_helpers\Traits\Utils; + use \Drupal\Tests\system\Traits\OffCanvasTestTrait; /** * {@inheritdoc} @@ -23,6 +24,7 @@ abstract class WebformCivicrmTestBase extends CiviCrmTestBase { 'webform_civicrm', 'token', 'ckeditor5', + 'off_canvas_test', 'mink_civicrm_helpers', ]; @@ -102,13 +104,18 @@ protected function setUp(): void { 'id' => 'civicrm_webform_test', 'title' => 'CiviCRM Webform Test.' . $CiviCRM_version, ]); - $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, - ]); + 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 { @@ -350,11 +357,13 @@ public function assertFieldValue($selector, $value, $isRadio = FALSE) { * 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) { - $checkbox_edit_button = $this->assertSession()->elementExists('css', '[data-drupal-selector="' . $selector . '"] a.webform-ajax-link'); + 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->assertSession()->waitForField('drupal-off-canvas'); + $this->waitForOffCanvasArea(); $this->htmlOutput(); if ($type) { $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-change-type"]')->click(); @@ -521,6 +530,9 @@ protected function editContactElement($params) { 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]"); } @@ -556,6 +568,10 @@ protected function editContactElement($params) { $this->assertSession()->elementExists('css', '[data-drupal-selector="edit-contact-defaults"]')->click(); $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->getSession()->getPage()->selectFieldOption('properties[default_relationship][]', $params['default_relationship']['default_relationship']); @@ -584,6 +600,13 @@ protected function editContactElement($params) { $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'); } diff --git a/tests/src/Kernel/FieldOptionsTest.php b/tests/src/Kernel/FieldOptionsTest.php deleted file mode 100644 index abbd5a008..000000000 --- a/tests/src/Kernel/FieldOptionsTest.php +++ /dev/null @@ -1,67 +0,0 @@ -getDatabaseConnectionInfo()['default']); - - } - - protected function setUp(): void { - $this->markTestSkipped('Requires MySQL'); - parent::setUp(); - - module_load_install('civicrm'); - civicrm_install(); - - $this->container->get('civicrm')->initialize(); - } - - /** - * {@inheritdoc} - */ - protected function tearDown(): void { - $conn = Database::getConnection('default', 'civicrm_test'); - $database = $conn->getConnectionOptions()['database']; - // Todo: get this working when db name passed in as an argument. - $conn->query("DROP DATABASE $database"); - $conn->destroy(); - parent::tearDown(); - } - - /** - * @dataProvider getDataprovider - */ - public function testGet(array $field, string $context, array $data) { - $field_options = $this->container->get('webform_civicrm.field_options'); - $options = $field_options->get($field, $context, $data); - } - - public static function getDataprovider() { - yield [ - ['form_key' => 'civicrm_1_contact_1_email_email'], - 'live_options', - [] - ]; - } - -}