2

给定一个反应变量

export const isLoggedInVar: ReactiveVar<boolean> = cache.makeVar<boolean>(
  !!localStorage.getItem("apiToken")
);

注销挂钩简化为:

function useLogout(): Dispatch<SetStateAction<boolean>> {
  const client = useApolloClient();
  const [loggedOut, setLogout] = useState(false);

  useEffect(() => {
    const resetCache = async (): Promise<void> => {
      localStorage.clear(); // remove api token
      isLoggedInVar(false); // update reactive variable
      client.resetStore();
    };

    if (loggedOut) {
      resetCache();
    }
  }, [loggedOut, client]);

  return setLogout;
}

还有一个调用钩子的组件:

const ProfileHeader: React.FC = () => {
  const setLogout = useLogout();

  return isLoggedInVar() ? (
      <p>
        <Link to="/settings/">
          <span className="m-auto">Settings</span>
        </Link>

        <button
          type="button"
          data-testid="logout-button"
          onClick={(): void => setLogout(true)}
        >
          Log out
        </button>
      </p>
  ) : null;
};

当我为组件编写测试时,我被迫await waitFor(() => {});在测试中使用。

describe("ProfileHeader", () => {
  it("should allow users to logout", async () => {
    isLoggedInVar(true);

    const { container, getByTestId, queryByTestId } = renderApollo(
      <MemoryRouter>
        <ProfileHeader />
      </MemoryRouter>
    );

    expect(isLoggedInVar()).toBeTruthy();
    expect(getByTestId("logout-button")).toBeTruthy();
    userEvent.click(getByTestId("logout-button"));

    waitForElementToBeRemoved(queryByTestId("logout-button"));
    expect(localStorage.getItem("apiToken")).toBeNull();

    // await new Promise((resolve) => setTimeout(resolve, 0)); // works too
    await waitFor(() => {});
    expect(isLoggedInVar()).toBeFalsy();
  });
});

但是测试库文档提到

使用空回调被认为是不好的做法,因为它会使测试更加脆弱。

我真的很想做:

- await waitFor(() => {});
- expect(isLoggedInVar()).toBeFalsy();
+ await waitFor(() => expect(isLoggedInVar()).toBeFalsy());

但这给了我无数错误

测试中 ProfileHeader 的更新未包含在 act(...) 中。

我不明白。

我的测试等待反应变量改变的正确方法是什么?

4

0 回答 0