Как правильно ждать реактивных переменных в тестах?

Учитывая реактивную переменную

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(...).

Чего я не понимаю.

Каким образом мой тест будет правильно ждать изменения реактивной переменной?

0 ответов

Другие вопросы по тегам