Почему useParams во время теста возвращает undefined в тестовой среде с оболочкой? - PullRequest
1 голос
/ 01 мая 2020

Я видел это в 2 разных базах кода, и я озадачен, потому что он отлично работает в реальном браузере, но не в тестах: если компонент использует хук useParams, хук выдает ошибку в тесте:

Ошибка: Uncaught [TypeError: Невозможно уничтожить свойство accountId из 'undefined' или 'null'.]

Я использую функциональный компонент React, библиотеку тестирования React и React -Router:

// компонент:

const Overview: FC = () => {
  const location = useLocation();
  console.log(location) // see below
  const { accountId } = useParams();
  console.log(accountId) // see below

  ... rest
}

Похоже, что в журналах консоли правильно найдены параметры:

console.log src /screen / Overview /index.tsx:66 accountId: nodata

console.log src / screenshot / Overview / index.tsx: 64 расположение: {путь: '/ mix / Overview / nodata', поиск: '', ха sh: '', состояние: не определено, ключ: 'bn6zvv'}

// тестирование установки с оберткой, как рекомендуется в RTL документах


function renderWithProviders(
  ui,
  {
    route = '/',
    params = routes.root, 
    history = createMemoryHistory({ initialEntries: [route] }),
  } = {},
  apolloMocks
) {
  console.log("route:", route) // see below
  console.log("params:", params) // see below
  return {
    ...render(
      <Provider store={mockProviderStore}>
        <Router history={history}>
          <MockedProvider mocks={apolloMocks}>
            <Route path={params}> // tried to set path to "params" not "route" so the slug of /url/:accountId is properly set
             {ui}
            </Route>
          </MockedProvider>
        </Router>
      </Provider>
    ),
    history,
  };
}

результат консольного журнала в файле test-utils выглядит правильно:

console.log src / test-utils / index. js: 19 маршрут: / микс / обзор / nodata

console.log src / test-utils / index. js: 20 параметров: / микс / обзор /: accountId

// сам по себе

test('it works', async () => {
    const { findByText } = renderWithProviders(<Overview />, {
      route: routes.overview('1234567890'), // => path/1234567890
      params: routes.overview(), // => path/:accountId
    });

    await findByText('loading configs...');

    await waitForElementToBeRemoved(() => getByText('loading configs...'));

    await findByText('View your stuff now. It works!');
  });

Я пытаюсь рекомендовать обходной путь из #kentdodds, чтобы использовать await в тестах, что позволяет изменениям состояния корректно урегулироваться.

Что это за крючок React-Router, который неправильно подбирает параметры маршрута?

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Вы также можете смоделировать параметры запроса, используя Jest, например:

describe(() => {
    test('...', () => {
        jest.spyOn(ReactRouter, 'useParams').mockReturnValue({ id: '1234' });
        // id = 1234 in your tested component
    });
});

См. { ссылка }, чтобы смоделировать больше реакции-маршрутизатора.

0 голосов
/ 02 мая 2020

Убедитесь, что даже если у вас есть оболочка с Маршрутизатором / Маршрутом, как было предложено, компонент, который вы хотите протестировать, будет упакован с Маршрутом с параметрами:

<Route path="/mix/config/:param1/:param2/:param3" >
        <Config />
      </Route>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...