给定一个反应变量
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(...) 中。
我不明白。
我的测试等待反应变量改变的正确方法是什么?