3 namespace Drupal\editor\Tests;
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;
12 * Tests loading of text editors.
16 class EditorLoadingTest extends WebTestBase {
23 public static $modules = ['filter', 'editor', 'editor_test', 'node'];
26 * An untrusted user, with access to the 'plain_text' format.
28 * @var \Drupal\user\UserInterface
30 protected $untrustedUser;
33 * A normal user with additional access to the 'filtered_html' format.
35 * @var \Drupal\user\UserInterface
37 protected $normalUser;
40 * A privileged user with additional access to the 'full_html' format.
42 * @var \Drupal\user\UserInterface
44 protected $privilegedUser;
46 protected function setUp() {
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();
54 $filtered_html_format = FilterFormat::create([
55 'format' => 'filtered_html',
56 'name' => 'Filtered HTML',
60 $filtered_html_format->save();
61 $full_html_format = FilterFormat::create([
62 'format' => 'full_html',
63 'name' => 'Full HTML',
67 $full_html_format->save();
69 // Create article node type.
70 $this->drupalCreateContentType([
75 // Create page node type, but remove the body.
76 $this->drupalCreateContentType([
80 $body = FieldConfig::loadByName('node', 'page', 'body');
83 // Create a formatted text field, which uses an <input type="text">.
84 FieldStorageConfig::create([
85 'field_name' => 'field_text',
86 'entity_type' => 'node',
91 'field_name' => 'field_text',
92 'entity_type' => 'node',
93 'label' => 'Textfield',
97 entity_get_form_display('node', 'page', 'default')
98 ->setComponent('field_text')
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']);
108 * Tests loading of text editors.
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',
117 'scheme' => file_default_scheme(),
118 'directory' => 'inline-images',
120 'max_dimensions' => ['width' => '', 'height' => ''],
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);
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');
146 'format' => 'full_html',
147 'editor' => 'unicorn',
148 'editorSettings' => ['ponyModeEnabled' => TRUE],
149 'editorSupportsContentFiltering' => TRUE,
150 'isXssSafe' => FALSE,
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.');
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);
166 $this->drupalLogout($this->privilegedUser);
168 // Also associate a text editor with the "Plain Text" text format.
169 $editor = Editor::create([
170 'format' => 'plain_text',
171 'editor' => 'unicorn',
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');
184 'format' => 'plain_text',
185 'editor' => 'unicorn',
186 'editorSettings' => ['ponyModeEnabled' => TRUE],
187 'editorSupportsContentFiltering' => TRUE,
188 'isXssSafe' => FALSE,
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.');
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([
205 ['value' => $this->randomMachineName(32), 'format' => 'full_html']
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.');
224 * Test supported element types.
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',
233 'scheme' => file_default_scheme(),
234 'directory' => 'inline-images',
236 'max_dimensions' => ['width' => '', 'height' => ''],
241 // Create an "page" node that uses the full_html text format.
242 $this->drupalCreateNode([
245 ['value' => $this->randomMachineName(32), 'format' => 'full_html']
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.');
260 // Associate the trex text editor with the "Full HTML" text format.
263 'format' => 'full_html',
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.');
277 protected function getThingsToCheck($field_name, $type = 'textarea') {
278 $settings = $this->getDrupalSettings();
280 // JavaScript 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,
287 $this->xpath('//' . $type . '[@id="edit-' . $field_name . '-0-value"]'),
289 $this->xpath('//select[contains(@class, "filter-list")]'),