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