Description
Hey guys, I'm unit testing my React Native components, and one in particular is causing a console.error with a Warning every time I run the tests. I've searched online and through the official documentation for solutions, but I haven't found one. Hopefully, you can help me here, as this is my first time using this tool, which I'm really enjoying.
The error in particular shows this log:
Warning: An update to Animated(View) inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped in act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at C:\mobile\react-native\project\node_modules\react-native\Libraries\Animated\createAnimatedComponent.js:38:59
at TouchableOpacity (C:\mobile\react-native\project\node_modules\react-native\Libraries\Components\Touchable\TouchableOpacity.js:132:23)
at TouchableOpacity
at View
at View (C:\mobile\react-native\project\node_modules\react-native\jest\mockComponent.js:33:18)
at showNotifications (C:\mobile\react-native\project\components\ui\Notifications.jsx:11:2)
The tests file that is Notifications-test.jsx
looks like this:
import {
render,
fireEvent,
screen,
waitFor
} from '@testing-library/react-native'
import Notifications from '@/components/ui/Notifications'
import { initialNotifications } from '@/lib/utils'
jest.mock('@/lib/useColorScheme', () => ({
useColorScheme: () => ({ isDarkColorScheme: true })
}))
jest.mock('@/lib/utils', () => ({
initialNotifications: jest.fn()
}))
const mockInitialNotifications = initialNotifications
jest.mock('@/components/ui/IconSymbol', () => ({
IconSymbol: jest.fn(() => <></>)
}))
jest.mock('@/components/ui/Icons', () => ({
WaterObstructionIcon: jest.fn(() => <></>),
TemperatureSubstrateIcon: jest.fn(() => <></>)
}))
const mockHandleNotificationPress = jest.fn()
const mockHandleClearNotifications = jest.fn()
const initialNotificationsValue = [
{
type: 'waterObstruction',
content: '60% de agua restante'
},
{
type: 'temperatureSubstrate',
content: '0.5% obstrucción'
}
]
describe('<Notifications />', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('should render notification button', () => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
expect(screen.getByRole('button')).toBeOnTheScreen()
})
test('should show notification count badge when there are notifications', () => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
expect(
screen.getByText(initialNotificationsValue.length.toString())
).toBeOnTheScreen()
})
test('does not show notification count when there are no notifications', () => {
mockInitialNotifications.mockReturnValue([])
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
expect(
screen.queryByText(initialNotificationsValue.length.toString())
).not.toBeOnTheScreen()
})
test.each(initialNotificationsValue)(
'should display $count when showNotifications is true',
({ content }) => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={true}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
expect(screen.getByRole('text', { name: content })).toBeOnTheScreen()
}
)
test('should call handleNotificationPress when button is pressed', async () => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
fireEvent.press(screen.getByRole('button'))
await waitFor(() => {
expect(mockHandleNotificationPress).toHaveBeenCalled()
})
})
test('does not call handleNotificationPress when button is disabled', async () => {
mockInitialNotifications.mockReturnValue([])
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
fireEvent.press(screen.getByRole('button'))
await waitFor(() => {
expect(mockHandleNotificationPress).not.toHaveBeenCalled()
})
})
test('should render clear notifications button', () => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={true}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
const clearBtn = screen.getByText('Limpiar todo')
expect(clearBtn).toBeOnTheScreen()
expect(clearBtn).toHaveStyle({ color: 'white' })
expect(clearBtn.props).toHaveProperty('className', 'font-bold')
})
test('should call handleClearNotifications when clear button is pressed', async () => {
mockInitialNotifications.mockReturnValue(initialNotificationsValue)
render(
<Notifications
showNotifications={true}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
const clearBtn = screen.getByText('Limpiar todo')
expect(clearBtn).toBeOnTheScreen()
expect(clearBtn).toHaveStyle({ color: 'white' })
expect(clearBtn.props).toHaveProperty('className', 'font-bold')
fireEvent.press(clearBtn)
await waitFor(() => {
expect(mockHandleClearNotifications).toHaveBeenCalled()
})
})
test('should display "+9" when there are 10 or more notifications', () => {
mockInitialNotifications.mockReturnValue(
Array(10).fill({
type: 'waterObstruction',
content: '60% de agua restante'
})
)
render(
<Notifications
showNotifications={false}
handleNotificationPress={mockHandleNotificationPress}
handleClearNotifications={mockHandleClearNotifications}
/>
)
expect(screen.getByText('+9')).toBeOnTheScreen()
})
})
It is important to clarify that all tests are passing correctly, but this warning is displayed, which I find annoying and makes me doubt if I am doing something wrong. I currently use Jest with Expo and I configured it according to its official documentation. If you need any other resources such as the Notifications component code, please let me know. I would really appreciate your help 🙌