Состояние реакции устанавливается с состоянием предыдущего теста в шутку - PullRequest
0 голосов
/ 14 марта 2020

Я тестирую компонент. Если вызов ajax успешен, он устанавливает состояние фильмов для некоторых данных. Если нет, то это не так.

Это компонент, который делает ajax вызов:

class MoviesList extends PureComponent {
  state = {
    movies: [],
  };

  async componentDidMount() {
    try {
      const res = await fetch(
        'https://api.themoviedb.org/3/discover/movie?api_key=62a958396506ab41d5e9adf0f55261a3&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1',
      )
      const movies = await res.json();
      if (movies.results) {
        this.setState({ movies: movies.results })
      }
    } catch (e) {
      console.error('err: ',e);
    }
  }

  render() {
  render() {
    if (this.state.movies < 1) return <h1 data-testid="loading">LOADING...</h1>

    return (
      <MovieGrid data-testid="movie-grid">
        {this.state.movies.map(movie => <Movie key={movie.id} movie={movie} />)}
      </MovieGrid>
    );
  }
}

Теперь один тест проверяет, что если вызов ajax был успешным, должно быть элемент с идентификатором movie-link на странице:

// use fetch mock
global.fetch = require('jest-fetch-mock')

afterEach(() => {
  cleanup
  console.error.mockClear()
})

console.error = jest.fn()

const movies = {
  success: true,
  results: [
    {
      id: 'hi1',
      title: 'title1',
      poster_path: 'gfdsftg'
    },
    {
      id: 'hi2',
      title: 'title2',
      poster_path: 'gfdsftg'
    }
  ]
}

const movie = movies.results[0]

test('<MoviesList />', async  () => {
  fetch.mockResponseOnce(JSON.stringify(movies))
  const {getByTestId, queryByTestId, getAllByTestId} = render(
    <MemoryRouter>
      <MoviesList />
    </MemoryRouter>
  )

  expect(getByTestId('loading')).toBeTruthy()

  await waitForElement(() => getByTestId('movie-link'))

  // HERE I TEST TO SE IF movie-link  EXISTS!
  expect(queryByTestId('loading')).toBeFalsy()
})  


Как видите, я высмеиваю ответ с помощью переменной movies.

Но теперь я хочу проверить если ответ неудачен, то элемент movie-link не должен быть там. И я пытаюсь сделать это, установив movies.results = false, чтобы он не устанавливал состояние на что-либо.

Это неудачный тест API:

test('<MoviesList /> fail api', async  () => {
  // HERE
  movies.results = false
  fetch.mockResponseOnce(JSON.stringify(movies))
  console.log('this', movies.results)

  const {debug, getByTestId, queryByTestId, getAllByTestId} = render(
    <MemoryRouter>
      <MoviesList />
    </MemoryRouter>
  )

  expect(getByTestId('loading')).toBeTruthy()
  debug()
  expect(queryByTestId('movie-link')).toBeFalsy()
})  

Однако, несмотря на установку movies.results = false он все еще устанавливает состояние с помощью переменной movie. И это не должно быть так, как в компоненте, который у меня есть:

      if (movies.results) {
        this.setState({ movies: movies.results })
      } 

Таким образом, он должен установить состояние, так как результаты установлены в false.

И если я добавлю отладку, я могу видеть, что movie-link и другие элементы присутствуют так, как если бы movies.results = false был массивом с данными, вместо того, чтобы быть установленным в false.

Есть идеи, что я делаю неправильно?

...