030526eef9fa42c2ecff07c9416fe28c9b7e641f
[yaffs-website] / web / core / modules / system / src / Tests / Form / ElementsTableSelectTest.php
1 <?php
2
3 namespace Drupal\system\Tests\Form;
4
5 use Drupal\Core\Form\FormState;
6 use Drupal\simpletest\WebTestBase;
7 use Drupal\Tests\system\Functional\Form\StubForm;
8
9 /**
10  * Tests the tableselect form element for expected behavior.
11  *
12  * @group Form
13  */
14 class ElementsTableSelectTest extends WebTestBase {
15
16   /**
17    * Modules to enable.
18    *
19    * @var array
20    */
21   public static $modules = ['form_test'];
22
23   /**
24    * Test the display of checkboxes when #multiple is TRUE.
25    */
26   public function testMultipleTrue() {
27
28     $this->drupalGet('form_test/tableselect/multiple-true');
29
30     $this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.');
31
32     // Test for the presence of the Select all rows tableheader.
33     $this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Presence of the "Select all" checkbox.');
34
35     $rows = ['row1', 'row2', 'row3'];
36     foreach ($rows as $row) {
37       $this->assertFieldByXPath('//input[@type="checkbox"]', $row, format_string('Checkbox for value @row.', ['@row' => $row]));
38     }
39   }
40
41   /**
42    * Test the presence of ajax functionality for all options.
43    */
44   public function testAjax() {
45     $rows = ['row1', 'row2', 'row3'];
46     // Test checkboxes (#multiple == TRUE).
47     foreach ($rows as $row) {
48       $element = 'tableselect[' . $row . ']';
49       $edit = [$element => TRUE];
50       $result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-true', $edit, $element);
51       $this->assertFalse(empty($result), t('Ajax triggers on checkbox for @row.', ['@row' => $row]));
52     }
53     // Test radios (#multiple == FALSE).
54     $element = 'tableselect';
55     foreach ($rows as $row) {
56       $edit = [$element => $row];
57       $result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-false', $edit, $element);
58       $this->assertFalse(empty($result), t('Ajax triggers on radio for @row.', ['@row' => $row]));
59     }
60   }
61
62   /**
63    * Test the display of radios when #multiple is FALSE.
64    */
65   public function testMultipleFalse() {
66     $this->drupalGet('form_test/tableselect/multiple-false');
67
68     $this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.');
69
70     // Test for the absence of the Select all rows tableheader.
71     $this->assertNoFieldByXPath('//th[@class="select-all"]', '', 'Absence of the "Select all" checkbox.');
72
73     $rows = ['row1', 'row2', 'row3'];
74     foreach ($rows as $row) {
75       $this->assertFieldByXPath('//input[@type="radio"]', $row, format_string('Radio button for value @row.', ['@row' => $row]));
76     }
77   }
78
79   /**
80    * Tests the display when #colspan is set.
81    */
82   public function testTableselectColSpan() {
83     $this->drupalGet('form_test/tableselect/colspan');
84
85     $this->assertText(t('Three'), 'Presence of the third column');
86     $this->assertNoText(t('Four'), 'Absence of a fourth column');
87
88     // There should be three labeled column headers and 1 for the input.
89     $table_head = $this->xpath('//thead');
90     $this->assertEqual(count($table_head[0]->tr->th), 4, 'There are four column headers');
91
92     $table_body = $this->xpath('//tbody');
93     // The first two body rows should each have 5 table cells: One for the
94     // radio, one cell in the first column, one cell in the second column,
95     // and two cells in the third column which has colspan 2.
96     for ($i = 0; $i <= 1; $i++) {
97       $this->assertEqual(count($table_body[0]->tr[$i]->td), 5, format_string('There are five cells in row @row.', ['@row' => $i]));
98     }
99     // The third row should have 3 cells, one for the radio, one spanning the
100     // first and second column, and a third in column 3 (which has colspan 3).
101     $this->assertEqual(count($table_body[0]->tr[2]->td), 3, 'There are three cells in row 3.');
102   }
103
104   /**
105    * Test the display of the #empty text when #options is an empty array.
106    */
107   public function testEmptyText() {
108     $this->drupalGet('form_test/tableselect/empty-text');
109     $this->assertText(t('Empty text.'), 'Empty text should be displayed.');
110   }
111
112   /**
113    * Test the submission of single and multiple values when #multiple is TRUE.
114    */
115   public function testMultipleTrueSubmit() {
116
117     // Test a submission with one checkbox checked.
118     $edit = [];
119     $edit['tableselect[row1]'] = TRUE;
120     $this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit');
121
122     $this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1');
123     $this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.');
124     $this->assertText(t('Submitted: row3 = 0'), 'Unchecked checkbox row3.');
125
126     // Test a submission with multiple checkboxes checked.
127     $edit['tableselect[row1]'] = TRUE;
128     $edit['tableselect[row3]'] = TRUE;
129     $this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit');
130
131     $this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1.');
132     $this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.');
133     $this->assertText(t('Submitted: row3 = row3'), 'Checked checkbox row3.');
134
135   }
136
137   /**
138    * Test submission of values when #multiple is FALSE.
139    */
140   public function testMultipleFalseSubmit() {
141     $edit['tableselect'] = 'row1';
142     $this->drupalPostForm('form_test/tableselect/multiple-false', $edit, 'Submit');
143     $this->assertText(t('Submitted: row1'), 'Selected radio button');
144   }
145
146   /**
147    * Test the #js_select property.
148    */
149   public function testAdvancedSelect() {
150     // When #multiple = TRUE a Select all checkbox should be displayed by default.
151     $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-default');
152     $this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Display a "Select all" checkbox by default when #multiple is TRUE.');
153
154     // When #js_select is set to FALSE, a "Select all" checkbox should not be displayed.
155     $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-no-advanced-select');
156     $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #js_select is FALSE.');
157
158     // A "Select all" checkbox never makes sense when #multiple = FALSE, regardless of the value of #js_select.
159     $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-default');
160     $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE.');
161
162     $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-advanced-select');
163     $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE, even when #js_select is TRUE.');
164   }
165
166   /**
167    * Test the whether the option checker gives an error on invalid tableselect values for checkboxes.
168    */
169   public function testMultipleTrueOptionchecker() {
170
171     list($header, $options) = _form_test_tableselect_get_data();
172
173     $form['tableselect'] = [
174       '#type' => 'tableselect',
175       '#header' => $header,
176       '#options' => $options,
177     ];
178
179     // Test with a valid value.
180     list(, , $errors) = $this->formSubmitHelper($form, ['tableselect' => ['row1' => 'row1']]);
181     $this->assertFalse(isset($errors['tableselect']), 'Option checker allows valid values for checkboxes.');
182
183     // Test with an invalid value.
184     list(, , $errors) = $this->formSubmitHelper($form, ['tableselect' => ['non_existing_value' => 'non_existing_value']]);
185     $this->assertTrue(isset($errors['tableselect']), 'Option checker disallows invalid values for checkboxes.');
186
187   }
188
189   /**
190    * Test the whether the option checker gives an error on invalid tableselect values for radios.
191    */
192   public function testMultipleFalseOptionchecker() {
193
194     list($header, $options) = _form_test_tableselect_get_data();
195
196     $form['tableselect'] = [
197       '#type' => 'tableselect',
198       '#header' => $header,
199       '#options' => $options,
200       '#multiple' => FALSE,
201     ];
202
203     // Test with a valid value.
204     list(, , $errors) = $this->formSubmitHelper($form, ['tableselect' => 'row1']);
205     $this->assertFalse(isset($errors['tableselect']), 'Option checker allows valid values for radio buttons.');
206
207     // Test with an invalid value.
208     list(, , $errors) = $this->formSubmitHelper($form, ['tableselect' => 'non_existing_value']);
209     $this->assertTrue(isset($errors['tableselect']), 'Option checker disallows invalid values for radio buttons.');
210   }
211
212   /**
213    * Helper function for the option check test to submit a form while collecting errors.
214    *
215    * @param $form_element
216    *   A form element to test.
217    * @param $edit
218    *   An array containing post data.
219    *
220    * @return
221    *   An array containing the processed form, the form_state and any errors.
222    */
223   private function formSubmitHelper($form, $edit) {
224     $form_id = $this->randomMachineName();
225     $form_state = new FormState();
226
227     $form['op'] = ['#type' => 'submit', '#value' => t('Submit')];
228     // The form token CSRF protection should not interfere with this test, so we
229     // bypass it by setting the token to FALSE.
230     $form['#token'] = FALSE;
231
232     $edit['form_id'] = $form_id;
233
234     // Disable page redirect for forms submitted programmatically. This is a
235     // solution to skip the redirect step (there are no pages, then the redirect
236     // isn't possible).
237     $form_state->disableRedirect();
238     $form_state->setUserInput($edit);
239     $form_state->setFormObject(new StubForm($form_id, $form));
240
241     \Drupal::formBuilder()->prepareForm($form_id, $form, $form_state);
242
243     \Drupal::formBuilder()->processForm($form_id, $form, $form_state);
244
245     $errors = $form_state->getErrors();
246
247     // Clear errors and messages.
248     \Drupal::messenger()->deleteAll();
249     $form_state->clearErrors();
250
251     // Return the processed form together with form_state and errors
252     // to allow the caller lowlevel access to the form.
253     return [$form, $form_state, $errors];
254   }
255
256 }