diff --git a/js/FileHandler.js b/js/FileHandler.js index 1bdb3b5a6df4d1a0405d9dfff4e611fa1fef695c..5f45245d1b131346ea2196038be427229b5bac07 100644 --- a/js/FileHandler.js +++ b/js/FileHandler.js @@ -12,8 +12,8 @@ **/ Drupal.insert.FileHandler = class extends Drupal.insert.Handler { constructor(container, widgetSetting, selectors, wrapper) { - super(container, widgetSetting, selectors || SELECTORS, wrapper); - } -}; + super(container, widgetSetting, selectors || SELECTORS, wrapper); + } + }; })(Drupal); \ No newline at end of file diff --git a/js/FocusManager.js b/js/FocusManager.js index 50388f6ff8aec61680abb09a908e672dc433e499..c3758530e8fd6f4606806467790b4d1f1ef87b12 100644 --- a/js/FocusManager.js +++ b/js/FocusManager.js @@ -111,8 +111,8 @@ this.#focusTarget = event.target; }); - textarea.addEventListener('blur', event => { - this.#previousFocusTarget = event.target; + textarea.addEventListener('blur', () => { + this.#previousFocusTarget = textarea; if (this.#focusTarget && this.#focusTarget === textarea) { this.#focusTarget = undefined; @@ -133,8 +133,25 @@ return this.#previousFocusTarget; } + // Only return the default target if it is tracked by the focus manager if (this.defaultTarget) { - return this.defaultTarget; + if ( + typeof CKEditor5 !== 'undefined' + && this.defaultTarget instanceof CKEditor5.core.Editor + && this.#editors.find( + editor => editor.id === this.defaultTarget.id + ) + ) { + return this.defaultTarget; + } + + if ( + this.#textareas.find( + textarea => textarea === this.defaultTarget + ) + ) { + return this.defaultTarget; + } } if (this.#editors.length) { diff --git a/tests/js/EditorManager.js b/tests/js/EditorManager.js deleted file mode 100644 index 77a17fc216652f470d8f7320b389a923bb90fc4a..0000000000000000000000000000000000000000 --- a/tests/js/EditorManager.js +++ /dev/null @@ -1,58 +0,0 @@ -(function(QUnit, $, CKEDITOR, Drupal) { - - QUnit.module('EditorManager', { - afterEach: function() { - $.each(CKEDITOR.instances, function(id, editor) { - var element = editor.element; - editor.destroy(); - element.$.remove(); - }); - - CKEDITOR.currentInstance = undefined; - - $('textarea.insert-test').remove(); - } - }); - - QUnit.test('Instantiation', function(assert) { - var editorInterface = new Drupal.insert.editors.CKEditor(); - var editorManager = new Drupal.insert.EditorManager(editorInterface); - - assert.ok(editorManager instanceof Drupal.insert.EditorManager, 'Instantiated EditorManager.') - }); - - QUnit.test('basic functionality', function(assert) { - var $textarea = $('<div>').addClass('insert-test').appendTo('body'); - var editorInterface = new Drupal.insert.editors.CKEditor(); - var editorManager = new Drupal.insert.EditorManager(editorInterface); - editorManager.updateClassesToRetain({ - 'test': ['test1'] - }); - var editor = CKEDITOR.replace($textarea.get(0), { - extraAllowedContent: 'span[data-insert-type](*)' - }); - - var done = assert.async(2); - - CKEDITOR.on('instanceReady', function(e) { - editorManager.addEditor(e.editor); - - editor.on('change', function() { - var $span = $(editor.document.$).find('body').find('span'); - - assert.strictEqual($span.attr('data-insert-type'), 'test', 'data-insert-type attribute set: ' + editor.getData()); - assert.strictEqual($span.attr('data-insert-class'), 'test1', 'data-insert-class attribute set: ' + editor.getData()); - - done(); - }); - - editor.insertHtml('<span class="test1 test2" data-insert-type="test">test</span>'); - - e.removeListener(); - - done(); - }); - - }); - -})(QUnit, jQuery, CKEDITOR, Drupal); \ No newline at end of file diff --git a/tests/js/FileHandler.js b/tests/js/FileHandler.js index 71f9546b79f0ff3b8f6ad995a3515d206f2c1072..8cd8ea31fd98193cae12a18f1f89f57e8ace83b2 100644 --- a/tests/js/FileHandler.js +++ b/tests/js/FileHandler.js @@ -1,18 +1,6 @@ -(function(QUnit, $, Drupal, CKEDITOR) { +(function(QUnit, Drupal) { - QUnit.module('FileHandler', { - afterEach: function() { - $.each(CKEDITOR.instances, function(id, editor) { - var element = editor.element; - editor.destroy(); - element.$.remove(); - }); - - CKEDITOR.currentInstance = undefined; - } - }); - - var $baseDom = $('<div class="insert-test-wrapper">\ + const baseDom = '<div class="insert-test-wrapper">\ <input class="insert-filename" value="test-filename">\ <input class="insert-description" name="field-name[description]" value="test-description">\ <div class="insert-test">\ @@ -21,443 +9,533 @@ </div>\ <div class="insert-button" data-insert-id="test-id"></div>\ </div>\ - </div>\ - '); - - var editorInterface = Drupal.insert.editors.interfaces.CKEditor; - var focusManager = new Drupal.insert.FocusManager(editorInterface); + </div>'; /** * @param {string} template - * @param {boolean} returnDom - * @return {array|Drupal.insert.FileHandler} + * @returns {[Drupal.insert.FileHandler, HTMLDivElement]} */ - function instantiateFileHandler(template, returnDom) { - var $dom = $baseDom.clone(); - $dom.find('.insert-templates').append( - $('<input class="insert-template" name="insert-template[test]" value="' + template + '">') - ); - var inserter = new Drupal.insert.Inserter($dom.find('.insert-test').get(0), focusManager, editorInterface); - var handler = new Drupal.insert.FileHandler(inserter); - return returnDom ? [handler, $dom] : handler; + function instantiateFileHandler(template) { + const wrapper = document.createElement('div'); + wrapper.innerHTML = baseDom; + + const templates = wrapper.querySelector('.insert-templates'); + templates.innerHTML = `<input class="insert-template" name="insert-template[test]" value="${template}">`; + + const container = wrapper.querySelector('.insert-test'); + const handler = new Drupal.insert.FileHandler(container); + return [handler, wrapper]; } /** * @param {Object} attach - * @param {boolean} returnDom - * @return {array|Drupal.insert.FileHandler} + * @returns {[Drupal.insert.FileHandler, HTMLDivElement]} */ - function instantiateFileHandlerJson(attach, returnDom) { + function instantiateFileHandlerJson(attach) { return instantiateFileHandler('' + '<span data-insert-attach=\'' + JSON.stringify(attach).replace(/"/g, '"') - + '\'>test</span>', - returnDom + + '\'>test</span>' ); } - QUnit.test('buildContent(): no attachments', function(assert) { - var fileHandler = instantiateFileHandler('<span>test</span>'); - assert.strictEqual(fileHandler.buildContent(), '<span>test</span>', 'Verified result: ' + fileHandler.buildContent()); + let editor; + + QUnit.module('FileHandler', { + beforeEach: () => { + Drupal.insert.FocusManager = new Drupal.insert.Manager(); + }, + afterEach: async () => { + if (editor) { + const sourceElement = editor.sourceElement; + await editor.destroy(); + sourceElement.remove(); + editor = undefined; + } + return true; + } + }) + + QUnit.test('buildContent(): no attachments', assert => { + let [fileHandler] = instantiateFileHandler('<span>test</span>'); - fileHandler = instantiateFileHandler('<span class="test">test</span>'); - assert.strictEqual(fileHandler.buildContent(), '<span class="test">test</span>', 'Verified result: ' + fileHandler.buildContent()); + assert.strictEqual( + fileHandler.buildContent(), + '<span>test</span>' + ); + + [fileHandler] = instantiateFileHandler( + '<span class="test">test</span>' + ); + + assert.strictEqual( + fileHandler.buildContent(), + '<span class="test">test</span>' + ); }); - QUnit.test('buildContent(): attribute attachments', function(assert) { - var fileHandler = instantiateFileHandlerJson({ + QUnit.test('buildContent(): attribute attachments', assert => { + let [fileHandler] = instantiateFileHandlerJson({ "attributes": { "class": ["description"] } }); - var $content = $(fileHandler.buildContent()); + let wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.attr('class'), 'test-description', 'Verified setting attribute: ' + fileHandler.buildContent()); + assert.strictEqual( + wrapper.firstChild.classList.contains('test-description'), + true, + `Verified setting attribute: ${fileHandler.buildContent()}` + ); - fileHandler = instantiateFileHandlerJson({ + [fileHandler] = instantiateFileHandlerJson({ "attributes": { "class": ["does-not-exist", "description"] } } ); - $content = $(fileHandler.buildContent()); + wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.attr('class'), 'test-description', 'Verified setting fallback attribute: ' + fileHandler.buildContent()); + assert.strictEqual( + wrapper.firstChild.classList.contains('test-description'), + true, + `Verified setting fallback attribute: '${fileHandler.buildContent()}` + ); - fileHandler = instantiateFileHandlerJson({ + [fileHandler] = instantiateFileHandlerJson({ "attributes": { "class": ["filename", "description"] } }); - $content = $(fileHandler.buildContent()); + wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.attr('class'), 'test-filename', 'Verified not setting fallback attribute when first value is not empty: ' + fileHandler.buildContent()); + assert.strictEqual( + wrapper.firstChild.classList.contains('test-filename'), + true, + `Verified not setting fallback attribute when first value is not empty: ${fileHandler.buildContent()}` + ); - fileHandler = instantiateFileHandlerJson({ + [fileHandler] = instantiateFileHandlerJson({ "attributes": { "class": ["filename", "description"], "title": ["does-not-exist", "filename"] } }); - $content = $(fileHandler.buildContent()); + wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.attr('class') + '_' + $content.attr('title'), 'test-filename_test-filename', 'Verified setting two attributes: ' + fileHandler.buildContent()); + assert.strictEqual( + wrapper.firstChild.classList.contains('test-filename'), + true, + `Verified setting two attributes: ${fileHandler.buildContent()}` + ); + + assert.strictEqual( + wrapper.firstChild.getAttribute('title'), + 'test-filename' + ); }); - QUnit.test('buildContent(): content attachments', function(assert) { - var fileHandler = instantiateFileHandlerJson({ - "content": ["description"] - }); + QUnit.test('buildContent(): content attachments', assert => { + let [fileHandler] = instantiateFileHandlerJson({ + "content": ["description"] + }); - var $content = $(fileHandler.buildContent()); + let wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.text(), 'test-description', 'Verified setting content: ' + fileHandler.buildContent()); + assert.strictEqual(wrapper.firstChild.innerText, 'test-description'); - fileHandler = instantiateFileHandlerJson({ - "content": ["does-not-exist", "description"] - }); + [fileHandler] = instantiateFileHandlerJson({ + "content": ["does-not-exist", "description"] + }); - $content = $(fileHandler.buildContent()); + wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.text(), 'test-description', 'Verified setting fallback content: ' + fileHandler.buildContent()); + assert.strictEqual(wrapper.firstChild.innerText, 'test-description'); - fileHandler = instantiateFileHandlerJson({ - "content": ["filename", "description"] - }); + [fileHandler] = instantiateFileHandlerJson({ + "content": ["filename", "description"] + }); - $content = $(fileHandler.buildContent()); + wrapper = document.createElement('div'); + wrapper.innerHTML = fileHandler.buildContent(); - assert.strictEqual($content.text(), 'test-filename', 'Verified not setting fallback content when first value is not empty: ' + fileHandler.buildContent()); + assert.strictEqual( + wrapper.firstChild.innerText, + 'test-filename', + `Verified not setting fallback content when first value is not empty: ${fileHandler.buildContent()}` + ); }); - QUnit.test('Update attribute in textarea', function(assert) { + QUnit.test('Update attribute in textarea', assert => { + const textarea = document.createElement('textarea'); - var $textarea = $('<textarea>'); + Drupal.insert.FocusManager.addTextarea(textarea); - focusManager.addTextareas($textarea); - - var fileHandler = instantiateFileHandlerJson({ + const [fileHandler, wrapper] = instantiateFileHandlerJson({ "id": "test-id", "attributes": { "class": ["description"] } }); - $textarea.val(fileHandler.buildContent()); + textarea.value = fileHandler.buildContent(); - var $dom = fileHandler._inserter.$container.parent(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - assert.strictEqual($($textarea.val()).attr('class'), 'overwritten', 'Updated attribute: ' + $textarea.val()); - }); + assert.true( + updatedWrapper.firstChild.classList.contains('overwritten'), + `Updated attribute: ${textarea.value}` + ); - QUnit.test('Update attributes of multiple instances in textarea', function(assert) { + assert.strictEqual( + updatedWrapper.firstChild.classList.length, + 1, + `Updated attribute: ${textarea.value}` + ); + }); - var $textarea = $('<textarea>'); + QUnit.test('Update attributes of multiple instances in textarea', assert => { + const textarea = document.createElement('textarea'); - focusManager.addTextareas($textarea); + Drupal.insert.FocusManager.addTextarea(textarea); - var fileHandler = instantiateFileHandlerJson({ + const [fileHandler, wrapper] = instantiateFileHandlerJson({ "id": "test-id", "attributes": { "class": ["description"] } }); - $textarea.val(fileHandler.buildContent() + fileHandler.buildContent()); + textarea.value = fileHandler.buildContent() + fileHandler.buildContent(); - var $dom = fileHandler._inserter.$container.parent(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - assert.strictEqual( - $($textarea.val()).eq(0).attr('class') + '_' + $($textarea.val()).eq(1).attr('class'), - 'overwritten_overwritten', - 'Updated attribute: ' + $textarea.val() + assert.true( + updatedWrapper.querySelectorAll('span')[0].classList.contains('overwritten'), + `Updated attribute of first element: ${textarea.value}` ); - }); - QUnit.test('Update content in textarea', function(assert) { + assert.true( + updatedWrapper.querySelectorAll('span')[1].classList.contains('overwritten'), + `Updated attribute of second element: ${textarea.value}` + ); + }); - var $textarea = $('<textarea>'); + QUnit.test('Update content in textarea', assert => { + const textarea = document.createElement('textarea'); - focusManager.addTextareas($textarea); + Drupal.insert.FocusManager.addTextarea(textarea); - var fileHandler = instantiateFileHandlerJson({ + const [fileHandler, wrapper] = instantiateFileHandlerJson({ "id": "test-id", "content": ["description"] }); - $textarea.val(fileHandler.buildContent()); + textarea.value = fileHandler.buildContent(); - var $dom = fileHandler._inserter.$container.parent(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - assert.strictEqual($($textarea.val()).text(), 'overwritten', 'Updated content: ' + $textarea.val()); + assert.strictEqual( + updatedWrapper.querySelector('span').innerText, + 'overwritten', + `Updated content: ${textarea.value}` + ); }); - QUnit.test('Update content of multiple instances in textarea', function(assert) { + QUnit.test('Update content of multiple instances in textarea', assert => { + const textarea = document.createElement('textarea'); - var $textarea = $('<textarea>'); + Drupal.insert.FocusManager.addTextarea(textarea); - focusManager.addTextareas($textarea); - - var fileHandler = instantiateFileHandlerJson({ + const [fileHandler, wrapper] = instantiateFileHandlerJson({ "id": "test-id", "content": ["description"] }); - $textarea.val(fileHandler.buildContent() + fileHandler.buildContent()); + textarea.value = fileHandler.buildContent() + fileHandler.buildContent(); + + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $dom = fileHandler._inserter.$container.parent(); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + assert.strictEqual( + updatedWrapper.querySelectorAll('span')[0].innerText, + 'overwritten', + `Updated content of first element: ${textarea.value}` + ); assert.strictEqual( - $($textarea.val()).eq(0).text() + '_' + $($textarea.val()).eq(1).text(), - 'overwritten_overwritten', - 'Updated content: ' + $textarea.val() + updatedWrapper.querySelectorAll('span')[1].innerText, + 'overwritten', + `Updated content of second element: ${textarea.value}` ); }); - QUnit.test('Update attribute in CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update attribute in CKEditor instance', async (assert) => { + const done = assert.async(); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "attributes": { - "class": ["description"] - } - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "attributes": { + "class": ["description"] + } + }); - $(editor.document.$).find('body').empty().append(fileHandler.buildContent()); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).data, + 'test', + 'Verified content before altering' + ); - var $alteredDom = $(editor.document.$).find('body').children(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - assert.strictEqual($alteredDom.attr('class'), 'overwritten', 'Updated attribute: ' + $(editor.document.$).find('body').html()); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).getAttribute('htmlSpan').classes[0], + 'overwritten' + ); - done(); - }); + done(); }); - QUnit.test('Update attributes of multiple instances in CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update attributes of multiple instances in CKEditor instance', async (assert) => { + const done = assert.async(); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "attributes": { - "class": ["description"] - } - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "attributes": { + "class": ["description"] + } + }); - $(editor.document.$).find('body').empty() - .append(fileHandler.buildContent() + fileHandler.buildContent()); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent() + fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $alteredDom = $(editor.document.$).find('body').children(); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).getAttribute('htmlSpan').classes[0], + 'overwritten', + 'Verified first item being updated' + ); - assert.strictEqual( - $alteredDom.eq(0).attr('class') + '_' + $alteredDom.eq(1).attr('class'), - 'overwritten_overwritten', - 'Updated attribute: ' + $(editor.document.$).find('body').html() - ); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 1]).getAttribute('htmlSpan').classes[0], + 'overwritten', + 'Verified second item to be updated' + ); - done(); - }); + done(); }); - QUnit.test('Update content in CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update content in CKEditor instance', async (assert) => { + const done = assert.async(); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "content": ["description"] - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; - - $(editor.document.$).find('body').empty().append(fileHandler.buildContent()); + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "content": ["description"] + }); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent() + fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $alteredDom = $(editor.document.$).find('body').children(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - assert.strictEqual($alteredDom.text(), 'overwritten', 'Updated content: ' + $(editor.document.$).find('body').html()); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).data, + 'overwritten' + ); - done(); - }); + done(); }); - QUnit.test('Update content of multiple instances in CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update content of multiple instances in CKEditor instance', async (assert) => { + const done = assert.async(); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "content": ["description"] - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "content": ["description"] + }); - $(editor.document.$).find('body').empty() - .append(fileHandler.buildContent() + fileHandler.buildContent()); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent() + fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $alteredDom = $(editor.document.$).find('body').children(); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 1]).data, + 'overwritten', + 'Verified first item being updated' + ); - assert.strictEqual( - $alteredDom.eq(0).text() + '_' + $alteredDom.eq(1).text(), - 'overwritten_overwritten', - 'Updated content: ' + $(editor.document.$).find('body').html() - ); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 1]).data, + 'overwritten', + 'Verified second item being updated' + ); - done(); - }); + done(); }); - QUnit.test('Update attributes in textarea and CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update attributes in textarea and CKEditor instance', async (assert) => { + const done = assert.async(); - var $textarea = $('<textarea>'); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + const textarea = document.createElement('textarea'); - focusManager.addTextareas($textarea); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addTextarea(textarea); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "attributes": { - "class": ["description"] - } - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "attributes": { + "class": ["description"] + } + }); + + textarea.value = fileHandler.buildContent(); - $textarea.val(fileHandler.buildContent()); - $(editor.document.$).find('body').empty().append(fileHandler.buildContent()); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - var $alteredDom = $(editor.document.$).find('body').children(); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - assert.strictEqual( - $alteredDom.attr('class'), - 'overwritten', - 'Updated editor attribute: ' + $(editor.document.$).find('body').html() - ); + assert.true( + updatedWrapper.firstChild.classList.contains('overwritten'), + `Updated attribute: ${textarea.value}` + ); - assert.strictEqual( - $($textarea.val()).attr('class'), - 'overwritten', - 'Updated textarea attribute: ' + $textarea.val() - ); + assert.strictEqual( + updatedWrapper.firstChild.classList.length, + 1, + `Updated attribute: ${textarea.value}` + ); - done(); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).getAttribute('htmlSpan').classes[0], + 'overwritten' + ); - }); + done(); }); - QUnit.test('Update content in textarea and CKEditor instance', function(assert) { - var done = assert.async(); + QUnit.test('Update content in textarea and CKEditor instance', async (assert) => { + const done = assert.async(); - var $textarea = $('<textarea>'); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + const textarea = document.createElement('textarea'); - focusManager.addTextareas($textarea); + editor = await Drupal.insert.testUtil.createEditor(); - editor.on('contentDom', function() { - focusManager.addEditor(editor); + Drupal.insert.FocusManager.addTextarea(textarea); + Drupal.insert.FocusManager.addEditor(editor); - var instantiation = instantiateFileHandlerJson({ - "id": "test-id", - "content": ["description"] - }, true); - var fileHandler = instantiation[0]; - var $dom = instantiation[1]; + const [fileHandler, wrapper] = instantiateFileHandlerJson({ + "id": "test-id", + "content": ["description"] + }); - $textarea.val(fileHandler.buildContent()); - $(editor.document.$).find('body').empty().append(fileHandler.buildContent()); + textarea.value = fileHandler.buildContent(); - var $description = $dom.find('.insert-description'); - $description.val('overwritten'); - $description.trigger('input'); + editor.model.change(writer => { + const viewFragment = editor.data.processor.toView(fileHandler.buildContent()); + const modelFragment = editor.data.toModel(viewFragment); + writer.model.insertContent(modelFragment); + }); - var $alteredDom = $(editor.document.$).find('body').children(); + const description = wrapper.querySelector('.insert-description'); + description.value = 'overwritten'; + description.dispatchEvent(new Event('input')); - assert.strictEqual( - $alteredDom.text(), - 'overwritten', - 'Updated editor attribute: ' + $(editor.document.$).find('body').html() - ); + const updatedWrapper = document.createElement('div'); + updatedWrapper.innerHTML = textarea.value; - assert.strictEqual( - $($textarea.val()).text(), - 'overwritten', - 'Updated textarea attribute: ' + $textarea.val() - ); + assert.strictEqual( + updatedWrapper.querySelector('span').innerText, + 'overwritten', + `Updated content: ${textarea.value}` + ); - done(); + assert.strictEqual( + editor.model.document.getRoot().getNodeByPath([[0], 0]).data, + 'overwritten' + ); - }); + done(); }); -})(QUnit, jQuery, Drupal, CKEDITOR); +})(QUnit, Drupal); diff --git a/tests/js/FocusManager.js b/tests/js/FocusManager.js index daab36702f66874f15b65475bd3ccba812f71a98..35edb3a83ebc410e61e4fbec45383ebe78eb8fb8 100644 --- a/tests/js/FocusManager.js +++ b/tests/js/FocusManager.js @@ -1,143 +1,134 @@ -(function(QUnit, $, Drupal, CKEDITOR) { - QUnit.module('FocusManager', { - afterEach: function() { - $.each(CKEDITOR.instances, function(id, editor) { - var element = editor.element; - editor.destroy(); - element.$.remove(); - }); +(function(QUnit, Drupal) { - CKEDITOR.currentInstance = undefined; + let editor; - $('.insert-test').remove(); + QUnit.module('FocusManager', { + beforeEach: () => { + Drupal.insert.FocusManager = new Drupal.insert.Manager(); + }, + afterEach: async () => { + for (const textarea of document.getElementsByClassName('insert-test')) { + textarea.remove(); + } + + if (editor) { + const sourceElement = editor.sourceElement; + await editor.destroy(); + sourceElement.remove(); + editor = undefined; + } + + return true; } + }) + + QUnit.test('Instantiation', assert => { + const focusManager = new Drupal.insert.Manager(); + assert.ok( + focusManager instanceof Drupal.insert.Manager, + 'Instantiated FocusManager' + ); }); - var editorInterface = Drupal.insert.editors.interfaces.CKEditor; - - QUnit.test('Instantiation', function(assert) { - var focusManager = new Drupal.insert.FocusManager(); - assert.ok(focusManager instanceof Drupal.insert.FocusManager, 'Instantiated FocusManager without editor interface.'); - - focusManager = new Drupal.insert.FocusManager(editorInterface); - assert.ok(focusManager instanceof Drupal.insert.FocusManager, 'Instantiated FocusManager with editor interface.'); - }); + QUnit.test('addEditor / getEditors', async (assert) => { + const done = assert.async(); - QUnit.test('addEditor / getEditors', function(assert) { - var focusManager = new Drupal.insert.FocusManager(editorInterface); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + const focusManager = new Drupal.insert.Manager(); + editor = await Drupal.insert.testUtil.createEditor(); focusManager.addEditor(editor); - assert.strictEqual(focusManager.getEditors().length, 1, 'getEditors() returns one item.'); - assert.ok(focusManager.getEditors()[0] instanceof CKEDITOR.editor, 'getEditors() returns editor.'); - - editor.focusManager.focus(true); - - assert.ok($(editorInterface.getElement(editor)).data('insertIsFocused'), 'insertIsFocused is true after focusing.'); - assert.ok($(editorInterface.getElement(editor)).data('insertLastFocused'), 'insertLastFocused is true after focusing.'); - - // Causes error in Chrome, see https://dev.ckeditor.com/ticket/16825 - editor.focusManager.blur(true); + assert.strictEqual(focusManager.editors.length, 1, 'Added one editor'); + assert.strictEqual( + focusManager.editors[0].id, + editor.id, + 'editors() returns editor' + ); - assert.ok($(editorInterface.getElement(editor)).data('insertIsFocused'), 'Still, insertIsFocused is true immediately after blurring.'); - assert.ok($(editorInterface.getElement(editor)).data('insertLastFocused'), 'Still, insertLastFocused is true after blurring.'); - - var done = assert.async(); - - setTimeout(function() { - assert.ok(typeof $(editorInterface.getElement(editor)).data('insertIsFocused') === 'undefined', 'insertIsFocused is undefined after blurring.'); - done(); - }, 1500); + done(); }); - QUnit.test('addTextareas / getTextareas', function(assert) { - var focusManager = new Drupal.insert.FocusManager(); - var $textarea = $('<textarea>').addClass('insert-test').appendTo('body'); - - focusManager.addTextareas($textarea); - - assert.strictEqual(focusManager.getTextareas().length, 1, 'getTextareas() returns one item.'); - assert.strictEqual(focusManager.getTextareas().get(0), $textarea.get(0), 'getTextareas() returns text area.'); - - $textarea.focus(); - - assert.ok($textarea.data('insertIsFocused'), 'insertIsFocused is true after focusing.'); - assert.ok($textarea.data('insertLastFocused'), 'insertLastFocused is true after focusing.'); - - $textarea.blur(); + QUnit.test('addTextareas / getTextareas', assert => { + const focusManager = new Drupal.insert.Manager(); + const textarea = document.createElement('textarea'); + textarea.classList.add('insert-test'); + document.querySelector('body').appendChild(textarea); + + focusManager.addTextarea(textarea); + + assert.strictEqual( + focusManager.textareas.length, + 1, + 'Added one textarea' + ); + assert.strictEqual( + focusManager.textareas[0], + textarea, + 'textareas() returns textarea' + ); + }); - assert.ok($textarea.data('insertIsFocused'), 'Still, insertIsFocused is true immediately after blurring.'); - assert.ok($textarea.data('insertLastFocused'), 'Still, insertLastFocused is true after blurring.'); + QUnit.test('getTarget', async assert => { + const done = assert.async(); - var done = assert.async(); + const focusManager = new Drupal.insert.Manager(); - setTimeout(function() { - assert.ok(typeof $textarea.data('insertIsFocused') === 'undefined', 'insertIsFocused is undefined after blurring.'); - done(); - }, 1500); - }); + const textarea = document.createElement('textarea'); + textarea.classList.add('insert-test'); + document.querySelector('body').appendChild(textarea); - QUnit.test('getActive', function(assert) { - var focusManager = new Drupal.insert.FocusManager(editorInterface); - var $textarea = $('<textarea>').addClass('insert-test').appendTo('body'); - var $editor = $('<div>').appendTo('body'); - var editor = CKEDITOR.replace($editor.get(0)); + editor = await Drupal.insert.testUtil.createEditor(); - focusManager.addTextareas($textarea); + focusManager.addTextarea(textarea); focusManager.addEditor(editor); - assert.strictEqual(focusManager.getActive(), null, 'Returning null when no input was focused yet.'); + assert.strictEqual( + focusManager.getTarget().id, + editor.id, + 'Returning first editor instance when nothing has been focused yet' + ); - $textarea.focus(); + textarea.focus(); - assert.strictEqual(focusManager.getActive(), $textarea.get(0), 'Returning textarea after focusing.'); + assert.strictEqual( + focusManager.getTarget(), + textarea, + 'Returning textarea after focusing' + ); - editor.focusManager.focus(); + editor.focus(); - assert.strictEqual(focusManager.getActive().id, editor.id, 'Returning editor after focusing.'); + assert.strictEqual( + focusManager.getTarget().id, + editor.id, + 'Returning editor after focusing' + ); - $textarea.focus(); + textarea.focus(); - assert.strictEqual(focusManager.getActive(), $textarea.get(0), 'Returning textarea after re-focusing.'); + assert.strictEqual( + focusManager.getTarget(), + textarea, + 'Returning textarea after re-focusing' + ); - $textarea.blur(); + textarea.blur(); - assert.strictEqual(focusManager.getActive(), $textarea.get(0), 'Returning textarea after bluring.'); + assert.strictEqual( + focusManager.getTarget(), + textarea, + 'Returning textarea after bluring' + ); - var done = assert.async(); + setTimeout(() => { + assert.strictEqual( + focusManager.getTarget(), + textarea, + 'Returning textarea after some sleep' + ); - setTimeout(function() { - assert.strictEqual(focusManager.getActive(), $textarea.get(0), 'Returning textarea after some sleep.'); done(); - }, 1500); - }); - - QUnit.test('setDefaultTarget', function(assert) { - var focusManager = new Drupal.insert.FocusManager(editorInterface); - var $textarea1 = $('<textarea>').addClass('insert-test insert-test-1').appendTo('body'); - var $textarea2 = $('<textarea>').addClass('insert-test insert-test-2').appendTo('body'); - - focusManager.addTextareas($textarea1.add($textarea2)); - - focusManager.setDefaultTarget($textarea1.get(0)); - - assert.strictEqual(focusManager.getActive(), $textarea1.get(0), 'Returning first textarea after setting default target to first textarea.'); - - $textarea1.focus(); - - assert.strictEqual(focusManager.getActive(), $textarea1.get(0), 'Still returning first textarea after focusing.'); - - $textarea2.focus(); - - assert.strictEqual(focusManager.getActive(), $textarea2.get(0), 'Returning second textarea after focusing second textarea while first textarea is the default target.'); - - $textarea1.focus(); - $textarea1.blur(); - focusManager.setDefaultTarget($textarea2.get(0)); - - assert.strictEqual(focusManager.getActive(), $textarea1.get(0), 'Returning first textarea after setting second default target to second textarea, because first textarea was focused last.'); + }, 1000); }); -})(QUnit, jQuery, Drupal, CKEDITOR); \ No newline at end of file +})(QUnit, Drupal); \ No newline at end of file diff --git a/tests/js/ImageHandler.js b/tests/js/ImageHandler.js deleted file mode 100644 index 00d80b520d81321d3f4c85d9af6c9a0897c1a5bc..0000000000000000000000000000000000000000 --- a/tests/js/ImageHandler.js +++ /dev/null @@ -1,58 +0,0 @@ -(function(QUnit, $, Drupal, CKEDITOR) { - - QUnit.module('ImageHandler', { - afterEach: function() { - $.each(CKEDITOR.instances, function(id, editor) { - var element = editor.element; - editor.destroy(); - element.$.remove(); - }); - - CKEDITOR.currentInstance = undefined; - } - }); - - var $baseDom = $('<div class="insert-test-wrapper">\ - <input class="insert-filename" value="test-filename">\ - <input class="insert-title" name="field-name[title]" value="test-title">\ - <div class="insert-test">\ - <input class="insert-style" value="test">\ - <div class="insert-templates">\ - </div>\ - <div class="insert-button" data-insert-id="test-id"></div>\ - </div>\ - </div>\ - '); - - var editorInterface = Drupal.insert.editors.interfaces.CKEditor; - var focusManager = new Drupal.insert.FocusManager(editorInterface); - - /** - * @param {string} template - * @param {Object} [settings] - * @return {Drupal.insert.ImageHandler} - */ - function instantiateImageHandler(template, settings) { - var $dom = $baseDom.clone(); - $dom.find('.insert-templates').append( - $('<input class="insert-template" name="insert-template[test]" value="' + template + '">') - ); - var inserter = new Drupal.insert.Inserter($dom.find('.insert-test').get(0), focusManager, editorInterface); - return new Drupal.insert.ImageHandler(inserter, settings); - } - - /** - * @param {Object} attach - * @param {Object} [settings] - * @return {Drupal.insert.ImageHandler} - */ - function instantiateImageHandlerJson(attach, settings) { - return instantiateImageHandler('' - + '<img src=\'*\' data-insert-attach=\'' - + JSON.stringify(attach).replace(/"/g, '"') - + '\'>', - settings - ); - } - -})(QUnit, jQuery, Drupal, CKEDITOR); diff --git a/tests/js/Inserter.js b/tests/js/Inserter.js index 0975fdad000d35da45ad24deea2d92318f94a083..e62ff5df759db9d27745496fa0fe5bde6d9888b5 100644 --- a/tests/js/Inserter.js +++ b/tests/js/Inserter.js @@ -1,68 +1,42 @@ -(function(QUnit, $, Drupal, CKEDITOR) { +(function(QUnit, Drupal) { QUnit.module('Inserter', { - afterEach: function() { - $.each(CKEDITOR.instances, function(id, editor) { - var element = editor.element; - editor.destroy(); - element.$.remove(); - }); - - CKEDITOR.currentInstance = undefined; - - $('.insert-test').remove(); + afterEach: () => { + for (const temp of document.getElementsByClassName('insert-test')) { + temp.remove(); + } } }); - var editorInterface = Drupal.insert.editors.interfaces.CKEditor; - var focusManager = new Drupal.insert.FocusManager(editorInterface); - - var $dom = $('<div class="insert-test" data-insert-type="test">\ - <input class="insert-style" type="hidden" value="test">\ + const dom = '<input class="insert-style" type="hidden" value="test">\ <div class="insert-templates">\ <input class="insert-template" type="hidden" name="insert-template[test]" value="<span attr="__unused__">__filename__</span>">\ </div>\ - </div>\ - ').appendTo('body'); + <button class="insert-button">Insert</button>'; - QUnit.test('getFocusManager()', function(assert) { - var inserter = new Drupal.insert.Inserter( - $dom.get(0), - focusManager, - editorInterface - ); + QUnit.test('Insert content into textarea', assert => { + const container = document.createElement('div'); + container.classList.add('insert-test'); + container.innerHTML = dom; + document.querySelector('body').append(container); - assert.strictEqual(inserter.getFocusManager(), focusManager, 'Verified returning FocusManager instance.'); - }); + const textarea = document.createElement('textarea'); - QUnit.test('getEditorInterface()', function(assert) { - var inserter = new Drupal.insert.Inserter( - $dom.get(0), - focusManager, - editorInterface - ); - - assert.strictEqual(inserter.getEditorInterface(), editorInterface, 'Verified returning EditorInterface instance.'); - }); + Drupal.insert.FocusManager = new Drupal.insert.Manager(); + Drupal.insert.FocusManager.addTextarea(textarea); - QUnit.test('getType()', function(assert) { - var inserter = new Drupal.insert.Inserter( - $dom.get(0), - focusManager, - editorInterface + const inserter = new Drupal.insert.Inserter( + container, + new Drupal.insert.FileHandler(container) ); - assert.strictEqual(inserter.getType(), 'test', 'Verified returning insert type.'); - }); + document.querySelector('.insert-button').dispatchEvent(new Event('click')); - QUnit.test('getTemplate()', function(assert) { - var inserter = new Drupal.insert.Inserter( - $dom.get(0), - focusManager, - editorInterface + assert.strictEqual( + textarea.value, + '<span attr="__unused__">__filename__</span>', + 'Content is inserted' ); - - assert.strictEqual(inserter.getTemplate(), $dom.find('[name="insert-template[test]"]').val(), 'Verified returning template.'); }); -})(QUnit, jQuery, Drupal, CKEDITOR); +})(QUnit, Drupal); diff --git a/tests/js/index.html b/tests/js/index.html index c6c5fe7534aec36ba4e480cd90763ed9a54c0c72..6af1439076f42dc774ffe82c0b053091a7a75caa 100644 --- a/tests/js/index.html +++ b/tests/js/index.html @@ -1,27 +1,22 @@ <!DOCTYPE html> -<html> +<html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Insert module QUnit test runner</title> - <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.1.1.css"> + <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.20.1.css"> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"></div> - <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> - <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> - <script src="https://cdn.ckeditor.com/4.6.2/standard/ckeditor.js"></script> - <script src="https://code.jquery.com/qunit/qunit-2.1.1.js"></script> + <script src="https://cdn.ckeditor.com/ckeditor5/41.2.0/super-build/ckeditor.js"></script> + <script src="https://code.jquery.com/qunit/qunit-2.20.1.js"></script> <script src="namespaceMock.js"></script> + <script src="util.js"></script> <script src="../../js/namespace.js"></script> - <script src="../../js/editors/namespace.js"></script> - <script src="../../js/EditorInterface.js"></script> - <script src="../../js/editors/CKEditor.js"></script> - <script src="../../js/EditorManager.js"></script> <script src="../../js/FocusManager.js"></script> <script src="../../js/Inserter.js"></script> @@ -29,10 +24,8 @@ <script src="../../js/FileHandler.js"></script> <script src="../../js/ImageHandler.js"></script> - <script src="EditorManager.js"></script> <script src="FileHandler.js"></script> <script src="FocusManager.js"></script> - <script src="ImageHandler.js"></script> <script src="Inserter.js"></script> </body> diff --git a/tests/js/namespaceMock.js b/tests/js/namespaceMock.js index 988f63d843a425e2d5c6dcf3618aab2fefd63d04..6170517b0426c581d9e6bd11ca68ac596fc0b7a1 100644 --- a/tests/js/namespaceMock.js +++ b/tests/js/namespaceMock.js @@ -1,4 +1,4 @@ 'use strict'; -var Drupal = {}; +const Drupal = {}; Drupal.insert = {}; diff --git a/tests/js/util.js b/tests/js/util.js new file mode 100644 index 0000000000000000000000000000000000000000..54c1fd5368135db2b7b9c1cfc372277e3d6e415c --- /dev/null +++ b/tests/js/util.js @@ -0,0 +1,64 @@ +(function(ClassicEditor) { + Drupal.insert.testUtil = { + async createEditor() { + const container = document.createElement('div'); + container.setAttribute('id', 'editor'); + document.querySelector('body').append(container); + + return ClassicEditor.create(container, { + // In order to avoid having a build process to have an editor constructor featuring the + // GeneralHtmlSupport plugin, the super build is used from the CKEditor CDN. Since that + // build features plugins that require configuration and plugins that require a license, + // those plugins need to be specifically disabled. + removePlugins: [ + 'AIAssistant', + 'CaseChange', + 'CKBox', + 'CKBoxEditing', + 'CKBoxImageEdit', + 'CKBoxImageEditEditing', + 'CKBoxUtils', + 'CloudServices', + 'CloudServicesUploadAdapter', + 'Comments', + 'CommentsRepository', + 'ContentTemplates', + 'DocumentOutline', + 'EasyImage', + 'ExportPdf', + 'ExportWord', + 'FormatPainter', + 'PasteFromOffice', + 'Pagination', + 'PasteFromOfficeEnhanced', + 'PresenceList', + 'RealTimeCollaborationClient', + 'RealTimeCollaborativeEditing', + 'RealTimeCollaborativeComments', + 'RealTimeCollaborativeRevisionHistory', + 'RealTimeCollaborativeTrackChanges', + 'RevisionHistory', + 'RevisionTracker', + 'SlashCommand', + 'TableOfContents', + 'Template', + 'TrackChanges', + 'TrackChangesData', + 'TrackChangesEditing', + 'Users', + 'WProofreader', + ], + htmlSupport: { + allow: [ + { + name: /.*/, + attributes: true, + classes: true, + styles: true + }, + ], + }, + }); + } + } +})(CKEDITOR.ClassicEditor); \ No newline at end of file diff --git a/tests/src/FunctionalJavaScript/InsertFileTestBase.php b/tests/src/FunctionalJavaScript/InsertFileTestBase.php index a8e5c19cb4e8c59eee2f7f00fa3084dda604bdf4..e6eada4d33a5b20fd6f4e57da2f4402149741169 100644 --- a/tests/src/FunctionalJavaScript/InsertFileTestBase.php +++ b/tests/src/FunctionalJavaScript/InsertFileTestBase.php @@ -12,6 +12,8 @@ use Drupal\Tests\TestFileCreationTrait; */ abstract class InsertFileTestBase extends WebDriverTestBase { + protected $defaultTheme = 'stark'; + use FileFieldCreationTrait { createFileField as drupalCreateFileField; }