More updates to stop using dev or alpha or beta versions.
[yaffs-website] / web / core / modules / editor / src / Tests / EditorLoadingTest.php
1 <?php
2
3 namespace Drupal\editor\Tests;
4
5 use Drupal\editor\Entity\Editor;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\field\Entity\FieldStorageConfig;
8 use Drupal\simpletest\WebTestBase;
9 use Drupal\filter\Entity\FilterFormat;
10
11 /**
12  * Tests loading of text editors.
13  *
14  * @group editor
15  */
16 class EditorLoadingTest extends WebTestBase {
17
18   /**
19    * Modules to enable.
20    *
21    * @var array
22    */
23   public static $modules = ['filter', 'editor', 'editor_test', 'node'];
24
25   /**
26    * An untrusted user, with access to the 'plain_text' format.
27    *
28    * @var \Drupal\user\UserInterface
29    */
30   protected $untrustedUser;
31
32   /**
33    * A normal user with additional access to the 'filtered_html' format.
34    *
35    * @var \Drupal\user\UserInterface
36    */
37   protected $normalUser;
38
39   /**
40    * A privileged user with additional access to the 'full_html' format.
41    *
42    * @var \Drupal\user\UserInterface
43    */
44   protected $privilegedUser;
45
46   protected function setUp() {
47     parent::setUp();
48
49     // Let there be T-rex.
50     \Drupal::state()->set('editor_test_give_me_a_trex_thanks', TRUE);
51     \Drupal::service('plugin.manager.editor')->clearCachedDefinitions();
52
53     // Add text formats.
54     $filtered_html_format = FilterFormat::create([
55       'format' => 'filtered_html',
56       'name' => 'Filtered HTML',
57       'weight' => 0,
58       'filters' => [],
59     ]);
60     $filtered_html_format->save();
61     $full_html_format = FilterFormat::create([
62       'format' => 'full_html',
63       'name' => 'Full HTML',
64       'weight' => 1,
65       'filters' => [],
66     ]);
67     $full_html_format->save();
68
69     // Create article node type.
70     $this->drupalCreateContentType([
71       'type' => 'article',
72       'name' => 'Article',
73     ]);
74
75     // Create page node type, but remove the body.
76     $this->drupalCreateContentType([
77       'type' => 'page',
78       'name' => 'Page',
79     ]);
80     $body = FieldConfig::loadByName('node', 'page', 'body');
81     $body->delete();
82
83     // Create a formatted text field, which uses an <input type="text">.
84     FieldStorageConfig::create([
85       'field_name' => 'field_text',
86       'entity_type' => 'node',
87       'type' => 'text',
88     ])->save();
89
90     FieldConfig::create([
91       'field_name' => 'field_text',
92       'entity_type' => 'node',
93       'label' => 'Textfield',
94       'bundle' => 'page',
95     ])->save();
96
97     entity_get_form_display('node', 'page', 'default')
98       ->setComponent('field_text')
99       ->save();
100
101     // Create 3 users, each with access to different text formats.
102     $this->untrustedUser = $this->drupalCreateUser(['create article content', 'edit any article content']);
103     $this->normalUser = $this->drupalCreateUser(['create article content', 'edit any article content', 'use text format filtered_html']);
104     $this->privilegedUser = $this->drupalCreateUser(['create article content', 'edit any article content', 'create page content', 'edit any page content', 'use text format filtered_html', 'use text format full_html']);
105   }
106
107   /**
108    * Tests loading of text editors.
109    */
110   public function testLoading() {
111     // Only associate a text editor with the "Full HTML" text format.
112     $editor = Editor::create([
113       'format' => 'full_html',
114       'editor' => 'unicorn',
115       'image_upload' => [
116         'status' => FALSE,
117         'scheme' => file_default_scheme(),
118         'directory' => 'inline-images',
119         'max_size' => '',
120         'max_dimensions' => ['width' => '', 'height' => ''],
121       ]
122     ]);
123     $editor->save();
124
125     // The normal user:
126     // - has access to 2 text formats;
127     // - doesn't have access to the full_html text format, so: no text editor.
128     $this->drupalLogin($this->normalUser);
129     $this->drupalGet('node/add/article');
130     list(, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
131     $this->assertFalse($editor_settings_present, 'No Text Editor module settings.');
132     $this->assertFalse($editor_js_present, 'No Text Editor JavaScript.');
133     $this->assertTrue(count($body) === 1, 'A body field exists.');
134     $this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page because the user only has access to a single format.');
135     $this->drupalLogout($this->normalUser);
136
137     // The privileged user:
138     // - has access to 2 text formats (and the fallback format);
139     // - does have access to the full_html text format, so: Unicorn text editor.
140     $this->drupalLogin($this->privilegedUser);
141     $this->drupalGet('node/add/article');
142     list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
143     $expected = [
144       'formats' => [
145         'full_html' => [
146           'format' => 'full_html',
147           'editor' => 'unicorn',
148           'editorSettings' => ['ponyModeEnabled' => TRUE],
149           'editorSupportsContentFiltering' => TRUE,
150           'isXssSafe' => FALSE,
151         ],
152       ],
153     ];
154     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
155     $this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
156     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
157     $this->assertTrue(count($body) === 1, 'A body field exists.');
158     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
159     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and @data-editor-for="edit-body-0-value"]');
160     $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has a "data-editor-for" attribute with the correct value.');
161
162     // Load the editor image dialog form and make sure it does not fatal.
163     $this->drupalGet('editor/dialog/image/full_html');
164     $this->assertResponse(200);
165
166     $this->drupalLogout($this->privilegedUser);
167
168     // Also associate a text editor with the "Plain Text" text format.
169     $editor = Editor::create([
170       'format' => 'plain_text',
171       'editor' => 'unicorn',
172     ]);
173     $editor->save();
174
175     // The untrusted user:
176     // - has access to 1 text format (plain_text);
177     // - has access to the plain_text text format, so: Unicorn text editor.
178     $this->drupalLogin($this->untrustedUser);
179     $this->drupalGet('node/add/article');
180     list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
181     $expected = [
182       'formats' => [
183         'plain_text' => [
184           'format' => 'plain_text',
185           'editor' => 'unicorn',
186           'editorSettings' => ['ponyModeEnabled' => TRUE],
187           'editorSupportsContentFiltering' => TRUE,
188           'isXssSafe' => FALSE,
189         ],
190       ],
191     ];
192     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
193     $this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
194     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
195     $this->assertTrue(count($body) === 1, 'A body field exists.');
196     $this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page.');
197     $hidden_input = $this->xpath('//input[@type="hidden" and @value="plain_text" and @data-editor-for="edit-body-0-value"]');
198     $this->assertTrue(count($hidden_input) === 1, 'A single text format hidden input exists on the page and has a "data-editor-for" attribute with the correct value.');
199
200     // Create an "article" node that uses the full_html text format, then try
201     // to let the untrusted user edit it.
202     $this->drupalCreateNode([
203       'type' => 'article',
204       'body' => [
205         ['value' => $this->randomMachineName(32), 'format' => 'full_html']
206       ],
207     ]);
208
209     // The untrusted user tries to edit content that is written in a text format
210     // that (s)he is not allowed to use. The editor is still loaded. CKEditor,
211     // for example, supports being loaded in a disabled state.
212     $this->drupalGet('node/1/edit');
213     list(, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
214     $this->assertTrue($editor_settings_present, 'Text Editor module settings.');
215     $this->assertTrue($editor_js_present, 'Text Editor JavaScript.');
216     $this->assertTrue(count($body) === 1, 'A body field exists.');
217     $this->assertFieldByXPath('//textarea[@id="edit-body-0-value" and @disabled="disabled"]', t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.');
218     $this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page.');
219     $hidden_input = $this->xpath('//input[@type="hidden" and contains(@class, "editor")]');
220     $this->assertTrue(count($hidden_input) === 0, 'A single text format hidden input does not exist on the page.');
221   }
222
223   /**
224    * Test supported element types.
225    */
226   public function testSupportedElementTypes() {
227     // Associate the unicorn text editor with the "Full HTML" text format.
228     $editor = Editor::create([
229       'format' => 'full_html',
230       'editor' => 'unicorn',
231       'image_upload' => [
232         'status' => FALSE,
233         'scheme' => file_default_scheme(),
234         'directory' => 'inline-images',
235         'max_size' => '',
236         'max_dimensions' => ['width' => '', 'height' => ''],
237       ]
238     ]);
239     $editor->save();
240
241     // Create an "page" node that uses the full_html text format.
242     $this->drupalCreateNode([
243       'type' => 'page',
244       'field_text' => [
245         ['value' => $this->randomMachineName(32), 'format' => 'full_html']
246       ],
247     ]);
248
249     // Assert the unicorn editor works with textfields.
250     $this->drupalLogin($this->privilegedUser);
251     $this->drupalGet('node/1/edit');
252     list(, $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
253     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
254     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
255     $this->assertTrue(count($field) === 1, 'A text field exists.');
256     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
257     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
258     $this->assertTrue(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
259
260     // Associate the trex text editor with the "Full HTML" text format.
261     $editor->delete();
262     Editor::create([
263       'format' => 'full_html',
264       'editor' => 'trex',
265     ])->save();
266
267     $this->drupalGet('node/1/edit');
268     list(, $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
269     $this->assertFalse($editor_settings_present, "Text Editor module's JavaScript settings are not on the page.");
270     $this->assertFalse($editor_js_present, 'Text Editor JavaScript is not present.');
271     $this->assertTrue(count($field) === 1, 'A text field exists.');
272     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
273     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
274     $this->assertFalse(count($specific_format_selector) === 1, 'A single text format selector exists on the page and has the "editor" class and a "data-editor-for" attribute with the correct value.');
275   }
276
277   protected function getThingsToCheck($field_name, $type = 'textarea') {
278     $settings = $this->getDrupalSettings();
279     return [
280       // JavaScript settings.
281       $settings,
282       // Editor.module's JS settings present.
283       isset($settings['editor']),
284       // Editor.module's JS present.
285       strpos($this->getRawContent(), drupal_get_path('module', 'editor') . '/js/editor.js') !== FALSE,
286       // Body field.
287       $this->xpath('//' . $type . '[@id="edit-' . $field_name . '-0-value"]'),
288       // Format selector.
289       $this->xpath('//select[contains(@class, "filter-list")]'),
290     ];
291   }
292
293 }