Add missing unit tests for Draftail JS code

This commit is contained in:
Thibaud Colas 2018-02-03 00:11:21 +02:00 committed by Matt Westcott
parent d77f8681e0
commit e3ab5c5ff5
19 changed files with 893 additions and 88 deletions

View file

@ -0,0 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Draftail #initEditor options 1`] = `
Object {
"autoCapitalize": null,
"autoComplete": null,
"autoCorrect": null,
"blockTypes": Array [],
"decorators": Array [],
"enableHorizontalRule": Object {
"description": "Horizontal line",
},
"enableLineBreak": Object {
"description": "Line break",
},
"entityTypes": Array [
Object {
"block": [Function],
"decorator": undefined,
"source": [Function],
"type": "Image",
},
],
"inlineStyles": Array [],
"maxListNesting": 4,
"onSave": [Function],
"placeholder": "Write here…",
"rawContentState": null,
"showRedoControl": Object {
"description": "Redo",
},
"showUndoControl": Object {
"description": "Undo",
},
"spellCheck": true,
"stateSaveInterval": 250,
"stripPastedStyles": false,
"textAlignment": null,
"textDirectionality": null,
}
`;
exports[`Draftail #wrapWagtailIcon works 1`] = `
<Icon
className={null}
name="media"
title={null}
/>
`;

View file

@ -21,7 +21,7 @@ class ImageBlock extends Component {
const { editorState, onChange } = blockProps;
const data = {
alt: e.currentTarget.value,
alt: e.target.value,
};
onChange(DraftUtils.updateBlockEntity(editorState, block, data));

View file

@ -65,8 +65,7 @@ describe('ImageBlock', () => {
).toMatchSnapshot();
});
// Alt field is readonly for now.
it.skip('changeAlt', () => {
it('changeAlt', () => {
jest.spyOn(DraftUtils, 'updateBlockEntity');
DraftUtils.updateBlockEntity.mockImplementation(e => e);
@ -88,11 +87,17 @@ describe('ImageBlock', () => {
/>
);
wrapper.find('[type="text"]').simulate('change', {
currentTarget: {
// // Alt field is readonly for now.
wrapper.instance().changeAlt({
target: {
value: 'new alt',
},
}
});
// wrapper.find('[type="text"]').simulate('change', {
// target: {
// value: 'new alt',
// },
// });
expect(onChange).toHaveBeenCalled();
expect(DraftUtils.updateBlockEntity).toHaveBeenCalledWith(

View file

@ -86,7 +86,7 @@ describe('MediaBlock', () => {
).toMatchSnapshot();
});
it.skip('large viewport', () => {
it('large viewport', () => {
const target = document.createElement('div');
document.body.appendChild(target);
target.getBoundingClientRect = () => ({

View file

@ -61,7 +61,7 @@ class TooltipEntity extends Component {
closeOnResize
>
<Tooltip target={showTooltipAt} direction="top">
{url ? (
{(
<a
href={url}
title={url}
@ -71,7 +71,7 @@ class TooltipEntity extends Component {
>
{shortenLabel(label)}
</a>
) : null}
)}
<button
className="button Tooltip__button"

View file

@ -0,0 +1,85 @@
import React from 'react';
import { shallow } from 'enzyme';
import TooltipEntity from './TooltipEntity';
describe('TooltipEntity', () => {
it('works', () => {
expect(shallow((
<TooltipEntity
entityKey="1"
onEdit={() => {}}
onRemove={() => {}}
icon="#icon-test"
url="https://www.example.com/"
label="www.example.com"
>
test
</TooltipEntity>
))).toMatchSnapshot();
});
it('shortened label', () => {
expect(shallow((
<TooltipEntity
entityKey="1"
onEdit={() => {}}
onRemove={() => {}}
icon="#icon-test"
url="https://www.example.com/"
label="www.example.example.example.com"
>
test
</TooltipEntity>
)).setState({
showTooltipAt: document.createElement('div').getBoundingClientRect(),
}).find('Tooltip a')
.text()).toBe('www.example.example.…');
});
it('#openTooltip', () => {
const wrapper = shallow((
<TooltipEntity
entityKey="1"
onEdit={() => {}}
onRemove={() => {}}
icon="#icon-test"
url="https://www.example.com/"
label="www.example.com"
>
test
</TooltipEntity>
));
wrapper.find('.TooltipEntity').simulate('mouseup', {
target: document.createElement('div'),
});
expect(wrapper).toMatchSnapshot();
});
it('#closeTooltip', () => {
const wrapper = shallow((
<TooltipEntity
entityKey="1"
onEdit={() => {}}
onRemove={() => {}}
icon="#icon-test"
url="https://www.example.com/"
label="www.example.com"
>
test
</TooltipEntity>
));
wrapper.find('.TooltipEntity').simulate('mouseup', {
target: document.createElement('div'),
});
wrapper.instance().closeTooltip();
expect(wrapper.state()).toEqual({
showTooltipAt: null,
});
});
});

View file

@ -0,0 +1,73 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TooltipEntity #openTooltip 1`] = `
<a
className="TooltipEntity"
onMouseUp={[Function]}
role="button"
>
<Icon
className="TooltipEntity__icon"
icon="#icon-test"
title={null}
/>
test
<Portal
closeOnClick={true}
closeOnResize={true}
closeOnType={true}
onClose={[Function]}
>
<Tooltip
direction="top"
target={
Object {
"bottom": 0,
"height": 0,
"left": 0,
"right": 0,
"top": 0,
"width": 0,
}
}
>
<a
className="Tooltip__link"
href="https://www.example.com/"
rel="noopener noreferrer"
target="_blank"
title="https://www.example.com/"
>
www.example.com
</a>
<button
className="button Tooltip__button"
onClick={[Function]}
>
Edit
</button>
<button
className="button button-secondary no Tooltip__button"
onClick={[Function]}
>
Remove
</button>
</Tooltip>
</Portal>
</a>
`;
exports[`TooltipEntity works 1`] = `
<a
className="TooltipEntity"
onMouseUp={[Function]}
role="button"
>
<Icon
className="TooltipEntity__icon"
icon="#icon-test"
title={null}
/>
test
</a>
`;

