Skip to content

Commit 2542750

Browse files
committed
Test <CodeMirrorEditor> component's integration with CodeMirror
1 parent 793ded8 commit 2542750

File tree

6 files changed

+150
-47
lines changed

6 files changed

+150
-47
lines changed

.eslintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
},
6666
{
6767
"env": {
68-
"browser": false,
6968
"es6": true,
7069
"node": true,
7170
"jest": true

__mocks__/codemirror.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import extend from 'lodash-es/extend';
2+
import tap from 'lodash-es/tap';
3+
4+
export const Doc = jest.fn(() => ({}));
5+
6+
export default tap(
7+
jest.fn(() => ({
8+
getDoc: jest.fn(),
9+
on: jest.fn(),
10+
off: jest.fn(),
11+
performLint: jest.fn(),
12+
setOption: jest.fn(),
13+
setSize: jest.fn(),
14+
swapDoc: jest.fn(),
15+
getValue: jest.fn(() => ''),
16+
setValue: jest.fn(),
17+
})),
18+
CodeMirror => extend(CodeMirror, {Doc}),
19+
);

jest.config.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
/* eslint-env node */
22
/* eslint-disable import/no-commonjs */
33

4-
// For a detailed explanation regarding each configuration property, visit:
5-
// https://jestjs.io/docs/en/configuration.html
6-
74
module.exports = {
85
clearMocks: true,
96
moduleNameMapper: {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@
358358
"postcss-preset-env": "^5.3.0",
359359
"prettier": "^1.18.2",
360360
"raw-loader": "^0.5.1",
361-
"react-test-renderer": "^16.8.4",
361+
"react-test-renderer": "^16.8.5",
362362
"redux-saga-test-plan": "^4.0.0-beta.2",
363363
"rosie": "^2.0.1",
364364
"script-ext-html-webpack-plugin": "^2.0.1",
Lines changed: 119 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,132 @@
1-
import noop from 'lodash-es/noop';
1+
import CodeMirror from 'codemirror';
2+
import findLast from 'lodash-es/findLast';
3+
import last from 'lodash-es/last';
24
import React from 'react';
35
import ShallowRenderer from 'react-test-renderer/shallow';
6+
import TestRenderer, {act} from 'react-test-renderer';
47

58
import CodeMirrorEditor from '../CodeMirrorEditor';
69

7-
const projectKey = '0';
8-
const source = '<!doctype html>\n<html>\n</html>';
10+
const DEFAULT_PROPS = {
11+
errors: [],
12+
language: 'html',
13+
projectKey: '0',
14+
source: '<!doctype html>\n<html>\n</html>',
15+
onAutoFormat: jest.fn(),
16+
onInput: jest.fn(),
17+
onRequestedLineFocused: jest.fn(),
18+
};
19+
20+
function buildComponent(props = {}) {
21+
return <CodeMirrorEditor {...DEFAULT_PROPS} {...props} />;
22+
}
23+
24+
function shallowRenderComponent(props = {}) {
25+
return new ShallowRenderer().render(buildComponent(props));
26+
}
927

1028
function renderComponent(props = {}) {
11-
const renderer = new ShallowRenderer();
12-
13-
return renderer.render(
14-
<CodeMirrorEditor
15-
errors={[]}
16-
language="html"
17-
projectKey={projectKey}
18-
source={source}
19-
onAutoFormat={noop}
20-
onInput={noop}
21-
onRequestedLineFocused={noop}
22-
{...props}
23-
/>,
24-
);
29+
const container = {__stub: 'editors__codemirror-container'};
30+
let component;
31+
act(() => {
32+
component = TestRenderer.create(buildComponent(props), {
33+
createNodeMock(element) {
34+
if (
35+
!/\beditors__codemirror-container\b/u.test(element.props.className)
36+
) {
37+
throw new Error(`Got unexpected ref: ${JSON.stringify(element)}`);
38+
}
39+
return container;
40+
},
41+
});
42+
});
43+
return {component, container};
2544
}
2645

27-
test('default', async () => {
28-
const {
29-
type,
30-
props: {className},
31-
} = renderComponent();
46+
describe('large text', () => {
47+
test('not on by default', () => {
48+
const {
49+
props: {className},
50+
} = shallowRenderComponent();
51+
52+
expect(className.split(' ')).not.toContain(
53+
'editors__codemirror-container_large-text',
54+
);
55+
});
3256

33-
expect(type).toBe('div');
34-
expect(className).toBe('editors__codemirror-container');
57+
test('on if prop is true', () => {
58+
const {
59+
props: {className},
60+
} = shallowRenderComponent({textSizeIsLarge: true});
61+
62+
expect(className.split(' ')).toContain(
63+
'editors__codemirror-container_large-text',
64+
);
65+
});
3566
});
3667

37-
test('large text', () => {
38-
const {
39-
props: {className},
40-
} = renderComponent({textSizeIsLarge: true});
41-
expect(className.split(' ')).toContain(
42-
'editors__codemirror-container_large-text',
43-
);
68+
describe('codemirror editor', () => {
69+
let component, container, editor;
70+
beforeEach(() => {
71+
({container, component} = renderComponent());
72+
editor = last(CodeMirror.mock.results).value;
73+
});
74+
75+
function updateComponent(props = {}) {
76+
act(() => {
77+
component.update(buildComponent(props));
78+
});
79+
}
80+
81+
test('initial editor setup', () => {
82+
expect(CodeMirror).toHaveBeenLastCalledWith(container, expect.any(Object));
83+
expect(editor.setSize).toHaveBeenLastCalledWith('100%', '100%');
84+
85+
expect(CodeMirror.Doc).toHaveBeenLastCalledWith('', 'htmlmixed');
86+
expect(editor.swapDoc).toHaveBeenLastCalledWith(
87+
last(CodeMirror.Doc.mock.instances),
88+
);
89+
90+
expect(editor.setValue).toHaveBeenLastCalledWith(DEFAULT_PROPS.source);
91+
});
92+
93+
test('swapping docs', () => {
94+
updateComponent({projectKey: '1'});
95+
const [doc0, doc1] = CodeMirror.Doc.mock.instances;
96+
expect(editor.swapDoc).toHaveBeenLastCalledWith(doc1);
97+
98+
updateComponent();
99+
expect(editor.swapDoc).toHaveBeenLastCalledWith(doc0);
100+
101+
editor.swapDoc.mockClear();
102+
component.update(buildComponent());
103+
expect(editor.swapDoc).not.toHaveBeenCalled();
104+
});
105+
106+
test('updating source', () => {
107+
const newSource = DEFAULT_PROPS.source.replace(
108+
'<html>',
109+
'<html><body></body>',
110+
);
111+
updateComponent({source: newSource});
112+
expect(editor.setValue).toHaveBeenLastCalledWith(newSource);
113+
114+
editor.setValue.mockClear();
115+
updateComponent({source: newSource});
116+
expect(editor.setValue).not.toHaveBeenCalled();
117+
});
118+
119+
test('change listener', () => {
120+
const [, handleChanges] = findLast(editor.on.mock.calls, {0: 'changes'});
121+
expect(DEFAULT_PROPS.onInput).not.toHaveBeenCalled();
122+
123+
const newSource = DEFAULT_PROPS.source.replace('<html>', '<html>d');
124+
editor.getValue.mockReturnValueOnce(newSource);
125+
handleChanges(null, [{origin: '+input'}]);
126+
expect(DEFAULT_PROPS.onInput).toHaveBeenLastCalledWith(newSource);
127+
128+
DEFAULT_PROPS.onInput.mockClear();
129+
handleChanges(null, [{origin: 'setValue'}]);
130+
expect(DEFAULT_PROPS.onInput).not.toHaveBeenCalled();
131+
});
44132
});

yarn.lock

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12132,7 +12132,7 @@ react-immutable-proptypes@^2.1.0:
1213212132
resolved "https://registry.yarnpkg.com/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz#023d6f39bb15c97c071e9e60d00d136eac5fa0b4"
1213312133
integrity sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ=
1213412134

12135-
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4:
12135+
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4, react-is@^16.8.6:
1213612136
version "16.8.6"
1213712137
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
1213812138
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
@@ -12172,15 +12172,15 @@ react-redux@^6.0.1:
1217212172
prop-types "^15.7.2"
1217312173
react-is "^16.8.2"
1217412174

12175-
react-test-renderer@^16.8.4:
12176-
version "16.8.4"
12177-
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.4.tgz#abee4c2c3bf967a8892a7b37f77370c5570d5329"
12178-
integrity sha512-jQ9Tf/ilIGSr55Cz23AZ/7H3ABEdo9oy2zF9nDHZyhLHDSLKuoILxw2ifpBfuuwQvj4LCoqdru9iZf7gwFH28A==
12175+
react-test-renderer@^16.8.5:
12176+
version "16.8.6"
12177+
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
12178+
integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
1217912179
dependencies:
1218012180
object-assign "^4.1.1"
1218112181
prop-types "^15.6.2"
12182-
react-is "^16.8.4"
12183-
scheduler "^0.13.4"
12182+
react-is "^16.8.6"
12183+
scheduler "^0.13.6"
1218412184

1218512185
react@^0.14.0:
1218612186
version "0.14.9"
@@ -13184,10 +13184,10 @@ sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1, sax@~1.2.4:
1318413184
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
1318513185
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
1318613186

13187-
scheduler@^0.13.2, scheduler@^0.13.4:
13188-
version "0.13.4"
13189-
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.4.tgz#8fef05e7a3580c76c0364d2df5e550e4c9140298"
13190-
integrity sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA==
13187+
scheduler@^0.13.2, scheduler@^0.13.6:
13188+
version "0.13.6"
13189+
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
13190+
integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==
1319113191
dependencies:
1319213192
loose-envify "^1.1.0"
1319313193
object-assign "^4.1.1"

0 commit comments

Comments
 (0)