9d0641e41bd7ee018b311507f5febcc1ddb22ba7
[yaffs-website] / web / core / modules / filter / src / Tests / FilterFormTest.php
1 <?php
2
3 namespace Drupal\filter\Tests;
4
5 use Drupal\Component\Utility\SafeMarkup;
6 use Drupal\filter\Entity\FilterFormat;
7 use Drupal\simpletest\WebTestBase;
8
9 /**
10  * Tests form elements with associated text formats.
11  *
12  * @group filter
13  */
14 class FilterFormTest extends WebTestBase {
15
16   /**
17    * Modules to enable for this test.
18    *
19    * @var array
20    */
21   protected static $modules = ['filter', 'filter_test'];
22
23   /**
24    * An administrative user account that can administer text formats.
25    *
26    * @var \Drupal\user\Entity\User
27    */
28   protected $adminUser;
29
30   /**
31    * An basic user account that can only access basic HTML text format.
32    *
33    * @var \Drupal\user\Entity\User
34    */
35   protected $webUser;
36
37   /**
38    * {@inheritdoc}
39    */
40   protected function setUp() {
41     parent::setUp();
42
43     /** @var \Drupal\filter\FilterFormatInterface $filter_test_format */
44     $filter_test_format = FilterFormat::load('filter_test');
45     /** @var \Drupal\filter\FilterFormatInterface $filtered_html_format */
46     $filtered_html_format = FilterFormat::load('filtered_html');
47     /** @var \Drupal\filter\FilterFormatInterface $full_html_format */
48     $full_html_format = FilterFormat::load('full_html');
49
50     // Create users.
51     $this->adminUser = $this->drupalCreateUser([
52       'administer filters',
53       $filtered_html_format->getPermissionName(),
54       $full_html_format->getPermissionName(),
55       $filter_test_format->getPermissionName(),
56     ]);
57
58     $this->webUser = $this->drupalCreateUser([
59       $filtered_html_format->getPermissionName(),
60       $filter_test_format->getPermissionName(),
61     ]);
62   }
63
64   /**
65    * Tests various different configurations of the 'text_format' element.
66    */
67   public function testFilterForm() {
68     $this->doFilterFormTestAsAdmin();
69     $this->doFilterFormTestAsNonAdmin();
70     // Ensure that enabling modules which provide filter plugins behaves
71     // correctly.
72     // @see https://www.drupal.org/node/2387983
73     \Drupal::service('module_installer')->install(['filter_test_plugin']);
74     // Force rebuild module data.
75     _system_rebuild_module_data();
76   }
77
78   /**
79    * Tests the behavior of the 'text_format' element as an administrator.
80    */
81   protected function doFilterFormTestAsAdmin() {
82     $this->drupalLogin($this->adminUser);
83     $this->drupalGet('filter-test/text-format');
84
85     // Test a text format element with all formats.
86     $formats = ['filtered_html', 'full_html', 'filter_test'];
87     $this->assertEnabledTextarea('edit-all-formats-no-default-value');
88     // If no default is given, the format with the lowest weight becomes the
89     // default.
90     $this->assertOptions('edit-all-formats-no-default-format--2', $formats, 'filtered_html');
91     $this->assertEnabledTextarea('edit-all-formats-default-value');
92     // \Drupal\filter_test\Form\FilterTestFormatForm::buildForm() uses
93     // 'filter_test' as the default value in this case.
94     $this->assertOptions('edit-all-formats-default-format--2', $formats, 'filter_test');
95     $this->assertEnabledTextarea('edit-all-formats-default-missing-value');
96     // If a missing format is set as the default, administrators must select a
97     // valid replacement format.
98     $this->assertRequiredSelectAndOptions('edit-all-formats-default-missing-format--2', $formats);
99
100     // Test a text format element with a predefined list of formats.
101     $formats = ['full_html', 'filter_test'];
102     $this->assertEnabledTextarea('edit-restricted-formats-no-default-value');
103     $this->assertOptions('edit-restricted-formats-no-default-format--2', $formats, 'full_html');
104     $this->assertEnabledTextarea('edit-restricted-formats-default-value');
105     $this->assertOptions('edit-restricted-formats-default-format--2', $formats, 'full_html');
106     $this->assertEnabledTextarea('edit-restricted-formats-default-missing-value');
107     $this->assertRequiredSelectAndOptions('edit-restricted-formats-default-missing-format--2', $formats);
108     $this->assertEnabledTextarea('edit-restricted-formats-default-disallowed-value');
109     $this->assertRequiredSelectAndOptions('edit-restricted-formats-default-disallowed-format--2', $formats);
110
111     // Test a text format element with a fixed format.
112     $formats = ['filter_test'];
113     // When there is only a single option there is no point in choosing.
114     $this->assertEnabledTextarea('edit-single-format-no-default-value');
115     $this->assertNoSelect('edit-single-format-no-default-format--2');
116     $this->assertEnabledTextarea('edit-single-format-default-value');
117     $this->assertNoSelect('edit-single-format-default-format--2');
118     // If the select has a missing or disallowed format, administrators must
119     // explicitly choose the format.
120     $this->assertEnabledTextarea('edit-single-format-default-missing-value');
121     $this->assertRequiredSelectAndOptions('edit-single-format-default-missing-format--2', $formats);
122     $this->assertEnabledTextarea('edit-single-format-default-disallowed-value');
123     $this->assertRequiredSelectAndOptions('edit-single-format-default-disallowed-format--2', $formats);
124   }
125
126   /**
127    * Tests the behavior of the 'text_format' element as a normal user.
128    */
129   protected function doFilterFormTestAsNonAdmin() {
130     $this->drupalLogin($this->webUser);
131     $this->drupalGet('filter-test/text-format');
132
133     // Test a text format element with all formats. Only formats the user has
134     // access to are shown.
135     $formats = ['filtered_html', 'filter_test'];
136     $this->assertEnabledTextarea('edit-all-formats-no-default-value');
137     // If no default is given, the format with the lowest weight becomes the
138     // default. This happens to be 'filtered_html'.
139     $this->assertOptions('edit-all-formats-no-default-format--2', $formats, 'filtered_html');
140     $this->assertEnabledTextarea('edit-all-formats-default-value');
141     // \Drupal\filter_test\Form\FilterTestFormatForm::buildForm() uses
142     // 'filter_test' as the default value in this case.
143     $this->assertOptions('edit-all-formats-default-format--2', $formats, 'filter_test');
144     // If a missing format is given as default, non-admin users are presented
145     // with a disabled textarea.
146     $this->assertDisabledTextarea('edit-all-formats-default-missing-value');
147
148     // Test a text format element with a predefined list of formats.
149     $this->assertEnabledTextarea('edit-restricted-formats-no-default-value');
150     // The user only has access to the 'filter_test' format, so when no default
151     // is given that is preselected and the text format select is hidden.
152     $this->assertNoSelect('edit-restricted-formats-no-default-format--2');
153     // When the format that the user does not have access to is preselected, the
154     // textarea should be disabled.
155     $this->assertDisabledTextarea('edit-restricted-formats-default-value');
156     $this->assertDisabledTextarea('edit-restricted-formats-default-missing-value');
157     $this->assertDisabledTextarea('edit-restricted-formats-default-disallowed-value');
158
159     // Test a text format element with a fixed format.
160     // When there is only a single option there is no point in choosing.
161     $this->assertEnabledTextarea('edit-single-format-no-default-value');
162     $this->assertNoSelect('edit-single-format-no-default-format--2');
163     $this->assertEnabledTextarea('edit-single-format-default-value');
164     $this->assertNoSelect('edit-single-format-default-format--2');
165     // If the select has a missing or disallowed format make sure the textarea
166     // is disabled.
167     $this->assertDisabledTextarea('edit-single-format-default-missing-value');
168     $this->assertDisabledTextarea('edit-single-format-default-disallowed-value');
169   }
170
171   /**
172    * Makes sure that no select element with the given ID exists on the page.
173    *
174    * @param string $id
175    *   The HTML ID of the select element.
176    *
177    * @return bool
178    *   TRUE if the assertion passed; FALSE otherwise.
179    */
180   protected function assertNoSelect($id) {
181     $select = $this->xpath('//select[@id=:id]', [':id' => $id]);
182     return $this->assertFalse($select, SafeMarkup::format('Field @id does not exist.', [
183       '@id' => $id,
184     ]));
185   }
186
187   /**
188    * Asserts that a select element has the correct options.
189    *
190    * @param string $id
191    *   The HTML ID of the select element.
192    * @param array $expected_options
193    *   An array of option values.
194    * @param string $selected
195    *   The value of the selected option.
196    *
197    * @return bool
198    *   TRUE if the assertion passed; FALSE otherwise.
199    */
200   protected function assertOptions($id, array $expected_options, $selected) {
201     $select = $this->xpath('//select[@id=:id]', [':id' => $id]);
202     $select = reset($select);
203     $passed = $this->assertTrue($select instanceof \SimpleXMLElement, SafeMarkup::format('Field @id exists.', [
204       '@id' => $id,
205     ]));
206
207     $found_options = $this->getAllOptions($select);
208     foreach ($found_options as $found_key => $found_option) {
209       $expected_key = array_search($found_option->attributes()->value, $expected_options);
210       if ($expected_key !== FALSE) {
211         $this->pass(SafeMarkup::format('Option @option for field @id exists.', [
212           '@option' => $expected_options[$expected_key],
213           '@id' => $id,
214         ]));
215         unset($found_options[$found_key]);
216         unset($expected_options[$expected_key]);
217       }
218     }
219
220     // Make sure that all expected options were found and that there are no
221     // unexpected options.
222     foreach ($expected_options as $expected_option) {
223       $this->fail(SafeMarkup::format('Option @option for field @id exists.', [
224         '@option' => $expected_option,
225         '@id' => $id,
226       ]));
227       $passed = FALSE;
228     }
229     foreach ($found_options as $found_option) {
230       $this->fail(SafeMarkup::format('Option @option for field @id does not exist.', [
231         '@option' => $found_option->attributes()->value,
232         '@id' => $id,
233       ]));
234       $passed = FALSE;
235     }
236
237     return $passed && $this->assertOptionSelected($id, $selected);
238   }
239
240   /**
241    * Asserts that there is a select element with the given ID that is required.
242    *
243    * @param string $id
244    *   The HTML ID of the select element.
245    * @param array $options
246    *   An array of option values that are contained in the select element
247    *   besides the "- Select -" option.
248    *
249    * @return bool
250    *   TRUE if the assertion passed; FALSE otherwise.
251    */
252   protected function assertRequiredSelectAndOptions($id, array $options) {
253     $select = $this->xpath('//select[@id=:id and contains(@required, "required")]', [
254       ':id' => $id,
255     ]);
256     $select = reset($select);
257     $passed = $this->assertTrue($select instanceof \SimpleXMLElement, SafeMarkup::format('Required field @id exists.', [
258       '@id' => $id,
259     ]));
260     // A required select element has a "- Select -" option whose key is an empty
261     // string.
262     $options[] = '';
263     return $passed && $this->assertOptions($id, $options, '');
264   }
265
266   /**
267    * Asserts that a textarea with a given ID exists and is not disabled.
268    *
269    * @param string $id
270    *   The HTML ID of the textarea.
271    *
272    * @return bool
273    *   TRUE if the assertion passed; FALSE otherwise.
274    */
275   protected function assertEnabledTextarea($id) {
276     $textarea = $this->xpath('//textarea[@id=:id and not(contains(@disabled, "disabled"))]', [
277       ':id' => $id,
278     ]);
279     $textarea = reset($textarea);
280     return $this->assertTrue($textarea instanceof \SimpleXMLElement, SafeMarkup::format('Enabled field @id exists.', [
281       '@id' => $id,
282     ]));
283   }
284
285   /**
286    * Asserts that a textarea with a given ID has been disabled from editing.
287    *
288    * @param string $id
289    *   The HTML ID of the textarea.
290    *
291    * @return bool
292    *   TRUE if the assertion passed; FALSE otherwise.
293    */
294   protected function assertDisabledTextarea($id) {
295     $textarea = $this->xpath('//textarea[@id=:id and contains(@disabled, "disabled")]', [
296       ':id' => $id,
297     ]);
298     $textarea = reset($textarea);
299     $passed = $this->assertTrue($textarea instanceof \SimpleXMLElement, SafeMarkup::format('Disabled field @id exists.', [
300       '@id' => $id,
301     ]));
302     $expected = 'This field has been disabled because you do not have sufficient permissions to edit it.';
303     $passed = $passed && $this->assertEqual((string) $textarea, $expected, SafeMarkup::format('Disabled textarea @id hides text in an inaccessible text format.', [
304       '@id' => $id,
305     ]));
306     // Make sure the text format select is not shown.
307     $select_id = str_replace('value', 'format--2', $id);
308     return $passed && $this->assertNoSelect($select_id);
309   }
310
311 }