View file

@ -6,16 +6,18 @@ import { IS_IE11, STRINGS } from '../../config/wagtailConfig';
import Icon from '../Icon/Icon';
import Link from './decorators/Link';
import Document from './decorators/Document';
import ImageBlock from './blocks/ImageBlock';
import EmbedBlock from './blocks/EmbedBlock';
import ModalWorkflowSource from './sources/ModalWorkflowSource';
import registry from './registry';
const wrapWagtailIcon = type => {
export { registry };
export { default as Link } from './decorators/Link';
export { default as Document } from './decorators/Document';
export { default as ImageBlock } from './blocks/ImageBlock';
export { default as EmbedBlock } from './blocks/EmbedBlock';
export { default as ModalWorkflowSource } from './sources/ModalWorkflowSource';
export const wrapWagtailIcon = type => {
const isIconFont = type.icon && typeof type.icon === 'string';
if (isIconFont) {
return Object.assign(type, {
@ -26,7 +28,12 @@ const wrapWagtailIcon = type => {
return type;
};
export const initEditor = (fieldName, options = {}) => {
/**
* Initialises the DraftailEditor for a given field.
* @param {string} fieldName
* @param {Object} options
*/
export const initEditor = (fieldName, options) => {
const field = document.querySelector(`[name="${fieldName}"]`);
const editorWrapper = document.createElement('div');
field.parentNode.appendChild(editorWrapper);
@ -35,29 +42,19 @@ export const initEditor = (fieldName, options = {}) => {
field.value = JSON.stringify(rawContentState);
};
let blockTypes;
let inlineStyles;
let entityTypes;
const blockTypes = options.blockTypes || [];
const inlineStyles = options.inlineStyles || [];
let entityTypes = options.entityTypes || [];
if (options && options.blockTypes) {
blockTypes = options.blockTypes.map(wrapWagtailIcon);
}
entityTypes = entityTypes.map(wrapWagtailIcon).map(type =>
Object.assign(type, {
source: registry.getSource(type.source),
decorator: registry.getDecorator(type.decorator),
block: registry.getBlock(type.block),
})
);
if (options && options.inlineStyles) {
inlineStyles = options.inlineStyles.map(wrapWagtailIcon);
}
if (options && options.entityTypes) {
entityTypes = options.entityTypes.map(wrapWagtailIcon).map(type =>
Object.assign(type, {
source: registry.getSource(type.source),
decorator: registry.getDecorator(type.decorator),
block: registry.getBlock(type.block),
})
);
}
const enableHorizontalRule = options && options.enableHorizontalRule ? {
const enableHorizontalRule = options.enableHorizontalRule ? {
description: STRINGS.HORIZONTAL_LINE,
} : false;
@ -77,8 +74,8 @@ export const initEditor = (fieldName, options = {}) => {
// Draft.js + IE 11 presents some issues with pasting rich text. Disable rich paste there.
stripPastedStyles={IS_IE11}
{...options}
blockTypes={blockTypes}
inlineStyles={inlineStyles}
blockTypes={blockTypes.map(wrapWagtailIcon)}
inlineStyles={inlineStyles.map(wrapWagtailIcon)}
entityTypes={entityTypes}
enableHorizontalRule={enableHorizontalRule}
/>
@ -89,24 +86,3 @@ export const initEditor = (fieldName, options = {}) => {
// Bind editor instance to its field so it can be accessed imperatively elsewhere.
field.draftailEditor = draftailEditor;
};
registry.registerSources({
ModalWorkflowSource,
});
registry.registerDecorators({
Link,
Document,
});
registry.registerBlocks({
ImageBlock,
EmbedBlock,
});
const draftail = Object.assign(
{
initEditor,
},
registry
);
export default draftail;

View file

@ -0,0 +1,89 @@
import {
wrapWagtailIcon,
initEditor,
registry,
ModalWorkflowSource,
Link,
Document,
ImageBlock,
EmbedBlock,
} from './index';
describe('Draftail', () => {
describe('#initEditor', () => {
beforeEach(() => {
document.body.innerHTML = '';
});
it('works', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
initEditor('test', {});
expect(field.draftailEditor).toBeDefined();
});
it('onSave', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
initEditor('test', {});
field.draftailEditor.saveState();
expect(field.value).toBe('null');
});
it('options', () => {
const field = document.createElement('input');
field.name = 'test';
field.value = 'null';
document.body.appendChild(field);
registry.registerSources({
ModalWorkflowSource: () => {},
});
registry.registerBlocks({
ImageBlock: () => {},
});
initEditor('test', {
entityTypes: [
{ type: 'Image', source: 'ModalWorkflowSource', block: 'ImageBlock' },
],
enableHorizontalRule: true,
});
expect(field.draftailEditor.props).toMatchSnapshot();
});
});
describe('#wrapWagtailIcon', () => {
it('works', () => {
expect(wrapWagtailIcon({ icon: 'media' }).icon).toMatchSnapshot();
});
it('no icon', () => {
const type = {};
expect(wrapWagtailIcon(type)).toBe(type);
});
it('array icon', () => {
const type = { icon: ['M10 10 H 90 V 90 H 10 Z'] };
expect(wrapWagtailIcon(type)).toBe(type);
});
});
it('#registry', () => expect(registry).toBeDefined());
it('#ModalWorkflowSource', () => expect(ModalWorkflowSource).toBeDefined());
it('#Link', () => expect(Link).toBeDefined());
it('#Document', () => expect(Document).toBeDefined());
it('#ImageBlock', () => expect(ImageBlock).toBeDefined());
it('#EmbedBlock', () => expect(EmbedBlock).toBeDefined());
});

View file

@ -4,29 +4,19 @@ const registry = {
sources: {},
};
const registerDecorators = (decorators) => {
Object.assign(registry.decorators, decorators);
};
const registerDecorators = (decorators) => Object.assign(registry.decorators, decorators);
const registerBlocks = (blocks) => Object.assign(registry.blocks, blocks);
const registerSources = (sources) => Object.assign(registry.sources, sources);
const getDecorator = name => registry.decorators[name];
const registerBlocks = (blocks) => {
Object.assign(registry.blocks, blocks);
};
const getBlock = name => registry.blocks[name];
const registerSources = (sources) => {
Object.assign(registry.sources, sources);
};
const getSource = name => registry.sources[name];
export default {
registerDecorators,
getDecorator,
registerBlocks,
getBlock,
registerSources,
getDecorator,
getBlock,
getSource,
};

View file

@ -0,0 +1,39 @@
import registry from './registry';
describe('registry', () => {
describe('sources', () => {
it('works', () => {
expect(registry.getSource('UndefinedSource')).not.toBeDefined();
registry.registerSources({
TestSource: null,
});
expect(registry.getSource('TestSource')).toBe(null);
});
});
describe('decorators', () => {
it('works', () => {
expect(registry.getDecorator('UndefinedDecorator')).not.toBeDefined();
registry.registerDecorators({
TestDecorator: null,
});
expect(registry.getDecorator('TestDecorator')).toBe(null);
});
});
describe('blocks', () => {
it('works', () => {
expect(registry.getBlock('UndefinedBlock')).not.toBeDefined();
registry.registerBlocks({
TestBlock: null,
});
expect(registry.getBlock('TestBlock')).toBe(null);
});
});
});

View file

@ -16,7 +16,7 @@ MUTABILITY[DOCUMENT] = 'MUTABLE';
MUTABILITY[ENTITY_TYPE.IMAGE] = 'IMMUTABLE';
MUTABILITY[EMBED] = 'IMMUTABLE';
const getChooserConfig = (entityType, entity) => {
export const getChooserConfig = (entityType, entity) => {
const chooserURL = {};
chooserURL[ENTITY_TYPE.IMAGE] = `${global.chooserUrls.imageChooser}?select_format=true`;
chooserURL[EMBED] = global.chooserUrls.embedsChooser;
@ -59,7 +59,7 @@ const getChooserConfig = (entityType, entity) => {
};
};
const filterEntityData = (entityType, data) => {
export const filterEntityData = (entityType, data) => {
switch (entityType.type) {
case ENTITY_TYPE.IMAGE:
return {

View file

@ -0,0 +1,343 @@
import React from 'react';
import { shallow } from 'enzyme';
import ModalWorkflowSource, { getChooserConfig, filterEntityData } from './ModalWorkflowSource';
import { EditorState, convertFromRaw, AtomicBlockUtils, RichUtils, Modifier } from 'draft-js';
global.ModalWorkflow = () => {};
describe('ModalWorkflowSource', () => {
beforeEach(() => {
jest.spyOn(global, 'ModalWorkflow');
});
afterEach(() => {
jest.restoreAllMocks();
});
it('works', () => {
expect(shallow((
<ModalWorkflowSource
editorState={{}}
entityType={{}}
entity={{}}
onComplete={() => {}}
onClose={() => {}}
/>
))).toMatchSnapshot();
});
describe('#getChooserConfig', () => {
it('IMAGE', () => {
expect(getChooserConfig({ type: 'IMAGE' })).toEqual({
url: '/admin/images/chooser/?select_format=true',
urlParams: {},
});
});
it('EMBED', () => {
expect(getChooserConfig({ type: 'EMBED' })).toEqual({
url: '/admin/embeds/chooser/',
urlParams: {},
});
});
it('DOCUMENT', () => {
expect(getChooserConfig({ type: 'DOCUMENT' })).toEqual({
url: '/admin/documents/chooser/',
urlParams: {},
});
});
describe('LINK', () => {
it('no entity', () => {
expect(getChooserConfig({ type: 'LINK' })).toMatchSnapshot();
});
it('page', () => {
expect(getChooserConfig({ type: 'LINK' }, {
getData: () => ({ id: 1, parentId: 0 })
})).toMatchSnapshot();
});
it('mail', () => {
expect(getChooserConfig({ type: 'LINK' }, {
getData: () => ({ url: 'mailto:test@example.com' })
})).toMatchSnapshot();
});
it('external', () => {
expect(getChooserConfig({ type: 'LINK' }, {
getData: () => ({ url: 'https://www.example.com/' })
})).toMatchSnapshot();
});
});
});
describe('#filterEntityData', () => {
it('IMAGE', () => {
expect(filterEntityData({ type: 'IMAGE' }, {
id: 53,
title: 'Test',
alt: 'Test',
class: 'richtext-image right',
edit_link: '/admin/images/53/',
format: 'right',
preview: {
url: '/media/images/test.width-500.jpg',
}
})).toMatchSnapshot();
});
it('EMBED', () => {
expect(filterEntityData({ type: 'EMBED' }, {
authorName: 'Test',
embedType: 'video',
providerName: 'YouTube',
thumbnail: 'https://i.ytimg.com/vi/pSlVtxLOYiM/hqdefault.jpg',
title: 'Test',
url: 'https://www.youtube.com/watch?v=pSlVtxLOYiM',
})).toMatchSnapshot();
});
it('DOCUMENT', () => {
expect(filterEntityData({ type: 'DOCUMENT' }, {
edit_link: '/admin/documents/edit/1/',
filename: 'test.pdf',
id: 1,
title: 'Test',
url: '/documents/1/test.pdf',
})).toMatchSnapshot();
});
it('OTHER', () => {
expect(filterEntityData({ type: 'OTHER' }, {})).toEqual({});
});
describe('LINK', () => {
it('page', () => {
expect(filterEntityData({ type: 'LINK' }, {
id: 60,
parentId: 1,
url: '/',
editUrl: '/admin/pages/60/edit/',
title: 'Welcome to the Wagtail Bakery!',
})).toMatchSnapshot();
});
it('mail', () => {
expect(filterEntityData({ type: 'LINK' }, {
prefer_this_title_as_link_text: false,
title: 'test@example.com',
url: 'mailto:test@example.com',
})).toMatchSnapshot();
});
it('external', () => {
expect(filterEntityData({ type: 'LINK' }, {
prefer_this_title_as_link_text: false,
title: 'https://www.example.com/',
url: 'https://www.example.com/',
})).toMatchSnapshot();
});
});
});
it('#componentDidMount', () => {
const wrapper = shallow((
<ModalWorkflowSource
editorState={{}}
entityType={{}}
entity={{}}
onComplete={() => {}}
onClose={() => {}}
/>
));
wrapper.instance().onChosen = jest.fn();
wrapper.instance().componentDidMount();
global.ModalWorkflow.mock.calls[0][0].responses.embedChosen('test', {});
expect(global.ModalWorkflow).toHaveBeenCalled();
expect(global.jQuery().on).toHaveBeenCalled();
expect(wrapper.instance().onChosen).toHaveBeenCalled();
});
it('#onError', () => {
window.alert = jest.fn();
const onClose = jest.fn();
const wrapper = shallow((
<ModalWorkflowSource
editorState={{}}
entityType={{}}
entity={{}}
onComplete={() => {}}
onClose={onClose}
/>
));
wrapper.instance().componentDidMount();
global.ModalWorkflow.mock.calls[0][0].onError();
expect(global.ModalWorkflow).toHaveBeenCalled();
expect(global.jQuery().on).toHaveBeenCalled();
expect(window.alert).toHaveBeenCalled();
expect(onClose).toHaveBeenCalled();
});
it('#componentWillUnmount', () => {
const wrapper = shallow((
<ModalWorkflowSource
editorState={{}}
entityType={{}}
entity={{}}
onComplete={() => {}}
onClose={() => {}}
/>
));
wrapper.instance().componentWillUnmount();
expect(global.jQuery().off).toHaveBeenCalled();
});
describe('#onChosen', () => {
it('works', () => {
jest.spyOn(RichUtils, 'toggleLink');
const onComplete = jest.fn();
let editorState = EditorState.createWithContent(convertFromRaw({
entityMap: {},
blocks: [
{
key: 'a',
text: 'test',
}
]
}));
let selection = editorState.getSelection();
selection = selection.merge({
focusOffset: 4,
});
editorState = EditorState.acceptSelection(editorState, selection);
const wrapper = shallow((
<ModalWorkflowSource
editorState={editorState}
entityType={{}}
entity={{}}
onComplete={onComplete}
onClose={() => {}}
/>
));
wrapper.instance().onChosen({});
expect(onComplete).toHaveBeenCalled();
expect(RichUtils.toggleLink).toHaveBeenCalled();
RichUtils.toggleLink.mockRestore();
});
it('block', () => {
jest.spyOn(AtomicBlockUtils, 'insertAtomicBlock');
const onComplete = jest.fn();
let editorState = EditorState.createWithContent(convertFromRaw({
entityMap: {},
blocks: [
{
key: 'a',
text: 'test',
}
]
}));
let selection = editorState.getSelection();
selection = selection.merge({
focusOffset: 4,
});
editorState = EditorState.acceptSelection(editorState, selection);
const wrapper = shallow((
<ModalWorkflowSource
editorState={editorState}
entityType={{
block: () => {},
}}
entity={{}}
onComplete={onComplete}
onClose={() => {}}
/>
));
wrapper.instance().onChosen({});
expect(onComplete).toHaveBeenCalled();
expect(AtomicBlockUtils.insertAtomicBlock).toHaveBeenCalled();
AtomicBlockUtils.insertAtomicBlock.mockRestore();
});
it('prefer_this_title_as_link_text', () => {
jest.spyOn(Modifier, 'replaceText');
const onComplete = jest.fn();
let editorState = EditorState.createWithContent(convertFromRaw({
entityMap: {},
blocks: [
{
key: 'a',
text: 'test',
}
]
}));
let selection = editorState.getSelection();
selection = selection.merge({
focusOffset: 4,
});
editorState = EditorState.acceptSelection(editorState, selection);
const wrapper = shallow((
<ModalWorkflowSource
editorState={editorState}
entityType={{}}
onComplete={onComplete}
onClose={() => {}}
/>
));
wrapper.instance().onChosen({
url: 'example.com',
prefer_this_title_as_link_text: true,
});
expect(onComplete).toHaveBeenCalled();
expect(Modifier.replaceText).toHaveBeenCalled();
Modifier.replaceText.mockRestore();
});
});
it('#onClose', () => {
const onClose = jest.fn();
const wrapper = shallow((
<ModalWorkflowSource
editorState={{}}
entityType={{}}
entity={{}}
onComplete={() => {}}
onClose={onClose}
/>
));
wrapper.instance().onClose({
preventDefault: () => {},
});
expect(onClose).toHaveBeenCalled();
});
});

View file

@ -0,0 +1,105 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ModalWorkflowSource #filterEntityData DOCUMENT 1`] = `
Object {
"filename": "test.pdf",
"id": 1,
"url": "/documents/1/test.pdf",
}
`;
exports[`ModalWorkflowSource #filterEntityData EMBED 1`] = `
Object {
"authorName": "Test",
"embedType": "video",
"providerName": "YouTube",
"thumbnail": "https://i.ytimg.com/vi/pSlVtxLOYiM/hqdefault.jpg",
"title": "Test",
"url": "https://www.youtube.com/watch?v=pSlVtxLOYiM",
}
`;
exports[`ModalWorkflowSource #filterEntityData IMAGE 1`] = `
Object {
"alt": "Test",
"format": "right",
"id": 53,
"src": "/media/images/test.width-500.jpg",
}
`;
exports[`ModalWorkflowSource #filterEntityData LINK external 1`] = `
Object {
"url": "https://www.example.com/",
}
`;
exports[`ModalWorkflowSource #filterEntityData LINK mail 1`] = `
Object {
"url": "mailto:test@example.com",
}
`;
exports[`ModalWorkflowSource #filterEntityData LINK page 1`] = `
Object {
"id": 60,
"parentId": 1,
"url": "/",
}
`;
exports[`ModalWorkflowSource #getChooserConfig LINK external 1`] = `
Object {
"url": "/admin/choose-external-link/",
"urlParams": Object {
"allow_email_link": true,
"allow_external_link": true,
"can_choose_root": "false",
"link_text": "",
"link_url": "https://www.example.com/",
"page_type": "wagtailcore.page",
},
}
`;
exports[`ModalWorkflowSource #getChooserConfig LINK mail 1`] = `
Object {
"url": "/admin/choose-email-link/",
"urlParams": Object {
"allow_email_link": true,
"allow_external_link": true,
"can_choose_root": "false",
"link_text": "",
"link_url": "test@example.com",
"page_type": "wagtailcore.page",
},
}
`;
exports[`ModalWorkflowSource #getChooserConfig LINK no entity 1`] = `
Object {
"url": "/admin/choose-page/",
"urlParams": Object {
"allow_email_link": true,
"allow_external_link": true,
"can_choose_root": "false",
"link_text": "",
"page_type": "wagtailcore.page",
},
}
`;
exports[`ModalWorkflowSource #getChooserConfig LINK page 1`] = `
Object {
"url": "/admin/choose-page/0/",
"urlParams": Object {
"allow_email_link": true,
"allow_external_link": true,
"can_choose_root": "false",
"link_text": "",
"page_type": "wagtailcore.page",
},
}
`;
exports[`ModalWorkflowSource works 1`] = `""`;

View file

@ -4,7 +4,7 @@ import Portal from './Portal';
const func = expect.any(Function);
describe.skip('Portal', () => {
describe('Portal', () => {
beforeEach(() => {
document.body.innerHTML = '';
});
@ -18,8 +18,8 @@ describe.skip('Portal', () => {
});
it('component lifecycle', () => {
jest.spyOn(document, 'removeEventListener');
jest.spyOn(window, 'removeEventListener');
document.removeEventListener = jest.fn();
window.removeEventListener = jest.fn();
const wrapper = shallow(<Portal onClose={() => {}}>Test!</Portal>);

View file

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Portal #children 1`] = `null`;
exports[`Portal #children 1`] = `""`;
exports[`Portal component lifecycle 1`] = `"<div><div data-reactroot=\\"\\">Test!</div></div>"`;
exports[`Portal component lifecycle 1`] = `"<div><div>Test!</div></div>"`;
exports[`Portal empty 1`] = `null`;
exports[`Portal empty 1`] = `""`;

View file

@ -39,3 +39,20 @@ global.wagtailConfig = {
};
global.wagtailVersion = '1.6a1';
global.chooserUrls = {
documentChooser: '/admin/documents/chooser/',
emailLinkChooser: '/admin/choose-email-link/',
embedsChooser: '/admin/embeds/chooser/',
externalLinkChooser: '/admin/choose-external-link/',
imageChooser: '/admin/images/chooser/',
pageChooser: '/admin/choose-page/',
snippetChooser: '/admin/snippets/choose/',
};
const jQueryObj = {
on: jest.fn(),
off: jest.fn(),
};
global.jQuery = () => jQueryObj;

View file

@ -1,4 +1,30 @@
import draftail from '../../../../../client/src/components/Draftail/index';
import {
initEditor,
registry,
ModalWorkflowSource,
Link,
Document,
ImageBlock,
EmbedBlock,
} from '../../../../../client/src/components/Draftail/index';
// Expose as a global variable, for integration with other scripts.
window.draftail = draftail;
/**
* Expose as a global, and register the built-in entities.
*/
window.draftail = registry;
window.draftail.initEditor = initEditor;
window.draftail.registerSources({
ModalWorkflowSource,
});
window.draftail.registerDecorators({
Link,
Document,
});
window.draftail.registerBlocks({
ImageBlock,
EmbedBlock,
});

View file

@ -4,4 +4,12 @@ describe('draftail.entry', () => {
it('exposes global', () => {
expect(window.draftail).toBeDefined();
});
it('has defaults registered', () => {
expect(window.draftail.getSource('ModalWorkflowSource')).toBeDefined();
expect(window.draftail.getDecorator('Link')).toBeDefined();
expect(window.draftail.getDecorator('Document')).toBeDefined();
expect(window.draftail.getBlock('ImageBlock')).toBeDefined();
expect(window.draftail.getBlock('EmbedBlock')).toBeDefined();
});
});