Мокинг состояния загрузки URQL в Jest

Я пытаюсь имитировать состояние загрузки в своих тестах. Состояние с данными и состояние с ошибкой были успешно смоделированы. Ниже вы можете найти пример:

const createMenuWithGraphQL = (graphqlData: MockGraphQLResponse): [JSX.Element, MockGraphQLClient] => {
    const mockGraphQLClient = {
        executeQuery: jest.fn(() => fromValue(graphqlData)),
        executeMutation: jest.fn(() => never),
        executeSubscription: jest.fn(() => never),
    };

    return [
        <GraphQLProvider key="provider" value={mockGraphQLClient}>
            <Menu {...menuConfig} />
        </GraphQLProvider>,
        mockGraphQLClient,
    ];
};

it('displays submenu with section in loading state after clicking on an item with children', async () => {
    const [Component, client] = createMenuWithGraphQL({
        fetching: true,
        error: false,
    });
    const { container } = render(Component);
    const itemConfig = menuConfig.links[0];

    fireEvent.click(screen.getByText(label));

    await waitFor(() => {
        const alertItem = screen.getByRole('alert');

        expect(client.executeQuery).toBeCalledTimes(1);
        expect(container).toContainElement(alertItem);
        expect(alertItem).toHaveAttribute('aria-busy', 'false');
    });
});

Компонент выглядит следующим образом:

export const Component: FC<Props> = ({ label, identifier }) => {
    const [result] = useQuery({ query });

    return (
        <div role="group">
            {result.fetching && (
                <p role="alert" aria-busy={true}>
                   Loading
                </p>
            )}
            {result.error && (
                <p role="alert" aria-busy={false}>
                   Error
                </p>
            )}
            {!result.fetching && !result.error && <p>Has data</p>}
        </div>
    );
};

Понятия не имею, что делаю не так. Когда я запускаю тест, он говоритfetching является false. Любая помощь будет оценена.

1 ответ

Сопровождающий здесь,

Я думаю, проблема в том, что вы синхронно возвращаетесь в executeQuery. Посмотрим, что происходит.

  • Ваш компонент монтируется и проверяет, есть ли синхронное состояние в кеше.
  • Это так, поскольку мы делаем только executeQuery: jest.fn(() => fromValue(graphqlData)),

Мы можем видеть, что это фактически сводится к тому же результату, как если бы результат просто вышел из кеша (нам никогда не нужно обращаться к API, поэтому мы никогда не выполняем выборку).

Мы могли бы решить эту проблему, добавив setTimeout, ... но Wonka (потоковая библиотека, используемая urql) имеет для этого встроенные решения.

Мы можем использовать delay оператор для имитации состояния выборки:

    const mockGraphQLClient = {
        executeQuery: jest.fn(() => pipe(fromValue(data), delay(100)),
    };

Теперь мы можем проверить fetching правильно указать в первые 100 мс, и после этого мы можем использовать waitFor для проверки последующего состояния.

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