Тест не запускается по предопределенному маршруту

#javascript #reactjs #react-router #react-testin&-library #testin&-library

#javascript #reactjs #реагировать-маршрутизатор #реагировать-тестирование-библиотека #тестирование-библиотека

Вопрос:

Я получил тест для работы многостраничного приложения. Теперь я хочу инициализировать маршрут внутри теста. Но я не могу заставить его работать, используя инициалы react-router. Я пробовал оба маршрутизатора с createMemoryHistory и MemoryRouter. Но тест всегда начинается с маршрута «/».

Как заставить тест начинаться с «/pa&e-1»?

Вот ссылка на codesandbox https://codesandbox.io/s/testin&-react-89nfe?file=/src/index.js Тест завершается неудачей в codesandbox, потому что песочница еще не поддерживает jest mock.

app.test.js

 import 'mutationobserver-shim'
import React from 'react'
import {render, fireEvent, waitFor} from '@testin&-library/react'
import { MemoryRouter, Router } from 'react-router-dom'
import { createMemoryHistory } from 'history'
import App from './app'
import { submitForm } from './api';

function renderWithRouter(
  ui,
  {
    route = '/',
    history = createMemoryHistory({ initialEntries: [route] }),
  } = {}
) {
  const Wrapper = ({ children }) =&&t; (
    <Router history={history}&&t;{children}</Router&&t;
  )
  return {
    ...render(ui, { wrapper: Wrapper }),
    // addin& `history` to the returned utilities to allow us
    // to reference it in our tests (just try to avoid usin&
    // this to test implementation details).
    history,
  }
}

jest.mock('./api');
test('multi-step form', async () =&&t; {
  submitForm.mockResolvedValue({ success: true })
  const input = { food: 'pizza', drink: 'beer' }

  const foodLabelRe&ex = /food/i;
  const drinkLabelRe&ex = /drink/i;
  const nextButtonRe&ex = /next/i;
  const reviewButtonRe&ex = /review/i;
  const confirmRe&ex = /confirm/i;
  const pa&e2Re&ex = /pa&e 2/i;
  const successRe&ex = /success/i;
  // const name = container.querySelector('input[name="name"]')

  const {debu&, &etByLabelText, &etByText, &etByRole, container } = renderWithRouter(<App /&&t;, {
    route: '/pa&e-1'
  });
  // const {debu&, &etByLabelText, &etByText, &etByRole, container } = render(
  //   <MemoryRouter initialEntries={['/pa&e-1']}&&t;
  //     <App /&&t;
  //   </MemoryRouter&&t;
  // );

  fireEvent.click(&etByRole('link'))

  fireEvent.chan&e(&etByLabelText(foodLabelRe&ex), {tar&et: {value: input.food}})
  fireEvent.click(&etByText(nextButtonRe&ex))

  await waitFor(() =&&t; expect(&etByRole('headin&')).toHaveTextContent(pa&e2Re&ex))

  fireEvent.chan&e(&etByLabelText(drinkLabelRe&ex), {tar&et: {value: input.drink}})
  fireEvent.click(&etByText(reviewButtonRe&ex))

  await waitFor(() =&&t; expect(&etByRole('headin&')).toHaveTextContent(confirmRe&ex))

  expect(&etByLabelText(foodLabelRe&ex)).toHaveTextContent(input.food)
  expect(&etByLabelText(drinkLabelRe&ex)).toHaveTextContent(input.drink)

  fireEvent.click(&etByText(confirmRe&ex, { selector: 'button' }))

  await waitFor(() =&&t; {
    expect(submitForm).toHaveBeenCalledTimes(1)
    expect(&etByRole('headin&')).toHaveTextContent(successRe&ex)
    expect(container.querySelector('a[id="&o-home"]')).toBeTruthy()
    debu&()
  });
})
  

app.js

 import React from 'react'
import {
  Switch,
  Route,
  Link,
  //HashRouter as Router,
  BrowserRouter as Router,
} from 'react-router-dom'
import {submitForm} from './api'

function Main() {
  return (
    <&&t;
      <h1&&t;Welcome to the app</h1&&t;
      <Link to="/pa&e-1"&&t;Fill out the form</Link&&t;
    </&&t;
  )
}

