From 188236e6f55ae01a3e4d98092ada565aaa51b65a Mon Sep 17 00:00:00 2001 From: Kenneth Kwakye-Gyamfi Date: Fri, 8 May 2020 12:19:55 +0000 Subject: [PATCH 1/2] Switched most tests from using test IDs --- src/__tests__/act.test.js | 15 +++--- src/__tests__/fireEvent.test.js | 70 ++++++++++++++++------------ src/__tests__/render.test.js | 4 +- src/__tests__/shallow.test.js | 4 +- src/__tests__/waitForElement.test.js | 14 +++--- 5 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/__tests__/act.test.js b/src/__tests__/act.test.js index 67f22ab74..2d3bb4909 100644 --- a/src/__tests__/act.test.js +++ b/src/__tests__/act.test.js @@ -14,11 +14,8 @@ const UseEffect = ({ callback }: { callback: Function }) => { const Counter = () => { const [count, setCount] = React.useState(0); - return ( - setCount(count + 1)}> - {count} - - ); + const text = `Total count: ${count}`; + return setCount(count + 1)}>{text}; }; test('render should trigger useEffect', () => { @@ -37,12 +34,12 @@ test('update should trigger useEffect', () => { }); test('fireEvent should trigger useState', () => { - const { getByTestId } = render(); - const counter = getByTestId('counter'); + const { getByText } = render(); + const counter = getByText(/Total count/i); - expect(counter.props.children).toEqual(0); + expect(counter.props.children).toEqual('Total count: 0'); fireEvent.press(counter); - expect(counter.props.children).toEqual(1); + expect(counter.props.children).toEqual('Total count: 1'); }); test('should act even if there is no act in react-test-renderer', () => { diff --git a/src/__tests__/fireEvent.test.js b/src/__tests__/fireEvent.test.js index 3301dae34..c1c69ebad 100644 --- a/src/__tests__/fireEvent.test.js +++ b/src/__tests__/fireEvent.test.js @@ -9,59 +9,63 @@ import { } from 'react-native'; import { render, fireEvent } from '..'; -const OnPressComponent = ({ onPress }) => ( +const OnPressComponent = ({ onPress, text }) => ( - - Press me + + {text} ); const WithoutEventComponent = () => ( - Content + Without event ); const CustomEventComponent = ({ onCustomEvent }) => ( - Click me + Custom event component ); -const MyCustomButton = ({ handlePress }) => ( - +const MyCustomButton = ({ handlePress, text }) => ( + ); const CustomEventComponentWithCustomName = ({ handlePress }) => ( - + ); describe('fireEvent', () => { test('should invoke specified event', () => { const onPressMock = jest.fn(); - const { getByTestId } = render(); + const { getByText } = render( + + ); - fireEvent(getByTestId('button'), 'press'); + fireEvent(getByText('Press me'), 'press'); expect(onPressMock).toHaveBeenCalled(); }); test('should invoke specified event on parent element', () => { const onPressMock = jest.fn(); - const { getByTestId } = render(); - - fireEvent(getByTestId('text-button'), 'press'); + const text = 'New press text'; + const { getByText } = render( + + ); + fireEvent(getByText(text), 'press'); expect(onPressMock).toHaveBeenCalled(); }); test('should throw an Error when event handler was not found', () => { - const { getByTestId } = render( + const { getByText } = render( 'this is not passed to children'} /> ); - expect(() => fireEvent(getByTestId('text'), 'press')).toThrow( + expect(() => fireEvent(getByText('Without event'), 'press')).toThrow( 'No handler function found for event: "press"' ); }); @@ -70,13 +74,13 @@ describe('fireEvent', () => { const handlerMock = jest.fn(); const EVENT_DATA = 'event data'; - const { getByTestId } = render( + const { getByText } = render( - + ); - fireEvent(getByTestId('custom'), 'customEvent', EVENT_DATA); + fireEvent(getByText('Custom event component'), 'customEvent', EVENT_DATA); expect(handlerMock).toHaveBeenCalledWith(EVENT_DATA); }); @@ -84,9 +88,12 @@ describe('fireEvent', () => { test('fireEvent.press', () => { const onPressMock = jest.fn(); - const { getByTestId } = render(); + const text = 'Fireevent press'; + const { getByText } = render( + + ); - fireEvent.press(getByTestId('text-button')); + fireEvent.press(getByText(text)); expect(onPressMock).toHaveBeenCalled(); }); @@ -101,13 +108,13 @@ test('fireEvent.scroll', () => { }, }; - const { getByTestId } = render( - + const { getByText } = render( + XD ); - fireEvent.scroll(getByTestId('scroll-view'), eventData); + fireEvent.scroll(getByText('XD'), eventData); expect(onScrollMock).toHaveBeenCalledWith(eventData); }); @@ -116,13 +123,16 @@ test('fireEvent.changeText', () => { const onChangeTextMock = jest.fn(); const CHANGE_TEXT = 'content'; - const { getByTestId } = render( + const { getByPlaceholder } = render( - + ); - fireEvent.changeText(getByTestId('text-input'), CHANGE_TEXT); + fireEvent.changeText(getByPlaceholder('Customer placeholder'), CHANGE_TEXT); expect(onChangeTextMock).toHaveBeenCalledWith(CHANGE_TEXT); }); @@ -130,11 +140,11 @@ test('fireEvent.changeText', () => { test('custom component with custom event name', () => { const handlePress = jest.fn(); - const { getByTestId } = render( + const { getByText } = render( ); - fireEvent(getByTestId('my-custom-button'), 'handlePress'); + fireEvent(getByText('Custom component'), 'handlePress'); expect(handlePress).toHaveBeenCalled(); }); @@ -142,11 +152,11 @@ test('custom component with custom event name', () => { test('event with multiple handler parameters', () => { const handlePress = jest.fn(); - const { getByTestId } = render( + const { getByText } = render( ); - fireEvent(getByTestId('my-custom-button'), 'handlePress', 'param1', 'param2'); + fireEvent(getByText('Custom component'), 'handlePress', 'param1', 'param2'); expect(handlePress).toHaveBeenCalledWith('param1', 'param2'); }); diff --git a/src/__tests__/render.test.js b/src/__tests__/render.test.js index e53e6f79a..eca96442f 100644 --- a/src/__tests__/render.test.js +++ b/src/__tests__/render.test.js @@ -110,8 +110,8 @@ test('getAllByTestId, queryAllByTestId', () => { }); test('getByName, queryByName', () => { - const { getByTestId, getByName, queryByName } = render(); - const bananaFresh = getByTestId('bananaFresh'); + const { getByText, getByName, queryByName } = render(); + const bananaFresh = getByText('not fresh'); const button = getByName('Button'); button.props.onPress(); diff --git a/src/__tests__/shallow.test.js b/src/__tests__/shallow.test.js index 927ee1bfc..a31af6c12 100644 --- a/src/__tests__/shallow.test.js +++ b/src/__tests__/shallow.test.js @@ -20,8 +20,8 @@ test('shallow rendering React elements', () => { }); test('shallow rendering React Test Instance', () => { - const { getByTestId } = render(); - const { output } = shallow(getByTestId('text-button')); + const { getByText } = render(); + const { output } = shallow(getByText('Press me')); expect(output).toMatchSnapshot(); }); diff --git a/src/__tests__/waitForElement.test.js b/src/__tests__/waitForElement.test.js index 04d19b432..d84a497b7 100644 --- a/src/__tests__/waitForElement.test.js +++ b/src/__tests__/waitForElement.test.js @@ -11,7 +11,7 @@ class Banana extends React.Component { render() { return ( - {this.props.fresh && Fresh} + {this.props.fresh && Fresh} Change freshness! @@ -36,25 +36,23 @@ class BananaContainer extends React.Component<{}, any> { } test('waits for element until it stops throwing', async () => { - const { getByTestId, getByName, queryByTestId } = render(); + const { getByText, getByName, queryByText } = render(); fireEvent.press(getByName('TouchableOpacity')); - expect(queryByTestId('fresh')).toBeNull(); + expect(queryByText('Fresh')).toBeNull(); - const freshBananaText = await waitForElement(() => getByTestId('fresh')); + const freshBananaText = await waitForElement(() => getByText('Fresh')); expect(freshBananaText.props.children).toBe('Fresh'); }); test('waits for element until timeout is met', async () => { - const { getByTestId, getByName } = render(); + const { getByText, getByName } = render(); fireEvent.press(getByName('TouchableOpacity')); - await expect( - waitForElement(() => getByTestId('fresh'), 100) - ).rejects.toThrow(); + await expect(waitForElement(() => getByText('Fresh'), 100)).rejects.toThrow(); }); test('waits for element with custom interval', async () => { From d808a1406f402f3eb54156b52601a84e4455e5ab Mon Sep 17 00:00:00 2001 From: Kenneth Kwakye-Gyamfi Date: Fri, 8 May 2020 12:33:06 +0000 Subject: [PATCH 2/2] Docs updated to use alternatives --- docs/API.md | 46 ++++++++++++++++++++++++---------------------- docs/Queries.md | 4 ++-- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/docs/API.md b/docs/API.md index 9d3ce81f3..8cf47a27c 100644 --- a/docs/API.md +++ b/docs/API.md @@ -118,7 +118,7 @@ Get the rendered component JSON representation, e.g. for snapshot testing. ## `cleanup` ```ts -const cleanup: () => void +const cleanup: () => void; ``` Unmounts React trees that were mounted with `render`. @@ -126,28 +126,28 @@ Unmounts React trees that were mounted with `render`. For example, if you're using the `jest` testing framework, then you would need to use the `afterEach` hook like so: ```jsx -import { cleanup, render } from 'react-native-testing-library' -import { View } from 'react-native' +import { cleanup, render } from 'react-native-testing-library'; +import { View } from 'react-native'; -afterEach(cleanup) +afterEach(cleanup); it('renders a view', () => { - render() + render(); // ... -}) +}); ``` The `afterEach(cleanup)` call also works in `describe` blocks: ```jsx describe('when logged in', () => { - afterEach(cleanup) + afterEach(cleanup); it('renders the user', () => { - render() + render(); // ... }); -}) +}); ``` Failing to call `cleanup` when you've called `render` could result in a memory leak and tests which are not "idempotent" (which can lead to difficult to debug errors in your tests). @@ -169,12 +169,13 @@ import { render, fireEvent } from 'react-native-testing-library'; test('fire changeText event', () => { const onEventMock = jest.fn(); - const { getByTestId } = render( - // MyComponent renders TextInput with `onChangeText` bound to handleChangeText - + const { getByPlaceholder } = render( + // MyComponent renders TextInput which has a placeholder 'Enter details' + // and with `onChangeText` bound to handleChangeText + ); - fireEvent(getByTestId('change'), 'onChangeText', 'ab'); + fireEvent(getByPlaceholder('change'), 'onChangeText', 'ab'); expect(onEventMock).toHaveBeenCalledWith('ab'); }); ``` @@ -215,15 +216,16 @@ import { render, fireEvent } from 'react-native-testing-library'; const onPressMock = jest.fn(); -const { getByTestId } = render( +const { getByText } = render( - + Press me ); -fireEvent.press(getByTestId('button')); +fireEvent.press(getByText('Press me')); +expect(onPressMock).toHaveBeenCalled(); ``` ### `fireEvent.changeText: (element: ReactTestInstance, ...data: Array) => void` @@ -237,13 +239,13 @@ import { render, fireEvent } from 'react-native-testing-library'; const onChangeTextMock = jest.fn(); const CHANGE_TEXT = 'content'; -const { getByTestId } = render( +const { getByPlaceholder } = render( - + ); -fireEvent.changeText(getByTestId('text-input'), CHANGE_TEXT); +fireEvent.changeText(getByPlaceholder('Enter data'), CHANGE_TEXT); ``` ### `fireEvent.scroll: (element: ReactTestInstance, ...data: Array) => void` @@ -265,13 +267,13 @@ const eventData = { }, }; -const { getByTestId } = render( - +const { getByText } = render( + XD ); -fireEvent.scroll(getByTestId('scroll-view'), eventData); +fireEvent.scroll(getByText('scroll-view'), eventData); ``` #### On a `FlatList` diff --git a/docs/Queries.md b/docs/Queries.md index e82d786db..e4330e4ae 100644 --- a/docs/Queries.md +++ b/docs/Queries.md @@ -203,7 +203,7 @@ A method returning a `ReactTestInstance` with matching props object ### `ByName` -> This method has been **deprecated** because using it results in fragile tests that may break between minor React Native versions. **DON'T USE IT**. It will be removed in next major release (v2.0). Use [`getByTestId`](#bytestid) instead. It's listed here only for back-compat purposes for early adopters of the library -A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches. +> This method has been **deprecated** because using it results in fragile tests that may break between minor React Native versions. **DON'T USE IT**. It will be removed in next major release (v2.0). Use the other alternatives, such as [`getByText`](#bytext) instead. It's listed here only for back-compat purposes for early adopters of the library +> A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches.