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/tests/src/FunctionalJavascript/ExistingContactElementTest.php b/tests/src/FunctionalJavascript/ExistingContactElementTest.php index 80e0cf1e2..3f13ec097 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. @@ -384,7 +387,10 @@ public function testTokensInEmail() { $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 {$weirdoNewline}----------------------------------------------------------- @@ -412,7 +418,615 @@ public function testTokensInEmail() { 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() { + $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/WebformCivicrmTestBase.php b/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php index 3589c275f..40dd7d41d 100644 --- a/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php +++ b/tests/src/FunctionalJavascript/WebformCivicrmTestBase.php @@ -525,6 +525,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]"); } @@ -561,6 +564,10 @@ protected function editContactElement($params) { $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(); @@ -590,6 +597,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'); }