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

Commit b8e3ca8

Browse files
authored
feat(cleanup): add after each cleanup helper (#19)
* feat(cleanup): add after each cleanup helper * feat(asFragment): rename asFragment to asJSON * chore: add asJSON to RenderResult typings
1 parent 9f74c27 commit b8e3ca8

27 files changed

+98
-34
lines changed

cleanup-after-each.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
afterEach(require('./dist').cleanup);

other/cheat-sheet.pdf

16 Bytes
Binary file not shown.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"files": [
88
"dist",
99
"typings",
10+
"cleanup-after-each.js",
1011
"jest-preset.js"
1112
],
1213
"engines": {

src/__tests__/act.js

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

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

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

src/__tests__/bugs.js

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

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

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

src/__tests__/debug.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React from 'react';
22
import { Text } from 'react-native';
33

4-
import { render } from '../';
4+
import { cleanup, render } from '../';
55

66
beforeEach(() => {
77
jest.spyOn(console, 'log').mockImplementation(() => {});
88
});
99

1010
afterEach(() => {
11+
cleanup();
1112
console.log.mockRestore();
1213
});
1314

src/__tests__/end-to-end.js

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

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

79
const fetchAMessage = () =>
810
new Promise(resolve => {

src/__tests__/events.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { Button, Image, Text, TextInput, TouchableHighlight } from 'react-native';
44

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

79
Object.keys(eventMap).forEach(key => {
810
describe(`${key} events`, () => {

src/__tests__/fetch.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22
import 'jest-native/extend-expect';
33
import { TouchableOpacity, Text, View } from 'react-native';
44

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

79
global.fetch = require('jest-fetch-mock');
810

src/__tests__/forms.js

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

57
function Login({ onSubmit, user }) {
68
return (

src/__tests__/misc.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22
import { Button, Picker, Text, View } from 'react-native';
33
import { toMatchDiffSnapshot } from 'snapshot-diff';
44

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

79
test('<Picker /> works', () => {
810
function Wrapper() {
@@ -32,15 +34,15 @@ test('fragments can show diffs', () => {
3234

3335
expect.extend({ toMatchDiffSnapshot });
3436

35-
const { getByText, asFragment } = render(<TestComponent />);
36-
const firstRender = asFragment();
37+
const { getByText, asJSON } = render(<TestComponent />);
38+
const firstRender = asJSON();
3739

3840
fireEvent.press(getByText(/Click to increase/));
3941

4042
// This will snapshot only the difference between the first render, and the
4143
// state of the DOM after the click event.
4244
// See https://github.com/jest-community/snapshot-diff
43-
expect(firstRender).toMatchDiffSnapshot(asFragment());
45+
expect(firstRender).toMatchDiffSnapshot(asJSON());
4446
});
4547

4648
test('finds only valid children', () => {

src/__tests__/render.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { Text, SafeAreaView, View } from 'react-native';
33

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

68
test('renders View', () => {
79
const { container } = render(<View />);
@@ -24,10 +26,10 @@ it('supports fragments', () => {
2426
}
2527
}
2628

27-
const { asFragment, unmount } = render(<Test />);
28-
expect(asFragment()).toMatchSnapshot();
29+
const { asJSON, unmount } = render(<Test />);
30+
expect(asJSON()).toMatchSnapshot();
2931
unmount();
30-
expect(asFragment()).toBeNull();
32+
expect(asJSON()).toBeNull();
3133
});
3234

3335
test('renders options.wrapper around node', () => {

src/__tests__/rerender.js

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

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

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

src/__tests__/stopwatch.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { Button, Text, View } from 'react-native';
33

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

68
class StopWatch extends React.Component {
79
state = { lapse: 0, running: false };

src/index.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import {
88
getQueriesForElement,
99
NativeTestEvent,
1010
prettyPrint,
11-
proxyElement as proxy,
11+
proxyElement,
1212
} from './lib';
1313
import act from './act-compat';
1414

15+
const renderers = new Set();
16+
1517
function render(ui, { options = {}, wrapper: WrapperComponent, queries } = {}) {
1618
const wrapUiIfNeeded = innerElement =>
1719
WrapperComponent ? (
@@ -28,7 +30,9 @@ function render(ui, { options = {}, wrapper: WrapperComponent, queries } = {}) {
2830
testRenderer = TR.create(wrapUiIfNeeded(ui), options);
2931
});
3032

31-
const wrappers = proxy(testRenderer.root).findAll(n => n.getProp('pointerEvents') === 'box-none');
33+
renderers.add(testRenderer);
34+
35+
const wrappers = proxyElement(testRenderer.root).findAll(n => n.type === 'View');
3236
const baseElement = wrappers[0]; // Includes YellowBox and your render
3337
const container = wrappers[1]; // Includes only your render
3438

@@ -42,13 +46,22 @@ function render(ui, { options = {}, wrapper: WrapperComponent, queries } = {}) {
4246
testRenderer.update(wrapUiIfNeeded(rerenderUi));
4347
});
4448
},
45-
asFragment: () => {
49+
asJSON: () => {
4650
return toJSON(container);
4751
},
4852
...getQueriesForElement(baseElement, queries),
4953
};
5054
}
5155

56+
function cleanup() {
57+
renderers.forEach(cleanupRenderer);
58+
}
59+
60+
function cleanupRenderer(renderer) {
61+
renderer.unmount();
62+
renderers.delete(renderer);
63+
}
64+
5265
function fireEvent(...args) {
5366
let returnValue;
5467
act(() => {
@@ -68,4 +81,4 @@ Object.keys(rntlFireEvent).forEach(typeArg => {
6881
});
6982

7083
export * from './lib';
71-
export { act, fireEvent, render, NativeTestEvent };
84+
export { act, cleanup, fireEvent, render, NativeTestEvent };

src/lib/__tests__/get-by-errors.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22
import { Button, Text, TextInput, View } from 'react-native';
33
import cases from 'jest-in-case';
44

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

79
cases(
810
'getBy* queries throw an error when there are multiple elements returned',

src/lib/__tests__/misc.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
2-
import { Text, View } from 'react-native';
2+
import { View } from 'react-native';
33

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

68
test('queryByProp', () => {
79
const { container } = render(

src/lib/__tests__/pretty-print.js

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

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

68
test('it prints correctly with no children', () => {
79
const { container } = render(<View />);

src/lib/__tests__/queries.find.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { Button, Image, Text, TextInput, View } from 'react-native';
33

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

68
test('find asynchronously finds elements', async () => {
79
const {

src/lib/__tests__/text-matchers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22
import cases from 'jest-in-case';
33
import { Button, Image, Text, TextInput, TouchableOpacity } from 'react-native';
44

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

79
cases(
810
'matches find case-sensitive full strings by default',

src/lib/__tests__/to-json.js

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

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

68
test('it converts to json', () => {
79
function ParentComponent({ children }) {

src/lib/__tests__/wait-for-element-to-be-removed.fake-timers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { View } from 'react-native';
33

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

68
jest.useFakeTimers();
79

src/lib/__tests__/wait-for-element-to-be-removed.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { View } from 'react-native';
33

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

68
test('resolves only when the element is removed', async () => {
79
class MutatedElement extends React.Component {

src/lib/__tests__/wait-for-element.js

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

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

68
test('waits for element to appear', async () => {
79
const { rerender, getByTestId } = render(<View />);

src/lib/__tests__/within.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
22
import { Button, View } from 'react-native';
33

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

68
test('it works when scoping to a smaller set of elements', () => {
79
const { getByTestId } = render(

src/preset/configure.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { asyncAct } from '../act-compat';
2+
import { NativeTestEvent } from '../lib/events';
23
import { configure as configureNTL } from '../lib';
34

5+
// Make this global for convenience, just like browser events
6+
global.NativeTestEvent = NativeTestEvent;
7+
48
configureNTL({
59
asyncWrapper: async cb => {
610
let result;

typings/index.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { ReactElement, ComponentType } from 'react';
22
import { ReactTestRenderer } from 'react-test-renderer';
33

4-
import { getQueriesForElement, BoundFunction } from './get-queries-for-element';
54
import * as queries from './queries';
65
import * as queryHelpers from './query-helpers';
76
import { NativeTestInstance } from './query-helpers';
7+
import { NativeTestInstanceJSON } from './to-json';
8+
import { getQueriesForElement, BoundFunction } from './get-queries-for-element';
89

910
declare const within: typeof getQueriesForElement;
1011

@@ -25,9 +26,10 @@ interface Queries {
2526
export type RenderResult<Q extends Queries = typeof queries> = {
2627
baseElement: NativeTestInstance;
2728
container: NativeTestInstance;
28-
debug: () => void;
29+
debug: (element?: NativeTestInstance) => void;
2930
rerender: (ui: ReactElement) => void;
3031
unmount: () => void;
32+
asFragment: () => NativeTestInstanceJSON;
3133
} & { [P in keyof Q]: BoundFunction<Q[P]> };
3234

3335
export interface RenderOptions<Q extends Queries = typeof queries> {
@@ -46,6 +48,8 @@ export function render<Q extends Queries>(
4648
options: RenderOptions<Q>,
4749
): RenderResult<Q>;
4850

51+
export const cleanup: () => void;
52+
4953
export const act: (callback: () => void) => void;
5054

5155
export { queries, queryHelpers, within };

0 commit comments

Comments
 (0)