Так как вы тестируете против context
, в идеале вам нужно протестировать на корневом уровне и сделать утверждения против любых изменений DOM оттуда.Также обратите внимание, что вы не можете использовать Route
вне маршрутизатора (BrowserRouter
, Router
, StaticRouter
, ... и т. Д.), А также history
, который не был подключен к маршрутизатору.Хотя я никогда не пользовался use-react-router
, заглядывая под капот, все же требуется роутер.Следовательно, ваш тест должен включать Provider
, маршрутизатор и вашу страницу / компонент.
Вот рабочий пример тестирования на корневом уровне :
![Edit Protected Route Root Context](https://codesandbox.io/static/img/play-codesandbox.svg)
src / root/index.js
import React from "react";
import { Provider } from "../hooks/useAuthentication";
import Routes from "../routes";
const Root = () => (
<Provider>
<Routes />
</Provider>
);
export default Root;
src / route / index.js
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { Container, Header, ProtectedRoutes } from "../components";
import { About, Dashboard, Home } from "../pages";
const Routes = () => (
<BrowserRouter>
<Container>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<ProtectedRoutes>
<Route exact path="/dashboard" component={Dashboard} />
</ProtectedRoutes>
</Switch>
</Container>
</BrowserRouter>
);
export default Routes;
src / root / __ tests __ / root.test.js
import React from "react";
import { mount } from "enzyme";
import Root from "../index";
describe("Authentication", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(<Root />);
wrapper
.find("Router")
.prop("history")
.push("/dashboard");
wrapper.update();
});
afterAll(() => {
wrapper.unmount();
});
it("initially renders a Login component and displays a message", () => {
expect(wrapper.find("h1").text()).toEqual("Login");
expect(wrapper.find("h3").text()).toEqual(
"You must login before viewing the dashboard!"
);
});
it("authenticates the user and renders the Dashboard", () => {
wrapper.find("button").simulate("click");
expect(wrapper.find("h1").text()).toEqual("Dashboard");
});
it("unauthenticates the user and redirects the user to the home page", () => {
wrapper.find("button").simulate("click");
expect(wrapper.find("h1").text()).toEqual("Home");
});
});
Страница панели инструментов может быть изолирована, если она имеет доступ к функциям аутентификации;однако, это может создать некоторые повторяющиеся тестовые случаи для последующих страниц / компонентов и не имеет особого смысла, поскольку все еще требует установки контекста на корневом уровне и маршрутизатора (особенно, если компонент / страница или ловушка подписываются наhistory
).
Вот рабочий пример, когда страница панели инструментов была изолирована для тестирования :
![Edit Protected Route Confined Context](https://codesandbox.io/static/img/play-codesandbox.svg)
src / route / index.js
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { Container, Header, ProtectedRoutes } from "../components";
import { About, Dashboard, Home } from "../pages";
const Routes = () => (
<BrowserRouter>
<Container>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<ProtectedRoutes>
<Route exact path="/dashboard" component={Dashboard} />
</ProtectedRoutes>
</Switch>
</Container>
</BrowserRouter>
);
export default Routes;
компонентов / ProtectedRoutes / index.js
import React from "react";
import { useAuthentication } from "../../hooks";
import Login from "../Login";
const ProtectedRoutes = ({ children }) => {
const { isAuthenticated, login } = useAuthentication();
return isAuthenticated ? children : <Login login={login} />;
};
export default ProtectedRoutes;
страниц/Dashboard/index.js
import React, { Fragment, useCallback } from "react";
import { useAuthentication } from "../../hooks";
import { Button, Description, Title } from "../../components";
const Dashboard = ({ history }) => {
const { logout } = useAuthentication();
const unAuthUser = useCallback(() => {
logout();
history.push("/");
}, [history, logout]);
return (
<Fragment>
<Title>Dashboard</Title>
<Description>
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper
suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem
vel eum iriure dolor in hendrerit in vulputate velit esse molestie
consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et
accumsan et iusto odio dignissim qui blandit praesent luptatum zzril
delenit augue duis dolore te feugait nulla facilisi.
</Description>
<Button onClick={unAuthUser}>Logout</Button>
</Fragment>
);
};
export default Dashboard;
страницы / Панель инструментов / __ тесты __ / Dashboard.test.js
import React from "react";
import { mount } from "enzyme";
import { BrowserRouter, Route } from "react-router-dom";
import { Provider } from "../../../hooks/useAuthentication";
import { ProtectedRoutes } from "../../../components";
import Dashboard from "../index";
describe("Dashboard Page", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(
<Provider>
<BrowserRouter>
<ProtectedRoutes>
<Route exact path="/" component={Dashboard} />
</ProtectedRoutes>
</BrowserRouter>
</Provider>
);
});
afterAll(() => {
wrapper.unmount();
});
it("initially renders a login component and displays a message", () => {
expect(wrapper.find("h1").text()).toEqual("Login");
expect(wrapper.find("h3").text()).toEqual(
"You must login before viewing the dashboard!"
);
});
it("authenticates the user and updates the component", () => {
wrapper.find("button").simulate("click");
expect(wrapper.find("h1").text()).toEqual("Dashboard");
});
it("unauthenticates the user", () => {
wrapper.find("button").simulate("click");
expect(wrapper.find("h1").text()).toEqual("Login");
});
});