I am trying to put url params under test using Enzyme of React Router. The application is simple so far. I have App.jsx that has a <Router />
component with a <Switch />
component and two <Route />
components.
Any help would be appreciated in setting up a test to take a URL as path
from <Route />
and return a value for the path stub in a child <Files />
component.
I am completely new to testing, so please link docs, if you have them, and please pseudo-code or demonstrate an overview of your approach so that I can put it into proper context.
I have not seen any adequate or contextualized methods for testing the URL param functionality that suit my level of understanding. There was an answer here that suggests mocking with Jest, How to test components using new react router hooks? but there is not enough context for me to implement.
This is a basic standup of create-react-app:
function App() {
const [user] = useState(sampleUser);
return (
<UserContext.Provider value={user}>
<SiteHeader />
<Router>
<Switch>
<Route path="/files/:fileId">
<Files />
</Route>
<Route path="*">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit
<code>src/App.js</code>
and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</Route>
</Switch>
</Router>
</UserContext.Provider>
);
}
export default App;
I am interested in testing <Files />
in isolation, and passing in a URL. <Files />
destructures fileId
from the useParams
hook.
The component for Files looks like this:
import React from 'react';
// import PropTypes from 'prop-types';
import { useParams, Router } from 'react-router-dom';
const Files = () => {
const { fileId } = useParams();
return (
<main>
{`component for ${fileId}`}
</main>
);
};
Files.propTypes = {};
Files.defaultProps = {};
export default Files;
For my test, I am importing Files and Route, since Files inherits the path
of Route using the useParams
hook. I am mounting <Route path="/files/:fileId" component={Files} />
, and I am wrapping that with <MemoryRouter initialEntries={['/files/mockId']} initialIndex={0}>
to get state. the full code looks like this:
import React from 'react';
import { mount, shallow, configure, render } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { MemoryRouter, matchPath, useParams } from 'react-router-dom';
import Files from './Files.jsx';
import Route from '../../App.jsx';
configure({ adapter: new Adapter() });
describe('FilesPage', () => {
it('has fileId of `mockId`', () => {
const wrapper = mount(
<MemoryRouter initialEntries={['/page-tagger/mockId']} initialIndex={0}>
<Route path="/page-tagger/:fileId" component={Files} />
// <Files />
</MemoryRouter>
);
// Get value fileId from <Files />
});
});
I have tried many different approaches to get any value from the <Files />
component, but to no avail. I have tried a shallow(<Files />)
, but that leads to an error that useParams
is undefined in the Files.jsx document. So, I mounted and used <MemoryRouter />
. When I see what the wrapper.props() looks like, I can see that <Route />
has the props().children element for App has the path, and that the hook useParam
is not a prop or anything for <Files />
. The url in <MemoryRouter />
does not get passed down to children <Route />
nor <Files />
.
useParams{}
is always undefined. – Mythopoeicundefined
– Springwood