Я тестирую компонент. Если вызов 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.
Есть идеи, что я делаю неправильно?