typescript 受保护的路径组件和返回Navigate in测试导致无限循环

7y4bm7vi  于 2023-02-25  发布在  TypeScript
关注(0)|答案(1)|浏览(107)

嘿,所有我有一个受保护的路由组件测试,这是造成无限循环,但似乎只发生在测试中,而不是当运行应用程序:

it("redirects to auth when user is not logged in", () => {
    const currentUser = null;
    render(
      <UserContext.Provider value={{ currentUser, setCurrentUser }}>
        <MemoryRouter>
          <ProtectedRoute user={currentUser}>
            <Profile />
          </ProtectedRoute>
        </MemoryRouter>
      </UserContext.Provider>
    );
    expect(screen.getByText(/sign in/i)).toBeInTheDocument();
  });

当保护路由上的用户为null时出现环路,此为保护路由:

const ProtectedRoute = ({ user, children }: {
  user: DocumentData | null | undefined;
  children: React.ReactElement;
}) => {
  if (!user) return <Navigate to="/auth" replace />;
  return children;
};

我认为Auth中的某些东西导致了这个问题,当我用一些文本替换返回的Navigate时,没有无限循环。这里是Auth,可能是useEffect导致了这个问题吗?

const Auth = () => {
  const { currentUser } = useContext(UserContext);
  const navigate = useNavigate();

  useEffect(() => {
    if (currentUser) navigate("/classes");
  }, [currentUser, navigate]);

  return (
    <AuthWrapper>
      <Routes>
        <Route path="/" element={<Navigate to="/auth/sign-up" />} />
      </Routes>
    </AuthWrapper>
  );
};
lb3vh1jj

lb3vh1jj1#

据我所知,渲染循环是在单元测试中引起的,因为没有渲染路由,所以ProtectedRoute组件被无条件渲染,并且由于currentUser总是null,即falsey,所以重定向到"/auth"被渲染,循环重复,令人厌恶。
类似于实际代码如何呈现要匹配和导航到的路线,单元测试也应该如此。
这里有一个例子,你的实际路径可能不同,它最初呈现在路径"/profile"上,在那里授权检查应该重定向到 other 测试路径,呈现你Assert的组件在文档中有一些文本。

it("redirects to auth when user is not logged in", () => {
  const currentUser = null;
  const setCurrentUser = jest.fn(); // in case it's needed to be defined 🤷🏻‍♂️

  render(
    <UserContext.Provider value={{ currentUser, setCurrentUser }}>
      <MemoryRouter initialEntries={["/profile"]}>
        <Route
          path="/profile"
          element={(
            <ProtectedRoute user={currentUser}>
              <Profile />
            </ProtectedRoute>
          )}
        />
        <Route path="/auth" element={<SignIn />} />
      </MemoryRouter>
    </UserContext.Provider>
  );
  expect(screen.getByText(/sign in/i)).toBeInTheDocument();
});

相关问题