I'm using RedwoodJS which uses React with React Testing Library under the hood. I'm struggling to test a component (and all page components which have this component in the tree) because of the useLocation() hook.
When using a useLocation()
hook inside my component, I need to wrap my component under test with a Router that mocks the browser location history to prevent the error Error: Uncaught [TypeError: Cannot read property 'pathname' of undefined]
.
However when I do that, the Navigation component is no longer fully rendered, so I can't test it... any ideas?
Navigation.js
//import statements
const renderListItems = (pathname) => {
const NavigationItems = [{..},{..},{..}] // example
return NavigationItems.map((item) => {
const selected = pathname.indexOf(item.path) ? false : true
return (
<ListItem
button
key={item.text}
onClick={() => {
navigate(item.route)
}}
selected={selected}
>
<ListItemText primary={item.text} />
</ListItem>
)
})
}
const Navigation = () => {
const { pathname } = useLocation() // this is why I need to wrap the Navigation component in a router for testing; I'm trying to get the current pathname so that I can give a specific navigation item an active state.
return (
<List data-testid="navigation" disablePadding>
{renderListItems(pathname)}
</List>
)
}
export default Navigation
Navigation.test.js
import { screen } from '@redwoodjs/testing'
import { renderWithRouter } from 'src/utilities/testHelpers'
import Navigation from './Navigation'
describe('Navigation', () => {
it('renders successfully', () => {
expect(() => {
renderWithRouter(<Navigation />)
}).not.toThrow()
})
it('has a "Dashboard" navigation menu item', () => {
renderWithRouter(<Navigation />)
expect(
screen.getByRole('button', { text: /Dashboard/i })
).toBeInTheDocument()
})
})
testHelpers.js
This is needed to prevent useLocation()
inside Navigation.js from breaking the test.
import { Router, Route } from '@redwoodjs/router'
import { createMemoryHistory } from 'history'
import { render } from '@redwoodjs/testing'
const history = createMemoryHistory()
export const renderWithRouter = (Component) =>
render(
<Router history={history}>
<Route component={Component} />
</Router>
)
Resulting error
Navigation › has a "Dashboard" navigation menu item
TestingLibraryElementError: Unable to find an accessible element with the role "button"
There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole
<body>
<div />
</body>