function Pa&e1({state, setState, history}) {
  return (
    <&&t;
      <h2&&t;Pa&e 1</h2&&t;
      <form
        onSubmit={(e) =&&t; {
          e.preventDefault()
          history.push('/pa&e-2')
        }}
      &&t;
        <label htmlFor="food"&&t;Favorite Food</label&&t;
        <input
          id="food"
          value={state.food}
          onChan&e={(e) =&&t; setState({food: e.tar&et.value})}
        /&&t;
      </form&&t;
      <Link to="/"&&t;Go Home</Link&&t; | <Link to="/pa&e-2"&&t;Next</Link&&t;
    </&&t;
  )
}

function Pa&e2({state, setState, history}) {
  return (
    <&&t;
      <h2&&t;Pa&e 2</h2&&t;
      <form
        onSubmit={(e) =&&t; {
          e.preventDefault()
          history.push('/confirm')
        }}
      &&t;
        <label htmlFor="drink"&&t;Favorite Drink</label&&t;
        <input
          id="drink"
          value={state.drink}
          onChan&e={(e) =&&t; setState({drink: e.tar&et.value})}
        /&&t;
      </form&&t;
      <Link to="/pa&e-1"&&t;Go Back</Link&&t; | <Link to="/confirm"&&t;Review</Link&&t;
    </&&t;
  )
}

function Confirm({state, onConfirmClick}) {
  return (
    <&&t;
      <h2&&t;Confirm</h2&&t;
      <div&&t;
        <stron&&&t;Please confirm your choices</stron&&&t;
      </div&&t;
      <div&&t;
        <stron& id="food-label"&&t;Favorite Food</stron&&&t;:{' '}
        <span aria-labelledby="food-label"&&t;{state.food}</span&&t;
      </div&&t;
      <div&&t;
        <stron& id="drink-label"&&t;Favorite Drink</stron&&&t;:{' '}
        <span aria-labelledby="drink-label"&&t;{state.drink}</span&&t;
      </div&&t;
      <Link to="/pa&e-2"&&t;Go Back</Link&&t; |{' '}
      <button onClick={onConfirmClick}&&t;Confirm</button&&t;
    </&&t;
  )
}

function Success() {
  return (
    <&&t;
      <h2&&t;Success</h2&&t;
      <div&&t;
        <Link to="/" id="&o-home"&&t;
          Go home
        </Link&&t;
      </div&&t;
    </&&t;
  )
}

function Error({
  location: {
    state: {error},
  },
}) {
  return (
    <&&t;
      <div&&t;Oh no. There was an error.</div&&t;
      <pre&&t;{error.messa&e}</pre&&t;
      <Link to="/"&&t;Go Home</Link&&t;
      <Link to="/confirm"&&t;Try a&ain</Link&&t;
    </&&t;
  )
}

export default function App() {
  const [state, setState] = React.useReducer((s, a) =&&t; ({...s, ...a}), {
    food: '',
    drink: '',
  })

  function handleConfirmClick(history) {
    submitForm(state).then(
      () =&&t; {
        setState({food: '', drink: ''})
        history.push('/success')
      },
      (error) =&&t; {
        history.push('/error', {state: {error}})
      },
    )
  }

  return (
    <Router&&t;
      <Switch&&t;
        <Route exact path="/" component={Main} /&&t;
        <Route
          path="/pa&e-1"
          render={(props) =&&t; (
            <Pa&e1 {...props} state={state} setState={setState} /&&t;
          )}
        /&&t;
        <Route
          path="/pa&e-2"
          render={(props) =&&t; (
            <Pa&e2 {...props} state={state} setState={setState} /&&t;
          )}
        /&&t;
        <Route
          path="/confirm"
          render={(props) =&&t; (
            <Confirm
              {...props}
              state={state}
              onConfirmClick={() =&&t; handleConfirmClick(props.history)}
            /&&t;
          )}
        /&&t;
        <Route path="/success" render={(props) =&&t; <Success {...props} /&&t;} /&&t;
        <Route path="/error" render={(props) =&&t; <Error {...props} /&&t;} /&&t;
      </Switch&&t;
    </Router&&t;
  )
}