Skip to content
This repository was archived by the owner on Jul 30, 2020. It is now read-only.

Commit c5364a8

Browse files
committed
feat: include jest serializer
1 parent c837fc5 commit c5364a8

38 files changed

+263
-283
lines changed

cleanup-after-each.js

-1
This file was deleted.

jest-preset.js

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ module.exports = Object.assign(jestPreset, {
55
...jestPreset.transformIgnorePatterns,
66
'node_modules/(?!(react-native.*|@?react-navigation.*)/)',
77
],
8+
snapshotSerializers: [require.resolve('./dist/preset/serializer.js')],
89
setupFiles: [...jestPreset.setupFiles, require.resolve('./dist/preset/setup.js')],
910
});

jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const ignores = ['/node_modules/', '/__tests__/helpers/', '__mocks__'];
44

55
module.exports = Object.assign(jestPreset, {
66
collectCoverageFrom: ['**/src/lib/**/*.js', '!**/src/preset/**/*.js'],
7+
snapshotSerializers: [require.resolve('./src/preset/serializer.js')],
78
setupFiles: [...jestPreset.setupFiles, require.resolve('./src/preset/setup.js')],
89
testPathIgnorePatterns: [...ignores],
910
transformIgnorePatterns: ['node_modules/(?!(react-native.*|@?react-navigation.*)/)'],

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"files": [
88
"dist",
99
"typings",
10-
"cleanup-after-each.js",
1110
"jest-preset.js"
1211
],
1312
"engines": {

src/__tests__/__snapshots__/fetch.js.snap

+7-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
exports[`Fetch makes an API call and displays the greeting when load-greeting is clicked 1`] = `
44
<View
5-
testID="ntl-container"
5+
collapsable={true}
6+
pointerEvents="box-none"
7+
style={
8+
Object {
9+
"flex": 1,
10+
}
11+
}
612
>
713
<View>
814
<TouchableOpacity

src/__tests__/act.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { Button } from 'react-native';
44

5-
import { cleanup, render, fireEvent } from '../';
6-
7-
afterEach(cleanup);
5+
import { render, fireEvent } from '../';
86

97
test('render calls useEffect immediately', () => {
108
const effectCb = jest.fn();

src/__tests__/bugs.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react';
22
import { Text, View } from 'react-native';
33

4-
import { cleanup, render, queryAllByProp } from '../';
5-
6-
afterEach(cleanup);
4+
import { render, queryAllByProp } from '../';
75

86
// This is to ensure custom queries can be passed to render. In most cases, you
97
// wouldn't/shouldn't need to do this, but we do allow it so we'll test to

src/__tests__/debug.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react';
22
import { Text } from 'react-native';
33

4-
import { cleanup, render } from '../';
5-
6-
afterEach(cleanup);
4+
import { render } from '../';
75

86
beforeEach(() => {
97
jest.spyOn(console, 'log').mockImplementation(() => {});
@@ -13,7 +11,7 @@ afterEach(() => {
1311
console.log.mockRestore();
1412
});
1513

16-
test('debug pretty prints the testRenderer', () => {
14+
test('debug pretty prints the baseElement', () => {
1715
const HelloWorld = () => <Text>Hello World</Text>;
1816
const { debug } = render(<HelloWorld />);
1917
debug();

src/__tests__/end-to-end.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { Text } from 'react-native';
44

5-
import { cleanup, render, wait } from '../';
6-
7-
afterEach(cleanup);
5+
import { render, wait } from '../';
86

97
const fetchAMessage = () =>
108
new Promise(resolve => {

src/__tests__/events.js

+23-15
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { Button, Image, Text, TextInput, TouchableHighlight } from 'react-native';
44

5-
import { cleanup, render, fireEvent, eventMap, NativeEvent, getEventHandlerName, wait } from '../';
6-
7-
afterEach(cleanup);
5+
import { render, fireEvent, eventMap, NativeEvent, getEventHandlerName, wait } from '../';
86

97
Object.keys(eventMap).forEach(key => {
108
const handlerName = getEventHandlerName(key);
@@ -15,14 +13,17 @@ Object.keys(eventMap).forEach(key => {
1513
config.validTargets.forEach(element => {
1614
const spy = jest.fn();
1715

18-
const { getByTestId } = render(
16+
const {
17+
container: {
18+
children: [button],
19+
},
20+
} = render(
1921
React.createElement(element, {
2022
[handlerName]: spy,
2123
}),
2224
);
2325

24-
const target = getByTestId('ntl-container').children[0];
25-
fireEvent[key](target);
26+
fireEvent[key](button);
2627

2728
expect(spy).toHaveBeenCalledTimes(1);
2829
});
@@ -31,9 +32,13 @@ Object.keys(eventMap).forEach(key => {
3132

3233
test('onChange works', () => {
3334
const handleChange = jest.fn();
34-
const { getByTestId } = render(<TextInput onChange={handleChange} />);
35-
const target = getByTestId('ntl-container').children[0];
36-
fireEvent.change(target, { target: { value: 'a' } });
35+
const {
36+
container: {
37+
children: [input],
38+
},
39+
} = render(<TextInput onChange={handleChange} />);
40+
41+
fireEvent.change(input, { target: { value: 'a' } });
3742
expect(handleChange).toHaveBeenCalledTimes(1);
3843
});
3944

@@ -75,10 +80,9 @@ test('assigns target properties', async () => {
7580

7681
test('calling `fireEvent` directly works too', () => {
7782
const handleEvent = jest.fn();
78-
const { getByTestId } = render(<Button onPress={handleEvent} title="test" />);
83+
const { container } = render(<Button onPress={handleEvent} title="test" />);
7984

80-
const target = getByTestId('ntl-container').children[0];
81-
fireEvent(target, new NativeEvent('press'));
85+
fireEvent(container.children[0], new NativeEvent('press'));
8286
expect(handleEvent).toBeCalledTimes(1);
8387
});
8488

@@ -87,9 +91,13 @@ test('calling a custom event works as well', () => {
8791
const onMyEvent = jest.fn(({ nativeEvent }) => expect(nativeEvent).toEqual({ value: 'testing' }));
8892
const MyComponent = ({ onMyEvent }) => <TextInput value="test" onChange={onMyEvent} />;
8993

90-
const { getByTestId } = render(<MyComponent onMyEvent={onMyEvent} />);
91-
const target = getByTestId('ntl-container').children[0];
92-
fireEvent(target, new NativeEvent('myEvent', event));
94+
const {
95+
container: {
96+
children: [input],
97+
},
98+
} = render(<MyComponent onMyEvent={onMyEvent} />);
99+
100+
fireEvent(input, new NativeEvent('myEvent', event));
93101

94102
expect(onMyEvent).toHaveBeenCalledWith({
95103
nativeEvent: { value: 'testing' },

src/__tests__/fetch.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { TouchableOpacity, Text, View } from 'react-native';
44

5-
import { cleanup, render, fireEvent, toJSON, wait } from '../';
6-
7-
afterEach(cleanup);
5+
import { render, fireEvent, wait } from '../';
86

97
global.fetch = require('jest-fetch-mock');
108

@@ -46,5 +44,5 @@ test('Fetch makes an API call and displays the greeting when load-greeting is cl
4644
expect(fetch).toHaveBeenCalledWith(url);
4745

4846
expect(getByText('hello there')).toHaveTextContent('hello there');
49-
expect(toJSON(container)).toMatchSnapshot();
47+
expect(container).toMatchSnapshot();
5048
});

src/__tests__/forms.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React from 'react';
22
import { Button, TextInput, View } from 'react-native';
3-
import { cleanup, render, fireEvent } from '../';
4-
5-
afterEach(cleanup);
3+
import { render, fireEvent } from '../';
64

75
function Login({ onSubmit, user }) {
86
return (

src/__tests__/misc.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react';
22
import { Picker } from 'react-native';
33

4-
import { cleanup, fireEvent, render } from '../';
5-
6-
afterEach(cleanup);
4+
import { fireEvent, render } from '../';
75

86
test('picker works', () => {
97
function Wrapper() {

src/__tests__/render.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react';
22
import { SafeAreaView, View } from 'react-native';
33

4-
import { cleanup, toJSON, render } from '../';
5-
6-
afterEach(cleanup);
4+
import { render } from '../';
75

86
test('renders View', () => {
97
const { container } = render(<View />);
@@ -25,9 +23,15 @@ test('renders options.wrapper around node', () => {
2523
});
2624

2725
expect(getByTestId('wrapper')).toBeTruthy();
28-
expect(toJSON(container)).toMatchInlineSnapshot(`
26+
expect(container).toMatchInlineSnapshot(`
2927
<View
30-
testID="ntl-container"
28+
collapsable={true}
29+
pointerEvents="box-none"
30+
style={
31+
Object {
32+
"flex": 1,
33+
}
34+
}
3135
>
3236
<SafeAreaView
3337
testID="wrapper"

src/__tests__/rerender.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { Text } from 'react-native';
44

5-
import { cleanup, render } from '../';
6-
7-
afterEach(cleanup);
5+
import { render } from '../';
86

97
test('rerender will re-render the element', () => {
108
const Greeting = props => <Text>{props.message}</Text>;

src/__tests__/stopwatch.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import React from 'react';
22
import { Button, Text, View } from 'react-native';
33

4-
import { cleanup, render, fireEvent, toJSON } from '../';
5-
6-
afterEach(cleanup);
4+
import { render, fireEvent, prettyPrint } from '../';
75

86
class StopWatch extends React.Component {
97
state = { lapse: 0, running: false };
@@ -47,7 +45,9 @@ test('unmounts a component', async () => {
4745
fireEvent.press(getByTitle('Start'));
4846

4947
unmount();
50-
51-
expect(toJSON(container)).toBeNull();
48+
// hey there reader! You don't need to have an assertion like this one
49+
// this is just me making sure that the unmount function works.
50+
// You don't need to do this in your apps. Just rely on the fact that this works.
51+
expect(prettyPrint(container)).toBe('null');
5252
await wait(() => expect(console.error).not.toHaveBeenCalled());
5353
});

src/index.js

+10-31
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,25 @@
11
import React from 'react';
2-
import { View } from 'react-native';
32
import TR from 'react-test-renderer';
43
import AppContainer from 'react-native/Libraries/ReactNative/AppContainer';
54

65
import {
7-
toJSON,
86
fireEvent as rntlFireEvent,
97
getQueriesForElement,
108
NativeEvent,
119
prettyPrint,
12-
proxyUnsafeProperties,
13-
validComponentFilter,
10+
proxyUnsafeProperties as proxy,
1411
} from './lib';
12+
import './preset/serializer';
1513
import act from './act-compat';
1614

17-
const containerId = 'ntl-container';
18-
const renderers = new Set();
19-
2015
function render(ui, { options = {}, wrapper: WrapperComponent, queries } = {}) {
2116
const wrapUiIfNeeded = innerElement =>
2217
WrapperComponent ? (
2318
<AppContainer>
24-
<View testID={containerId}>
25-
<WrapperComponent>{innerElement}</WrapperComponent>
26-
</View>
19+
<WrapperComponent>{innerElement}</WrapperComponent>
2720
</AppContainer>
2821
) : (
29-
<AppContainer>
30-
<View testID={containerId}>{innerElement}</View>
31-
</AppContainer>
22+
<AppContainer>{innerElement}</AppContainer>
3223
);
3324

3425
let testRenderer;
@@ -37,36 +28,24 @@ function render(ui, { options = {}, wrapper: WrapperComponent, queries } = {}) {
3728
testRenderer = TR.create(wrapUiIfNeeded(ui), options);
3829
});
3930

40-
renderers.add(testRenderer);
41-
42-
const baseElement = proxyUnsafeProperties(testRenderer.root);
43-
const container = baseElement
44-
.findAll(c => validComponentFilter(c))
45-
.filter(n => n.getProp('testID') === containerId)[0];
31+
const wrappers = proxy(testRenderer.root).findAll(n => n.getProp('pointerEvents') === 'box-none');
32+
const baseElement = wrappers[0]; // Includes YellowBox and your render
33+
const container = wrappers[1]; // Includes only your render
4634

4735
return {
4836
baseElement,
4937
container,
50-
debug: (el = baseElement) => console.log(prettyPrint(toJSON(el))),
38+
debug: (el = baseElement) => console.log(prettyPrint(el)),
5139
unmount: () => testRenderer.unmount(),
5240
rerender: rerenderUi => {
5341
act(() => {
5442
testRenderer.update(wrapUiIfNeeded(rerenderUi));
5543
});
5644
},
57-
...getQueriesForElement(testRenderer, queries),
45+
...getQueriesForElement(baseElement, queries),
5846
};
5947
}
6048

61-
function cleanup() {
62-
renderers.forEach(cleanupRenderer);
63-
}
64-
65-
function cleanupRenderer(renderer) {
66-
renderer.unmount();
67-
renderers.delete(renderer);
68-
}
69-
7049
function fireEvent(...args) {
7150
let returnValue;
7251
act(() => {
@@ -86,4 +65,4 @@ Object.keys(rntlFireEvent).forEach(key => {
8665
});
8766

8867
export * from './lib';
89-
export { act, cleanup, fireEvent, render, NativeEvent };
68+
export { act, fireEvent, render, NativeEvent };

0 commit comments

Comments
 (0)