Skip to content

Commit 66f8fd3

Browse files
author
Steve Galili
committed
further tests migration and readme update
1 parent 13376d6 commit 66f8fd3

15 files changed

+67
-83
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
### This is how you should test 🧪 your react-native ⚛️ components with [Jest](https://jestjs.io/) and [React Native Testing Library](https://www.native-testing-library.com/)
1+
### This is how you should test 🧪 your react-native ⚛️ components with [Jest](https://jestjs.io/) and [React Native Testing Library](https://callstack.github.io/react-native-testing-library/)
22

33
##### 👏 Inspired by [Kent C. Dodds'](https://testingjavascript.com/) workshop [Test React Components with Jest and React Testing Library](https://github.com/testing-library/react-testing-library). For more info check [Epic React](https://epicreact.dev/)
44

__tests__/Counter-test.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import 'react-native'
22
import React from 'react'
3-
import {fireEvent, render} from '@testing-library/react-native'
3+
import {fireEvent, render} from 'react-native-testing-library'
44
import Counter from "../src/components/Counter"
55
import {expect, it} from '@jest/globals'
66

77
it('renders correctly', () => {
8-
const {getByText, getByTestId, debug} = render(<Counter />)
9-
// debug()
10-
const decrement = getByTestId(/decrement/i)
11-
const increment = getByTestId(/increment/i)
8+
const {getByText} = render(<Counter />)
9+
10+
const decrement = getByText(/decrement/i)
11+
const increment = getByText(/increment/i)
1212
const counterText = getByText(/Current count:/i)
1313

1414
expect(counterText.props.children).toEqual(["Current count: ", 0])

__tests__/CounterUsesCustomHook-test.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import {
44
act,
55
fireEvent,
66
render,
7-
} from '@testing-library/react-native'
7+
} from 'react-native-testing-library'
88
import CounterUsesCustomHook from '../src/components/CounterUsesCustomHook'
99
import useCounter from '../src/hooks/useCounter'
1010
import {renderHook} from '@testing-library/react-hooks'
11-
import {describe, expect, it, test} from '@jest/globals'
11+
import {expect, it, test} from '@jest/globals'
1212

1313
//testing with the component
1414
it('exposes the count and increment/decrement functions', () => {
15-
const {getByText, getByTestId, debug} = render(<CounterUsesCustomHook />)
16-
// debug()
17-
const decrement = getByTestId(/decrement/i)
18-
const increment = getByTestId(/increment/i)
15+
const {getByText} = render(<CounterUsesCustomHook />)
16+
17+
const decrement = getByText(/decrement/i)
18+
const increment = getByText(/increment/i)
1919
const counterText = getByText(/Current count:/i)
2020

2121
expect(counterText.props.children).toEqual(['Current count: ', 0])

__tests__/EasyButton-test.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@ import React from 'react'
33
import EasyButton from '../src/components/EasyButton'
44
import {render} from '../src/test/test-utils'
55
import {expect, it} from '@jest/globals'
6+
import {ReactTestInstance} from 'react-test-renderer'
67

78
it('renders with the light styles for the light theme', () => {
8-
const {getByTestId, getByText} = render(<EasyButton>Click me!</EasyButton>)
9-
const button = getByTestId(/easy/i)
9+
const {getByText} = render(<EasyButton>Click me!</EasyButton>)
1010
const innerText = getByText(/click/i)
11+
const button = innerText.parent as ReactTestInstance
1112

1213
expect(button.props.style).toMatchObject({backgroundColor: 'white'})
1314
expect(innerText.props.style).toMatchObject({color: 'black'})
1415
})
1516

1617
it('renders with the dark styles for the dark theme', () => {
17-
const {getByTestId, getByText} = render(<EasyButton>Click me!</EasyButton>, {
18+
const {getByText} = render(<EasyButton>Click me!</EasyButton>, {
1819
theme: 'dark',
1920
})
20-
const button = getByTestId(/easy/i)
2121
const innerText = getByText(/click/i)
22+
const button = innerText.parent as ReactTestInstance
2223

2324
expect(button.props.style).toMatchObject({backgroundColor: 'black'})
2425
expect(innerText.props.style).toMatchObject({color: 'white'})

__tests__/Home-test.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import 'react-native'
22
import React from 'react'
3-
import {fireEvent, render, wait} from '@testing-library/react-native'
3+
import {fireEvent, render, waitFor} from 'react-native-testing-library'
44
import App from '../src/components/App'
55
import {expect, it, jest} from '@jest/globals'
66
//mocking async storage module
77
const mockedSetItem = jest.fn();
88
jest.mock('@react-native-community/async-storage', () => ({setItem: mockedSetItem}))
99

10-
it('renders/navigats throughout app screens', async () => {
10+
it('renders/navigates throughout app screens', async () => {
1111
const {getByText} = render(<App />)
12-
// const homeText = getByText(/home/i)
13-
// expect(homeText).not.toBeNull()
14-
// fireEvent.press(getByText(/counter/i))
15-
//
16-
// await wait(() => {
17-
// const counterText = getByText(/Current count:/i)
18-
// expect(counterText.props.children).toEqual(['Current count: ', 0])
19-
// })
12+
const homeText = getByText(/home/i)
13+
expect(homeText).not.toBeNull()
14+
fireEvent.press(getByText(/counter/i))
15+
16+
await waitFor(() => {
17+
const counterText = getByText(/Current count:/i)
18+
expect(counterText.props.children).toEqual(['Current count: ', 0])
19+
})
2020
})

__tests__/Login-test.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import 'react-native'
22
import React from 'react'
3-
import {fireEvent, render} from '@testing-library/react-native'
3+
import {fireEvent, render} from 'react-native-testing-library'
44
import Login from '../src/components/Login'
55
import {expect, it, jest} from '@jest/globals'
66

77
it('renders correctly', async () => {
88
const username = 'hi'
99
const password = 'qwerty1234'
1010
let submittedData = {}
11+
// @ts-ignore
1112
const handleSubmit = jest.fn(data => (submittedData = data))
12-
const {getByText, getByPlaceholderText} = render(
13+
const {getByText, getByPlaceholder} = render(
1314
<Login onSubmit={handleSubmit} />,
1415
)
1516
const button = getByText(/submit/i)
1617

17-
await fireEvent.changeText(getByPlaceholderText(/username/i), username)
18-
await fireEvent.changeText(getByPlaceholderText(/password/i), password)
18+
await fireEvent.changeText(getByPlaceholder(/username/i), username)
19+
await fireEvent.changeText(getByPlaceholder(/password/i), password)
1920
fireEvent.press(button)
2021

2122
expect(submittedData).toEqual({password, username})

__tests__/LoginSubmission-test.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'react-native'
22
import React from 'react'
3-
import {fireEvent, render, wait} from '@testing-library/react-native'
3+
import {fireEvent, render, waitFor} from 'react-native-testing-library'
44
import LoginSubmission from '../src/components/LoginSubmission'
55
import {useNavigation} from '@react-navigation/native'
66
import AsyncStorage from '@react-native-community/async-storage'
@@ -21,7 +21,6 @@ jest.mock('@react-native-community/masked-view', () => ({}))
2121
beforeEach(() => {
2222
// @ts-ignore
2323
useNavigation.mockReset()
24-
// window.localStorage.removeItem('token')
2524
})
2625

2726
it('renders correctly', async () => {
@@ -36,11 +35,11 @@ it('renders correctly', async () => {
3635

3736
const username = 'chucknorris'
3837
const password = 'i need no password'
39-
const {getByText, getByPlaceholderText} = render(<LoginSubmission />)
38+
const {getByText, getByPlaceholder} = render(<LoginSubmission />)
4039
const button = getByText(/submit/i)
4140

42-
fireEvent.changeText(getByPlaceholderText(/username/i), username)
43-
fireEvent.changeText(getByPlaceholderText(/password/i), password)
41+
fireEvent.changeText(getByPlaceholder(/username/i), username)
42+
fireEvent.changeText(getByPlaceholder(/password/i), password)
4443
fireEvent.press(button)
4544

4645
getByText(/loading/i)
@@ -69,7 +68,7 @@ it('renders correctly', async () => {
6968
]
7069
`)
7170

72-
await wait(() => expect(mockNavigate).toHaveBeenCalledTimes(1))
71+
await waitFor(() => expect(mockNavigate).toHaveBeenCalledTimes(1))
7372
expect(mockNavigate).toHaveBeenCalledWith("Home")
7473
expect(AsyncStorage.setItem).toHaveBeenCalledWith('token', 'fake-token')
7574
})

__tests__/Video-test.tsx

+8-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'react-native'
22
import React from 'react'
3-
import {fireEvent, getByTestId, render} from '@testing-library/react-native'
3+
import {fireEvent, render} from 'react-native-testing-library'
44
import {expect, it} from '@jest/globals'
55
import Video from '../src/components/Video'
66
import {StatusBar} from 'react-native'
@@ -10,29 +10,16 @@ const navigationMock = {
1010
setOptions: jest.fn()
1111
}
1212

13-
// jest.mock(
14-
// 'react-native-video',
15-
// () => {
16-
// const { View } = require('react-native')
17-
// const MockTouchable = (props: JSX.IntrinsicAttributes) => {
18-
// return <View {...props} />
19-
// }
20-
// MockTouchable.displayName = 'Video'
21-
//
22-
// return MockTouchable
23-
// }
24-
// )
25-
2613
jest.mock('react-native-video', () => {
2714
const mockComponent = require('react-native/jest/mockComponent')
2815
return mockComponent('react-native-video')
2916
});
3017

3118
it('renders/navigats throughout app screens', async () => {
32-
const {getByLabelText, getByTestId} = render(<Video navigation={navigationMock}/>)
33-
const video = getByLabelText(/video component/i)
34-
const enterFullScreenButton = getByTestId(/enter-full-screen/i)
35-
const pauseStartButton = getByTestId(/pause-start/i)
19+
const {getByText, getByA11yLabel} = render(<Video navigation={navigationMock}/>)
20+
const video = getByA11yLabel(/video component/i)
21+
const enterFullScreenButton = getByText(/full screen/i)
22+
const pauseStartButton = getByText(/pause\/start/i)
3623

3724
//video is initially playing and presented not on full screen
3825
expect(video.props.paused).toBeFalsy()
@@ -53,14 +40,15 @@ it('renders/navigats throughout app screens', async () => {
5340
height: 200,
5441
zIndex: 5
5542
})
43+
// @ts-ignore
5644
expect(StatusBar._propsStack[0].hidden.value).toBeTruthy()
5745

5846
//play video and exit full screen mode
59-
const pauseStartFSButton = getByTestId(/pause-start-fs/i)
47+
const pauseStartFSButton = getByText(/pause \/ start/i)
6048
fireEvent.press(pauseStartFSButton)
6149
expect(video.props.paused).toBeFalsy()
6250

63-
const exitFullScreenButton = getByTestId(/exit-full-screen/i)
51+
const exitFullScreenButton = getByText(/exit full screen/i)
6452
fireEvent.press(exitFullScreenButton)
6553
expect(video.props.fullscreen).toBeFalsy()
6654
})

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
"@babel/core": "^7.10.2",
3131
"@babel/runtime": "^7.10.2",
3232
"@react-native-community/eslint-config": "^2.0.0",
33-
"@testing-library/react-native": "^5.0.3",
3433
"@types/jest": "^26.0.0",
3534
"@types/react-native": "^0.62.13",
3635
"@types/react-native-video": "^5.0.1",
@@ -43,6 +42,7 @@
4342
"jest": "^26.1.0",
4443
"metro-react-native-babel-preset": "^0.60.0",
4544
"prettier": "^2.0.5",
45+
"react-native-testing-library": "^2.1.1",
4646
"react-test-renderer": "16.13.1",
4747
"typescript": "^3.9.5"
4848
}

src/components/Counter.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ export default () => {
1212
<View style={styles.body}>
1313
<View style={styles.sectionContainer}>
1414
<Text style={styles.sectionTitle}>Current count: {count}</Text>
15-
<TouchableOpacity testID='decrement' style={styles.button} onPress={decrement}>
15+
<TouchableOpacity style={styles.button} onPress={decrement}>
1616
<Text>Decrement</Text>
1717
</TouchableOpacity>
18-
<TouchableOpacity testID='increment' style={styles.button} onPress={increment}>
18+
<TouchableOpacity style={styles.button} onPress={increment}>
1919
<Text>Increment</Text>
2020
</TouchableOpacity>
2121
</View>

src/components/EasyButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default (props: any) => {
88
const [theme] = useTheme()
99
const {backgroundColor, color} = styles[theme]
1010
return (
11-
<TouchableOpacity testID='easy-button' style={{backgroundColor, padding: 8}} {...props}>
11+
<TouchableOpacity style={{backgroundColor, padding: 8}} {...props}>
1212
<Text style={{color}} >{props.children || 'Click me!'}</Text>
1313
</TouchableOpacity>
1414
);

src/components/Home.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ export default ({ navigation }) => {
1919
if (screenName === SCREENS.HOME) return null
2020

2121
return (
22-
<View key={i} style={{padding: 8}}>
23-
<Button
24-
title={screenName}
25-
onPress={() => navigation.navigate(screenName)}
26-
/>
27-
</View>
22+
<TouchableOpacity
23+
key={i} style={{padding: 8}}
24+
onPress={() => navigation.navigate(screenName)}
25+
>
26+
<Text>{screenName}</Text>
27+
</TouchableOpacity>
2828
)
2929
}
3030
)}

src/components/Video.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default ({navigation}) => {
4242
<Text>Exit full screen</Text>
4343
</TouchableOpacity>
4444
<TouchableOpacity testID='pause-start-fs' style={styles.button} onPress={togglePause}>
45-
<Text>Pause/Start</Text>
45+
<Text>Pause / Start</Text>
4646
</TouchableOpacity>
4747
</View>
4848
}

src/test/test-utils.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, {ComponentType} from 'react'
2-
import {render as rtlRender} from '@testing-library/react-native'
2+
import {render as rtlRender} from 'react-native-testing-library'
33
import {ThemeProvider} from '../utils/theme'
44
import {createStackNavigator} from '@react-navigation/stack'
55
import {NavigationContainer} from '@react-navigation/native'
@@ -13,7 +13,7 @@ function render(ui: any, {theme = 'light', ...options} = {}) {
1313
return rtlRender(ui, {wrapper: Wrapper, ...options})
1414
}
1515

16-
export * from '@testing-library/react-native'
16+
export * from 'react-native-testing-library'
1717
// override React Testing Library's render with our own
1818
export {render}
1919

@@ -24,6 +24,7 @@ export const renderWithNavigation = ({ screens = {}, navigatorConfig = {} } = {}
2424
<NavigationContainer>
2525
<Stack.Navigator {...navigatorConfig}>
2626
{
27+
// @ts-ignore
2728
Object.keys(screens).map(name=> <Stack.Screen key={name} name={name} component={screens[name]} />)
2829
}
2930
</Stack.Navigator>

yarn.lock

+8-14
Original file line numberDiff line numberDiff line change
@@ -1439,14 +1439,6 @@
14391439
"@babel/runtime" "^7.5.4"
14401440
"@types/testing-library__react-hooks" "^3.0.0"
14411441

1442-
"@testing-library/react-native@^5.0.3":
1443-
version "5.0.3"
1444-
resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-5.0.3.tgz#8821dcf7fe7364bc7f427d853cd96e4407d88a4f"
1445-
integrity sha512-lQH7vUgwESfagFw4BlKsfpX7Rv/m7h2NYfubY0aoQromSwI1slCxrhwZws8gABTXweob/DyLATsOamHsWdwDnA==
1446-
dependencies:
1447-
pretty-format "^24.9.0"
1448-
wait-for-expect "^3.0.0"
1449-
14501442
"@types/babel__core@^7.0.0":
14511443
version "7.1.9"
14521444
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d"
@@ -6123,7 +6115,7 @@ pretty-format@^25.2.0:
61236115
ansi-styles "^4.0.0"
61246116
react-is "^16.12.0"
61256117

6126-
pretty-format@^26.1.0:
6118+
pretty-format@^26.0.1, pretty-format@^26.1.0:
61276119
version "26.1.0"
61286120
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec"
61296121
integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==
@@ -6259,6 +6251,13 @@ react-native-screens@^2.8.0:
62596251
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.8.0.tgz#9f989096fc5ccf248e0dfa93a74f1a64057e15f1"
62606252
integrity sha512-fUCIQLZX+5XB0ypWX038P3zso54IFFjTsQUZJWEsjC3pp5rPItAt5SzqtJn+uVjcJaczZ+dpIuvj6IFLqkWLZQ==
62616253

6254+
react-native-testing-library@^2.1.1:
6255+
version "2.1.1"
6256+
resolved "https://registry.yarnpkg.com/react-native-testing-library/-/react-native-testing-library-2.1.1.tgz#f40b17aff707731a29bd596cab49fb3f4768ac2e"
6257+
integrity sha512-iorikwlADclvzvHWEE+zB8FdJctP8BtzdWj6C6ECU17B4iSCJ228iF2xcoE47/BKAeHMNRk5WbL0zsWpUvnPgA==
6258+
dependencies:
6259+
pretty-format "^26.0.1"
6260+
62626261
react-native-video@^4.4.5:
62636262
version "4.4.5"
62646263
resolved "https://registry.yarnpkg.com/react-native-video/-/react-native-video-4.4.5.tgz#d0db799293f8622c7894dd0f8875cb41bfafbde8"
@@ -7658,11 +7657,6 @@ w3c-xmlserializer@^2.0.0:
76587657
dependencies:
76597658
xml-name-validator "^3.0.0"
76607659

7661-
wait-for-expect@^3.0.0:
7662-
version "3.0.2"
7663-
resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-3.0.2.tgz#d2f14b2f7b778c9b82144109c8fa89ceaadaa463"
7664-
integrity sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag==
7665-
76667660
walker@^1.0.7, walker@~1.0.5:
76677661
version "1.0.7"
76687662
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"

0 commit comments

Comments
 (0)