annotate core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@17 1 <?php
Chris@17 2
Chris@17 3 namespace Drupal\FunctionalJavascriptTests\Ajax;
Chris@17 4
Chris@17 5 use Drupal\Component\Render\FormattableMarkup;
Chris@17 6 use Drupal\Core\Field\FieldStorageDefinitionInterface;
Chris@17 7 use Drupal\field\Entity\FieldConfig;
Chris@17 8 use Drupal\field\Entity\FieldStorageConfig;
Chris@17 9 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
Chris@17 10
Chris@17 11 /**
Chris@17 12 * Tests that AJAX-enabled forms work when multiple instances of the same form
Chris@17 13 * are on a page.
Chris@17 14 *
Chris@17 15 * @group Ajax
Chris@17 16 */
Chris@17 17 class MultiFormTest extends WebDriverTestBase {
Chris@17 18
Chris@17 19 /**
Chris@17 20 * {@inheritdoc}
Chris@17 21 */
Chris@17 22 public static $modules = ['node', 'form_test'];
Chris@17 23
Chris@17 24 /**
Chris@17 25 * {@inheritdoc}
Chris@17 26 */
Chris@17 27 protected function setUp() {
Chris@17 28 parent::setUp();
Chris@17 29
Chris@17 30 $this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']);
Chris@17 31
Chris@17 32 // Create a multi-valued field for 'page' nodes to use for Ajax testing.
Chris@17 33 $field_name = 'field_ajax_test';
Chris@17 34 FieldStorageConfig::create([
Chris@17 35 'entity_type' => 'node',
Chris@17 36 'field_name' => $field_name,
Chris@17 37 'type' => 'text',
Chris@17 38 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
Chris@17 39 ])->save();
Chris@17 40 FieldConfig::create([
Chris@17 41 'field_name' => $field_name,
Chris@17 42 'entity_type' => 'node',
Chris@17 43 'bundle' => 'page',
Chris@17 44 ])->save();
Chris@17 45 entity_get_form_display('node', 'page', 'default')
Chris@17 46 ->setComponent($field_name, ['type' => 'text_textfield'])
Chris@17 47 ->save();
Chris@17 48
Chris@17 49 // Log in a user who can create 'page' nodes.
Chris@17 50 $this->drupalLogin($this->drupalCreateUser(['create page content']));
Chris@17 51 }
Chris@17 52
Chris@17 53 /**
Chris@17 54 * Tests that pages with the 'node_page_form' included twice work correctly.
Chris@17 55 */
Chris@17 56 public function testMultiForm() {
Chris@17 57 // HTML IDs for elements within the field are potentially modified with
Chris@17 58 // each Ajax submission, but these variables are stable and help target the
Chris@17 59 // desired elements.
Chris@17 60 $field_name = 'field_ajax_test';
Chris@17 61
Chris@17 62 $form_xpath = '//form[starts-with(@id, "node-page-form")]';
Chris@17 63 $field_xpath = '//div[contains(@class, "field--name-field-ajax-test")]';
Chris@17 64 $button_name = $field_name . '_add_more';
Chris@17 65 $button_value = t('Add another item');
Chris@17 66 $button_xpath_suffix = '//input[@name="' . $button_name . '"]';
Chris@17 67 $field_items_xpath_suffix = '//input[@type="text"]';
Chris@17 68
Chris@17 69 // Ensure the initial page contains both node forms and the correct number
Chris@17 70 // of field items and "add more" button for the multi-valued field within
Chris@17 71 // each form.
Chris@17 72 $this->drupalGet('form-test/two-instances-of-same-form');
Chris@17 73
Chris@17 74 // Wait for javascript on the page to prepare the form attributes.
Chris@17 75 $this->assertSession()->assertWaitOnAjaxRequest();
Chris@17 76
Chris@17 77 $session = $this->getSession();
Chris@17 78 $page = $session->getPage();
Chris@17 79 $fields = $page->findAll('xpath', $form_xpath . $field_xpath);
Chris@17 80 $this->assertEqual(count($fields), 2);
Chris@17 81 foreach ($fields as $field) {
Chris@17 82 $this->assertCount(1, $field->findAll('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items on the initial page.');
Chris@17 83 $this->assertFieldsByValue($field->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.');
Chris@17 84 }
Chris@17 85
Chris@17 86 $this->assertNoDuplicateIds();
Chris@17 87
Chris@17 88 // Submit the "add more" button of each form twice. After each corresponding
Chris@17 89 // page update, ensure the same as above.
Chris@17 90
Chris@17 91 for ($i = 0; $i < 2; $i++) {
Chris@17 92 $forms = $page->find('xpath', $form_xpath);
Chris@17 93 foreach ($forms as $offset => $form) {
Chris@17 94 $button = $form->findButton($button_value);
Chris@17 95 $this->assertNotNull($button, 'Add Another Item button exists');
Chris@17 96 $button->press();
Chris@17 97
Chris@17 98 // Wait for page update.
Chris@17 99 $this->assertSession()->assertWaitOnAjaxRequest();
Chris@17 100
Chris@17 101 // After AJAX request and response page will update.
Chris@17 102 $page_updated = $session->getPage();
Chris@17 103 $field = $page_updated->findAll('xpath', '.' . $field_xpath);
Chris@17 104 $this->assertEqual(count($field[0]->find('xpath', '.' . $field_items_xpath_suffix)), $i + 2, 'Found the correct number of field items after an AJAX submission.');
Chris@17 105 $this->assertFieldsByValue($field[0]->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.');
Chris@17 106 $this->assertNoDuplicateIds();
Chris@17 107 }
Chris@17 108 }
Chris@17 109 }
Chris@17 110
Chris@17 111 /**
Chris@17 112 * Asserts that each HTML ID is used for just a single element on the page.
Chris@17 113 *
Chris@17 114 * @param string $message
Chris@17 115 * (optional) A message to display with the assertion.
Chris@17 116 */
Chris@17 117 protected function assertNoDuplicateIds($message = '') {
Chris@17 118 $args = ['@url' => $this->getUrl()];
Chris@17 119
Chris@17 120 if (!$elements = $this->xpath('//*[@id]')) {
Chris@17 121 $this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args));
Chris@17 122 return;
Chris@17 123 }
Chris@17 124
Chris@17 125 $message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args);
Chris@17 126
Chris@17 127 $seen_ids = [];
Chris@17 128 foreach ($elements as $element) {
Chris@17 129 $id = $element->getAttribute('id');
Chris@17 130 if (isset($seen_ids[$id])) {
Chris@17 131 $this->fail($message);
Chris@17 132 return;
Chris@17 133 }
Chris@17 134 $seen_ids[$id] = TRUE;
Chris@17 135 }
Chris@17 136 $this->assertTrue(TRUE, $message);
Chris@17 137 }
Chris@17 138
Chris@17 139 }