Skip to content

Commit add2e65

Browse files
committed
Plugin tests
1 parent a9fad60 commit add2e65

File tree

3 files changed

+285
-14
lines changed

3 files changed

+285
-14
lines changed

src/__test__/plugin-test.js

Lines changed: 283 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,292 @@
11
import { expect } from 'chai';
22
import sinon from 'sinon';
3+
import Draft, { EditorState, SelectionState, ContentBlock } from 'draft-js';
4+
import { CheckableListItem, CheckableListItemUtils } from 'draft-js-checkable-list-item';
5+
6+
import { Map, List } from 'immutable';
37
import createMarkdownShortcutsPlugin from '../';
48

59
describe('draft-js-markdown-shortcuts-plugin', () => {
6-
let plugin;
7-
beforeEach(() => {
8-
plugin = createMarkdownShortcutsPlugin({});
10+
afterEach(() => {
11+
/* eslint-disable no-underscore-dangle */
12+
createMarkdownShortcutsPlugin.__ResetDependency__('adjustBlockDepth');
13+
createMarkdownShortcutsPlugin.__ResetDependency__('handleBlockType');
14+
createMarkdownShortcutsPlugin.__ResetDependency__('handleInlineStyle');
15+
createMarkdownShortcutsPlugin.__ResetDependency__('handleNewCodeBlock');
16+
createMarkdownShortcutsPlugin.__ResetDependency__('insertEmptyBlock');
17+
createMarkdownShortcutsPlugin.__ResetDependency__('handleLink');
18+
createMarkdownShortcutsPlugin.__ResetDependency__('handleImage');
19+
createMarkdownShortcutsPlugin.__ResetDependency__('leaveList');
20+
/* eslint-enable no-underscore-dangle */
921
});
10-
it('is loaded', () => {
11-
expect(createMarkdownShortcutsPlugin).to.be.a('function');
12-
});
13-
it('initialize', () => {
14-
const getEditorState = sinon.spy();
15-
const setEditorState = sinon.spy();
16-
plugin.initialize({ getEditorState, setEditorState });
17-
expect(plugin.store).to.deep.equal({
18-
getEditorState,
19-
setEditorState
22+
23+
let plugin;
24+
let store;
25+
let currentEditorState;
26+
let newEditorState;
27+
let currentRawContentState;
28+
let newRawContentState;
29+
let currentSelectionState;
30+
let subject;
31+
let event;
32+
33+
let modifierSpy;
34+
35+
[
36+
[],
37+
[{}],
38+
].forEach((args) => {
39+
beforeEach(() => {
40+
modifierSpy = sinon.spy(() => newEditorState);
41+
42+
event = new window.KeyboardEvent('keydown');
43+
sinon.spy(event, 'preventDefault');
44+
currentSelectionState = new SelectionState({
45+
anchorKey: 'item1',
46+
anchorOffset: 0,
47+
focusKey: 'item1',
48+
focusOffset: 0,
49+
isBackward: false,
50+
hasFocus: true
51+
});
52+
53+
newRawContentState = {
54+
entityMap: {},
55+
blocks: [{
56+
key: 'item1',
57+
text: 'altered!!',
58+
type: 'unstyled',
59+
depth: 0,
60+
inlineStyleRanges: [],
61+
entityRanges: [],
62+
data: {}
63+
}]
64+
};
65+
newEditorState = EditorState.createWithContent(Draft.convertFromRaw(newRawContentState));
66+
67+
store = {
68+
setEditorState: sinon.spy(),
69+
getEditorState: sinon.spy(() => {
70+
const contentState = Draft.convertFromRaw(currentRawContentState);
71+
currentEditorState = EditorState.forceSelection(
72+
EditorState.createWithContent(contentState),
73+
currentSelectionState);
74+
return currentEditorState;
75+
})
76+
};
77+
subject = null;
78+
});
79+
80+
describe(args.length === 0 ? 'without config' : 'with config', () => {
81+
beforeEach(() => {
82+
plugin = createMarkdownShortcutsPlugin(...args);
83+
});
84+
85+
it('is loaded', () => {
86+
expect(createMarkdownShortcutsPlugin).to.be.a('function');
87+
});
88+
it('initialize', () => {
89+
plugin.initialize(store);
90+
expect(plugin.store).to.deep.equal(store);
91+
});
92+
describe('handleReturn', () => {
93+
beforeEach(() => {
94+
subject = () => plugin.handleReturn(event, store);
95+
});
96+
it('does not handle', () => {
97+
currentRawContentState = {
98+
entityMap: {},
99+
blocks: [{
100+
key: 'item1',
101+
text: '',
102+
type: 'unstyled',
103+
depth: 0,
104+
inlineStyleRanges: [],
105+
entityRanges: [],
106+
data: {}
107+
}]
108+
};
109+
expect(subject()).to.equal('not-handled');
110+
expect(modifierSpy).not.to.have.been.calledOnce();
111+
expect(store.setEditorState).not.to.have.been.called();
112+
});
113+
it('leaves from list', () => {
114+
createMarkdownShortcutsPlugin.__Rewire__('leaveList', modifierSpy); // eslint-disable-line no-underscore-dangle
115+
currentRawContentState = {
116+
entityMap: {},
117+
blocks: [{
118+
key: 'item1',
119+
text: '',
120+
type: 'ordered-list-item',
121+
depth: 0,
122+
inlineStyleRanges: [],
123+
entityRanges: [],
124+
data: {}
125+
}]
126+
};
127+
expect(subject()).to.equal('handled');
128+
expect(modifierSpy).to.have.been.calledOnce();
129+
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
130+
});
131+
const testInsertNewBlock = (type) => () => {
132+
createMarkdownShortcutsPlugin.__Rewire__('insertEmptyBlock', modifierSpy); // eslint-disable-line no-underscore-dangle
133+
currentRawContentState = {
134+
entityMap: {},
135+
blocks: [{
136+
key: 'item1',
137+
text: 'Hello',
138+
type,
139+
depth: 0,
140+
inlineStyleRanges: [],
141+
entityRanges: [],
142+
data: {}
143+
}]
144+
};
145+
expect(subject()).to.equal('handled');
146+
expect(modifierSpy).to.have.been.calledOnce();
147+
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
148+
};
149+
['one', 'two', 'three', 'four', 'five', 'six'].forEach((level) => {
150+
describe(`on header-${level}`, () => {
151+
it('inserts new empty block', testInsertNewBlock(`header-${level}`));
152+
});
153+
});
154+
['ctrlKey', 'shiftKey', 'metaKey', 'altKey'].forEach((key) => {
155+
describe(`${key} is pressed`, () => {
156+
beforeEach(() => {
157+
const props = {};
158+
props[key] = true;
159+
event = new window.KeyboardEvent('keydown', props);
160+
});
161+
it('inserts new empty block', testInsertNewBlock('blockquote'));
162+
});
163+
});
164+
it('handles new code block', () => {
165+
createMarkdownShortcutsPlugin.__Rewire__('handleNewCodeBlock', modifierSpy); // eslint-disable-line no-underscore-dangle
166+
currentRawContentState = {
167+
entityMap: {},
168+
blocks: [{
169+
key: 'item1',
170+
text: '',
171+
type: '```',
172+
depth: 0,
173+
inlineStyleRanges: [],
174+
entityRanges: [],
175+
data: {}
176+
}]
177+
};
178+
expect(subject()).to.equal('handled');
179+
expect(modifierSpy).to.have.been.calledOnce();
180+
expect(store.setEditorState).to.have.been.calledWith(newEditorState);
181+
});
182+
});
183+
describe('blockStyleFn', () => {
184+
let type;
185+
beforeEach(() => {
186+
type = null;
187+
const getType = () => type;
188+
subject = () => plugin.blockStyleFn({ getType });
189+
});
190+
it('returns checkable-list-item', () => {
191+
type = 'checkable-list-item';
192+
expect(subject()).to.equal('checkable-list-item');
193+
});
194+
it('returns null', () => {
195+
type = 'ordered-list-item';
196+
expect(subject()).to.be.null();
197+
});
198+
});
199+
describe('blockRendererFn', () => {
200+
let type;
201+
let data;
202+
let block;
203+
let spyOnChangeChecked;
204+
beforeEach(() => {
205+
type = null;
206+
data = {};
207+
spyOnChangeChecked = sinon.spy(CheckableListItemUtils, 'toggleChecked');
208+
subject = () => {
209+
block = new ContentBlock({
210+
type,
211+
data: Map(data),
212+
key: 'item1',
213+
characterList: List()
214+
});
215+
return plugin.blockRendererFn(block, store);
216+
};
217+
});
218+
afterEach(() => {
219+
CheckableListItemUtils.toggleChecked.restore();
220+
});
221+
it('returns renderer', () => {
222+
type = 'checkable-list-item';
223+
data = { checked: true };
224+
const renderer = subject();
225+
expect(renderer).to.be.an('object');
226+
expect(renderer.component).to.equal(CheckableListItem);
227+
expect(renderer.props.onChangeChecked).to.be.a('function');
228+
expect(renderer.props.checked).to.be.true();
229+
renderer.props.onChangeChecked();
230+
expect(spyOnChangeChecked).to.have.been.calledWith(currentEditorState, block);
231+
});
232+
it('returns null', () => {
233+
type = 'ordered-list-item';
234+
expect(subject()).to.be.null();
235+
});
236+
});
237+
describe('onTab', () => {
238+
beforeEach(() => {
239+
subject = () => {
240+
createMarkdownShortcutsPlugin.__Rewire__('adjustBlockDepth', modifierSpy); // eslint-disable-line no-underscore-dangle
241+
return plugin.onTab(event, store);
242+
};
243+
});
244+
describe('no changes', () => {
245+
it('returns handled', () => {
246+
expect(subject()).to.equal('handled');
247+
});
248+
it('returns not-handled', () => {
249+
modifierSpy = sinon.spy(() => currentEditorState);
250+
expect(subject()).to.equal('not-handled');
251+
});
252+
});
253+
});
254+
describe('handleBeforeInput', () => {
255+
let character;
256+
beforeEach(() => {
257+
character = ' ';
258+
subject = () => plugin.handleBeforeInput(character, store);
259+
});
260+
[
261+
'handleBlockType',
262+
'handleImage',
263+
'handleLink',
264+
'handleInlineStyle'
265+
].forEach((modifier) => {
266+
describe(modifier, () => {
267+
beforeEach(() => {
268+
createMarkdownShortcutsPlugin.__Rewire__(modifier, modifierSpy); // eslint-disable-line no-underscore-dangle
269+
});
270+
it('returns handled', () => {
271+
expect(subject()).to.equal('handled');
272+
expect(modifierSpy).to.have.been.calledWith(currentEditorState, ' ');
273+
});
274+
});
275+
});
276+
describe('character is not a space', () => {
277+
beforeEach(() => {
278+
character = 'x';
279+
});
280+
it('returns not-handled', () => {
281+
expect(subject()).to.equal('not-handled');
282+
});
283+
});
284+
describe('no matching modifiers', () => {
285+
it('returns not-handled', () => {
286+
expect(subject()).to.equal('not-handled');
287+
});
288+
});
289+
});
20290
});
21291
});
22292
});

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const createMarkdownShortcutsPlugin = (config = {}) => {
7171
},
7272

7373
blockRendererFn(block, { setEditorState, getEditorState }) {
74+
console.info(block);
7475
switch (block.getType()) {
7576
case CHECKABLE_LIST_ITEM: {
7677
return {

src/modifiers/__test__/handleImage-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('handleImage', () => {
1010
let fakeInsertImage;
1111

1212
after(() => {
13-
handleImage.__ResetDependency__('../insertImage'); // eslint-disable-line no-underscore-dangle
13+
handleImage.__ResetDependency__('insertImage'); // eslint-disable-line no-underscore-dangle
1414
});
1515

1616
const createEditorState = (text) => {

0 commit comments

Comments
 (0)