Fix Draftail initialising on the wrong elt. Fix #4295 (#4301)

This commit is contained in:
Thibaud Colas 2018-02-21 13:07:28 +02:00 committed by Matt Westcott
parent 74a75b0f3b
commit a35831ce8f
4 changed files with 56 additions and 22 deletions

View file

@ -43,11 +43,14 @@ export const wrapWagtailIcon = type => {
/**
* Initialises the DraftailEditor for a given field.
* @param {string} fieldName
* @param {string} selector
* @param {Object} options
* @param {Element} currentScript
*/
const initEditor = (fieldName, options) => {
const field = document.querySelector(`[name="${fieldName}"]`);
const initEditor = (selector, options, currentScript) => {
// document.currentScript is not available in IE11. Use a fallback instead.
const context = currentScript ? currentScript.parentNode : document.body;
const field = context.querySelector(selector);
const editorWrapper = document.createElement('div');
editorWrapper.className = 'Draftail-Editor__wrapper';

View file

@ -10,27 +10,24 @@ import draftail, {
describe('Draftail', () => {
describe('#initEditor', () => {
beforeEach(() => {
document.head.innerHTML = '';
document.body.innerHTML = '';
});
it('works', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
document.body.innerHTML = '<input type="text" id="test" value="null" />';
const field = document.querySelector('#test');
draftail.initEditor('test', {});
draftail.initEditor('#test', {});
expect(field.draftailEditor).toBeDefined();
});
it('onSave', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
document.body.innerHTML = '<input id="test" value="null" />';
const field = document.querySelector('#test');
draftail.initEditor('test', {});
draftail.initEditor('#test', {});
field.draftailEditor.saveState();
@ -38,10 +35,8 @@ describe('Draftail', () => {
});
it('options', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
document.body.innerHTML = '<input id="test" value="null" />';
const field = document.querySelector('#test');
draftail.registerPlugin({
type: 'IMAGE',
@ -49,7 +44,7 @@ describe('Draftail', () => {
block: () => {},
});
draftail.initEditor('test', {
draftail.initEditor('#test', {
entityTypes: [
{ type: 'IMAGE' },
],
@ -58,6 +53,42 @@ describe('Draftail', () => {
expect(field.draftailEditor.props).toMatchSnapshot();
});
describe('selector conflicts', () => {
it('fails to instantiate on the right field', () => {
document.body.innerHTML = '<meta name="description" content="null" /><input name="description" value="null" />';
expect(() => {
draftail.initEditor('[name="description"]', {}, document.body);
}).toThrow(SyntaxError);
});
it('fails to instantiate on the right field when currentScript is not used', () => {
window.draftail = draftail;
document.body.innerHTML = `
<input name="first" id="description" value="null" />
<div>
<input name="last" id="description" value="null" />
<script>window.draftail.initEditor('#description', {});</script>
</div>
`;
expect(document.querySelector('[name="last"]').draftailEditor).not.toBeDefined();
});
it('has no conflict when currentScript is used', () => {
window.draftail = draftail;
document.body.innerHTML = `
<input name="first" id="description" value="null" />
<div>
<input name="last" id="description" value="null" />
<script>window.draftail.initEditor('#description', {}, document.currentScript);</script>
</div>
`;
expect(document.querySelector('[name="last"]').draftailEditor).toBeDefined();
});
});
});
describe('#wrapWagtailIcon', () => {

View file

@ -52,8 +52,8 @@ class DraftailRichTextArea(WidgetWithScript, widgets.HiddenInput):
return super().render(name, translated_value, attrs)
def render_js_init(self, id_, name, value):
return "window.draftail.initEditor('{name}', {opts})".format(
name=name, opts=json.dumps(self.options))
return "window.draftail.initEditor('#{id}', {opts}, document.currentScript)".format(
id=id_, opts=json.dumps(self.options))
def value_from_datadict(self, data, files, name):
original_value = super().value_from_datadict(data, files, name)

View file

@ -102,7 +102,7 @@ class TestDefaultRichText(BaseRichTextEditHandlerTestCase, WagtailTestUtils):
self.assertEqual(response.status_code, 200)
# Check that draftail (default editor) initialisation is applied
self.assertContains(response, "window.draftail.initEditor('body',")
self.assertContains(response, "window.draftail.initEditor('#id_body',")
# check that media for draftail is being imported
self.assertContains(response, 'wagtailadmin/js/draftail.js')
@ -121,7 +121,7 @@ class TestDefaultRichText(BaseRichTextEditHandlerTestCase, WagtailTestUtils):
self.assertEqual(response.status_code, 200)
# Check that draftail (default editor) initialisation is applied
self.assertContains(response, "window.draftail.initEditor('__PREFIX__-value',")
self.assertContains(response, "window.draftail.initEditor('#__PREFIX__-value',")
# check that media for draftail is being imported
self.assertContains(response, 'wagtailadmin/js/draftail.js')