Given a reactive variable
export const isLoggedInVar: ReactiveVar<boolean> = cache.makeVar<boolean>(
!!localStorage.getItem("apiToken")
);
A logout hook simplified as:
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;
}
And a component that calls the hook:
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;
};
When I write a test for the component, I'm forced to use await waitFor(() => {});
in the test.
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();
});
});
But the testing-library documentation mentions:
it is considered bad practice to use an empty callback because it will make the tests more fragile.
I really want to do:
- await waitFor(() => {});
- expect(isLoggedInVar()).toBeFalsy();
+ await waitFor(() => expect(isLoggedInVar()).toBeFalsy());
But this gives me countless errors
An update to ProfileHeader inside a test was not wrapped in act(...).
Which I'm not understanding.
What would be the proper way for my test to wait for the reactive variable to change ?