[英]How to Test Private Routing with React & React-Router
I'm trying to test Private Routing in my React App.我正在尝试在我的 React 应用程序中测试私有路由。 I'm using the following versions:
我正在使用以下版本:
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.3",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^12.8.3",
In my PrivateRoute.js I'm simply checking if user is logged in and redirecting accordingly:在我的PrivateRoute.js 中,我只是检查用户是否已登录并相应地重定向:
...
const PrivateRoute = (props) => {
const { component: Component, ...rest } = props;
const user = useContext(AuthContext);
return (
<Route
{...rest}
render={(matchProps) =>
user ? <Component {...matchProps} /> : <Redirect to="/SignIn" />
}
/>
);
};
...
In my PrivateRoute.test.js I'm simply rendering <PrivateRoute>
and checking the history.location.pathname
.在我的PrivateRoute.test.js 中,我只是渲染
<PrivateRoute>
并检查history.location.pathname
。 However, I always get /
when expecting /SignIn
.但是,我总是在期待
/SignIn
时得到/
。
describe("<PrivateRoute/>", () => {
it("redirects unauthenticated users to SignIn", async () => {
const history = createBrowserHistory();
render(
<BrowserRouter>
<Switch>
<PrivateRoute exact path="/SomeRoute" component={SomeComponent} />
</Switch>
</BrowserRouter>
);
expect(history.location.pathname).toBe("/SignIn");
});
});
What am I missing?我错过了什么?
The answer is to use <Router history={history}>
along with createMemoryHistory
as seen below:答案是使用
<Router history={history}>
和createMemoryHistory
,如下所示:
This comes from React Router Documentaiton这来自React Router Documentaiton
See example test below:请参阅下面的示例测试:
it("redirects unauthenticated users to SignIn", async () => {
const history = createMemoryHistory ({ initialEntries: ["/Private"] });
const PrivateComponent = () => <>Private!</>
const PublicComponent = () => <>Redirected!</>
render(
<Router history={history}>
<Switch>
<PrivateRoute exact path="/Private" component={PrivateComponent} />
<Route exact path="/SignIn" component={PublicComponent} />
</Switch>
</Router>
);
expect(screen.queryByText("Private!")).not.toBeInTheDocument();
expect(screen.queryByText("Redirected!")).toBeInTheDocument();
expect(history.location.pathname).toBe("/SignIn")
});
The reason maybe is that you're redirecting the user to the SignIn component if the AuthContext isn't present.原因可能是如果 AuthContext 不存在,您将用户重定向到 SignIn 组件。 But I think the AuthContext is always present.
但我认为 AuthContext 总是存在的。 So, you should pass a value to the context when a user logs in. And check if the value is present.
因此,您应该在用户登录时将值传递给上下文。并检查该值是否存在。
function PrivateRoute({ children, ...rest }) { const [loggedInUser] = useContext(AuthContext); return ( <Route {...rest} render={({ location }) => loggedInUser.isSignedIn? ( children ): ( <Redirect to={{ pathname: "/SignIn", state: { from: location } }} /> ) } /> ); }
And you'll have to use the PrivateRoute component in the app.js just like you use a Route component.而且您必须在 app.js 中使用 PrivateRoute 组件,就像使用 Route 组件一样。
import React from 'react' import PrivateRoute from 'path/to/PrivateRoute/component' export const UserContext = createContext(); export default function App() { const [loggedInUser, setLoggedInUser] = useState({}); return ( <UserContext.Provider value={[loggedInUser, setLoggedInUser]}> <Router> <Switch> <PrivateRoute path="/top-secret"> <SecretDoor></SecretDoor> </PrivateRoute> <Route path="/SignIn"> <SignIn></SignIn> </Route> </Switch> </Router> </UserContext.Provider> ) }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.