419215f8732f9ba064e5bd21a29c6ac4eb8625a0
[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 = ['formats' => ['full_html' => [
144       'format' => 'full_html',
145       'editor' => 'unicorn',
146       'editorSettings' => ['ponyModeEnabled' => TRUE],
147       'editorSupportsContentFiltering' => TRUE,
148       'isXssSafe' => FALSE,
149     ]]];
150     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
151     $this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
152     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
153     $this->assertTrue(count($body) === 1, 'A body field exists.');
154     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
155     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and @data-editor-for="edit-body-0-value"]');
156     $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.');
157
158     // Load the editor image dialog form and make sure it does not fatal.
159     $this->drupalGet('editor/dialog/image/full_html');
160     $this->assertResponse(200);
161
162     $this->drupalLogout($this->privilegedUser);
163
164     // Also associate a text editor with the "Plain Text" text format.
165     $editor = Editor::create([
166       'format' => 'plain_text',
167       'editor' => 'unicorn',
168     ]);
169     $editor->save();
170
171     // The untrusted user:
172     // - has access to 1 text format (plain_text);
173     // - has access to the plain_text text format, so: Unicorn text editor.
174     $this->drupalLogin($this->untrustedUser);
175     $this->drupalGet('node/add/article');
176     list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
177     $expected = ['formats' => ['plain_text' => [
178       'format' => 'plain_text',
179       'editor' => 'unicorn',
180       'editorSettings' => ['ponyModeEnabled' => TRUE],
181       'editorSupportsContentFiltering' => TRUE,
182       'isXssSafe' => FALSE,
183     ]]];
184     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
185     $this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
186     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
187     $this->assertTrue(count($body) === 1, 'A body field exists.');
188     $this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page.');
189     $hidden_input = $this->xpath('//input[@type="hidden" and @value="plain_text" and @data-editor-for="edit-body-0-value"]');
190     $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.');
191
192     // Create an "article" node that uses the full_html text format, then try
193     // to let the untrusted user edit it.
194     $this->drupalCreateNode([
195       'type' => 'article',
196       'body' => [
197         ['value' => $this->randomMachineName(32), 'format' => 'full_html']
198       ],
199     ]);
200
201     // The untrusted user tries to edit content that is written in a text format
202     // that (s)he is not allowed to use. The editor is still loaded. CKEditor,
203     // for example, supports being loaded in a disabled state.
204     $this->drupalGet('node/1/edit');
205     list( , $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
206     $this->assertTrue($editor_settings_present, 'Text Editor module settings.');
207     $this->assertTrue($editor_js_present, 'Text Editor JavaScript.');
208     $this->assertTrue(count($body) === 1, 'A body field exists.');
209     $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.');
210     $this->assertTrue(count($format_selector) === 0, 'No text format selector exists on the page.');
211     $hidden_input = $this->xpath('//input[@type="hidden" and contains(@class, "editor")]');
212     $this->assertTrue(count($hidden_input) === 0, 'A single text format hidden input does not exist on the page.');
213   }
214
215   /**
216    * Test supported element types.
217    */
218   public function testSupportedElementTypes() {
219     // Associate the unicorn text editor with the "Full HTML" text format.
220     $editor = Editor::create([
221       'format' => 'full_html',
222       'editor' => 'unicorn',
223       'image_upload' => [
224         'status' => FALSE,
225         'scheme' => file_default_scheme(),
226         'directory' => 'inline-images',
227         'max_size' => '',
228         'max_dimensions' => ['width' => '', 'height' => ''],
229       ]
230     ]);
231     $editor->save();
232
233     // Create an "page" node that uses the full_html text format.
234     $this->drupalCreateNode([
235       'type' => 'page',
236       'field_text' => [
237         ['value' => $this->randomMachineName(32), 'format' => 'full_html']
238       ],
239     ]);
240
241     // Assert the unicorn editor works with textfields.
242     $this->drupalLogin($this->privilegedUser);
243     $this->drupalGet('node/1/edit');
244     list( , $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
245     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
246     $this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
247     $this->assertTrue(count($field) === 1, 'A text field exists.');
248     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
249     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
250     $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.');
251
252     // Associate the trex text editor with the "Full HTML" text format.
253     $editor->delete();
254     Editor::create([
255       'format' => 'full_html',
256       'editor' => 'trex',
257     ])->save();
258
259     $this->drupalGet('node/1/edit');
260     list( , $editor_settings_present, $editor_js_present, $field, $format_selector) = $this->getThingsToCheck('field-text', 'input');
261     $this->assertFalse($editor_settings_present, "Text Editor module's JavaScript settings are not on the page.");
262     $this->assertFalse($editor_js_present, 'Text Editor JavaScript is not present.');
263     $this->assertTrue(count($field) === 1, 'A text field exists.');
264     $this->assertTrue(count($format_selector) === 1, 'A single text format selector exists on the page.');
265     $specific_format_selector = $this->xpath('//select[contains(@class, "filter-list") and contains(@class, "editor") and @data-editor-for="edit-field-text-0-value"]');
266     $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.');
267   }
268
269   protected function getThingsToCheck($field_name, $type = 'textarea') {
270     $settings = $this->getDrupalSettings();
271     return [
272       // JavaScript settings.
273       $settings,
274       // Editor.module's JS settings present.
275       isset($settings['editor']),
276       // Editor.module's JS present.
277       strpos($this->getRawContent(), drupal_get_path('module', 'editor') . '/js/editor.js') !== FALSE,
278       // Body field.
279       $this->xpath('//' . $type . '[@id="edit-' . $field_name . '-0-value"]'),
280       // Format selector.
281       $this->xpath('//select[contains(@class, "filter-list")]'),
282     ];
283   }
284
285 }