Skip to content

Commit de7ae7d

Browse files
committed
Test <CodeMirrorEditor> component's integration with CodeMirror
1 parent f3dbdaf commit de7ae7d

File tree

6 files changed

+147
-39
lines changed

6 files changed

+147
-39
lines changed

.eslintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
},
4242
{
4343
"env": {
44-
"browser": false,
4544
"es6": true,
4645
"node": true,
4746
"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
@@ -345,7 +345,7 @@
345345
"null-loader": "^0.1.1",
346346
"postcss-preset-env": "^5.3.0",
347347
"raw-loader": "^0.5.1",
348-
"react-test-renderer": "^16.8.4",
348+
"react-test-renderer": "^16.8.5",
349349
"redux-saga-test-plan": "^4.0.0-beta.2",
350350
"rosie": "^2.0.1",
351351
"script-ext-html-webpack-plugin": "^2.0.1",
Lines changed: 116 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,131 @@
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+
};
919

10-
function renderComponent(props = {}) {
11-
const renderer = new ShallowRenderer();
12-
13-
return renderer.render(
20+
function buildComponent(props = {}) {
21+
return (
1422
<CodeMirrorEditor
15-
errors={[]}
16-
language="html"
17-
projectKey={projectKey}
18-
source={source}
19-
onAutoFormat={noop}
20-
onInput={noop}
21-
onRequestedLineFocused={noop}
23+
{...DEFAULT_PROPS}
2224
{...props}
23-
/>,
25+
/>
2426
);
2527
}
2628

27-
test('default', async() => {
28-
const {type, props: {className}} = renderComponent();
29+
function shallowRenderComponent(props = {}) {
30+
return new ShallowRenderer().render(buildComponent(props));
31+
}
32+
33+
function renderComponent(props = {}) {
34+
const container = {__stub: 'editors__codemirror-container'};
35+
let component;
36+
act(() => {
37+
component = TestRenderer.create(buildComponent(props), {
38+
createNodeMock(element) {
39+
if (
40+
!/\beditors__codemirror-container\b/u.test(element.props.className)
41+
) {
42+
throw new Error(`Got unexpected ref: ${JSON.stringify(element)}`);
43+
}
44+
return container;
45+
},
46+
});
47+
});
48+
return {component, container};
49+
}
2950

30-
expect(type).toBe('div');
31-
expect(className).toBe('editors__codemirror-container');
51+
describe('large text', () => {
52+
test('not on by default', () => {
53+
const {props: {className}} = shallowRenderComponent();
54+
55+
expect(className.split(' ')).not.
56+
toContain('editors__codemirror-container_large-text');
57+
});
58+
59+
test('on if prop is true', () => {
60+
const {props: {className}} =
61+
shallowRenderComponent({textSizeIsLarge: true});
62+
63+
expect(className.split(' ')).
64+
toContain('editors__codemirror-container_large-text');
65+
});
3266
});
3367

34-
test('large text', () => {
35-
const {props: {className}} = renderComponent({textSizeIsLarge: true});
36-
expect(className.split(' ')).
37-
toContain('editors__codemirror-container_large-text');
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).
87+
toHaveBeenLastCalledWith(last(CodeMirror.Doc.mock.instances));
88+
89+
expect(editor.setValue).
90+
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 =
108+
DEFAULT_PROPS.source.replace('<html>', '<html><body></body>');
109+
updateComponent({source: newSource});
110+
expect(editor.setValue).toHaveBeenLastCalledWith(newSource);
111+
112+
editor.setValue.mockClear();
113+
updateComponent({source: newSource});
114+
expect(editor.setValue).not.toHaveBeenCalled();
115+
});
116+
117+
test('change listener', () => {
118+
const [, handleChanges] = findLast(editor.on.mock.calls, {0: 'changes'});
119+
expect(DEFAULT_PROPS.onInput).not.toHaveBeenCalled();
120+
121+
const newSource =
122+
DEFAULT_PROPS.source.replace('<html>', '<html>d');
123+
editor.getValue.mockReturnValueOnce(newSource);
124+
handleChanges(null, [{origin: '+input'}]);
125+
expect(DEFAULT_PROPS.onInput).toHaveBeenLastCalledWith(newSource);
126+
127+
DEFAULT_PROPS.onInput.mockClear();
128+
handleChanges(null, [{origin: 'setValue'}]);
129+
expect(DEFAULT_PROPS.onInput).not.toHaveBeenCalled();
130+
});
38131
});

yarn.lock

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

12095-
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4:
12095+
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:
1209612096
version "16.8.6"
1209712097
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
1209812098
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
@@ -12132,15 +12132,15 @@ react-redux@^6.0.1:
1213212132
prop-types "^15.7.2"
1213312133
react-is "^16.8.2"
1213412134

12135-
react-test-renderer@^16.8.4:
12136-
version "16.8.4"
12137-
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.4.tgz#abee4c2c3bf967a8892a7b37f77370c5570d5329"
12138-
integrity sha512-jQ9Tf/ilIGSr55Cz23AZ/7H3ABEdo9oy2zF9nDHZyhLHDSLKuoILxw2ifpBfuuwQvj4LCoqdru9iZf7gwFH28A==
12135+
react-test-renderer@^16.8.5:
12136+
version "16.8.6"
12137+
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
12138+
integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
1213912139
dependencies:
1214012140
object-assign "^4.1.1"
1214112141
prop-types "^15.6.2"
12142-
react-is "^16.8.4"
12143-
scheduler "^0.13.4"
12142+
react-is "^16.8.6"
12143+
scheduler "^0.13.6"
1214412144

1214512145
react@^0.14.0:
1214612146
version "0.14.9"
@@ -13152,10 +13152,10 @@ scheduler@^0.13.2:
1315213152
loose-envify "^1.1.0"
1315313153
object-assign "^4.1.1"
1315413154

13155-
scheduler@^0.13.4:
13156-
version "0.13.4"
13157-
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.4.tgz#8fef05e7a3580c76c0364d2df5e550e4c9140298"
13158-
integrity sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA==
13155+
scheduler@^0.13.6:
13156+
version "0.13.6"
13157+
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
13158+
integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==
1315913159
dependencies:
1316013160
loose-envify "^1.1.0"
1316113161
object-assign "^4.1.1"

0 commit comments

Comments
 (0)