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 }
|