MultiFormTest.php

Same filename and directory in other branches
  1. 9 core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php
  2. 10 core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php
  3. 11.x core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php

Namespace

Drupal\FunctionalJavascriptTests\Ajax

File

core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php

View source
<?php

namespace Drupal\FunctionalJavascriptTests\Ajax;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;

/**
 * Tests that AJAX-enabled forms work when multiple instances of the same form
 * are on a page.
 *
 * @group Ajax
 */
class MultiFormTest extends WebDriverTestBase {
    
    /**
     * {@inheritdoc}
     */
    public static $modules = [
        'node',
        'form_test',
    ];
    
    /**
     * {@inheritdoc}
     */
    protected $defaultTheme = 'stark';
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() {
        parent::setUp();
        $this->drupalCreateContentType([
            'type' => 'page',
            'name' => 'Page',
        ]);
        // Create a multi-valued field for 'page' nodes to use for Ajax testing.
        $field_name = 'field_ajax_test';
        FieldStorageConfig::create([
            'entity_type' => 'node',
            'field_name' => $field_name,
            'type' => 'text',
            'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
        ])->save();
        FieldConfig::create([
            'field_name' => $field_name,
            'entity_type' => 'node',
            'bundle' => 'page',
        ])->save();
        \Drupal::service('entity_display.repository')->getFormDisplay('node', 'page', 'default')
            ->setComponent($field_name, [
            'type' => 'text_textfield',
        ])
            ->save();
        // Log in a user who can create 'page' nodes.
        $this->drupalLogin($this->drupalCreateUser([
            'create page content',
        ]));
    }
    
    /**
     * Tests that pages with the 'node_page_form' included twice work correctly.
     */
    public function testMultiForm() {
        // HTML IDs for elements within the field are potentially modified with
        // each Ajax submission, but these variables are stable and help target the
        // desired elements.
        $field_name = 'field_ajax_test';
        $form_xpath = '//form[starts-with(@id, "node-page-form")]';
        $field_xpath = '//div[contains(@class, "field--name-field-ajax-test")]';
        $button_name = $field_name . '_add_more';
        $button_value = t('Add another item');
        $button_xpath_suffix = '//input[@name="' . $button_name . '"]';
        $field_items_xpath_suffix = '//input[@type="text"]';
        // Ensure the initial page contains both node forms and the correct number
        // of field items and "add more" button for the multi-valued field within
        // each form.
        $this->drupalGet('form-test/two-instances-of-same-form');
        // Wait for javascript on the page to prepare the form attributes.
        $this->assertSession()
            ->assertWaitOnAjaxRequest();
        $session = $this->getSession();
        $page = $session->getPage();
        $fields = $page->findAll('xpath', $form_xpath . $field_xpath);
        $this->assertCount(2, $fields);
        foreach ($fields as $field) {
            $this->assertCount(1, $field->findAll('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items on the initial page.');
            $this->assertFieldsByValue($field->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.');
        }
        $this->assertNoDuplicateIds();
        // Submit the "add more" button of each form twice. After each corresponding
        // page update, ensure the same as above.
        for ($i = 0; $i < 2; $i++) {
            $forms = $page->find('xpath', $form_xpath);
            foreach ($forms as $offset => $form) {
                $button = $form->findButton($button_value);
                $this->assertNotNull($button, 'Add Another Item button exists');
                $button->press();
                // Wait for page update.
                $this->assertSession()
                    ->assertWaitOnAjaxRequest();
                // After AJAX request and response page will update.
                $page_updated = $session->getPage();
                $field = $page_updated->findAll('xpath', '.' . $field_xpath);
                $this->assertCount($i + 2, $field[0]->find('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items after an AJAX submission.');
                $this->assertFieldsByValue($field[0]->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.');
                $this->assertNoDuplicateIds();
            }
        }
    }
    
    /**
     * Asserts that each HTML ID is used for just a single element on the page.
     *
     * @param string $message
     *   (optional) A message to display with the assertion.
     */
    protected function assertNoDuplicateIds($message = '') {
        $args = [
            '@url' => $this->getUrl(),
        ];
        if (!($elements = $this->xpath('//*[@id]'))) {
            $this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args));
            return;
        }
        $message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args);
        $seen_ids = [];
        foreach ($elements as $element) {
            $id = $element->getAttribute('id');
            if (isset($seen_ids[$id])) {
                $this->fail($message);
                return;
            }
            $seen_ids[$id] = TRUE;
        }
        $this->assertTrue(TRUE, $message);
    }

}

Classes

Title Deprecated Summary
MultiFormTest Tests that AJAX-enabled forms work when multiple instances of the same form are on a page.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.