zth / enzyme-async-helpers Goto Github PK
View Code? Open in Web Editor NEWAsync helpers for testing React components with Enzyme.
License: MIT License
Async helpers for testing React components with Enzyme.
License: MIT License
When used with React 15, any of the methods causes
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
warning to appear.
This is probably caused by this line, which imports everything from the React package, including PropTypes
in case of React < 16.
Assuming that import is used to get React
and types from the react
package, I think it might be split into separate declarations:
import React from 'react';
import type * from 'react';
I don't know Flow very well though, so this might not be true.
While I realize this package isn't necessarily meant to work with React < 16, if the above is only thing required to make it compatible, I think it's worth doing it.
I'm having a problem, I'm using Enzyme
, Jest
, react-router
, React
, and the enzyme-async-helpers
in my project. Full project link.
But how do I wait for a child component state?
I need this, because to render my component I use the react-router
.
Code of my tests and component:
/* App.jsx */
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import * as BooksAPI from './BooksAPI';
import './App.css';
import HomePage from './components/HomePage';
import SearchPage from './components/SearchPage';
class BooksApp extends Component {
constructor(props) {
super(props);
this.state = {
myBooks: [],
booksSearch: [],
query: '',
loading: true,
};
}
componentDidMount() {
// Capturando todos os MEUS LIVROS da api
BooksAPI.getAll().then((books) => {
this.setState({
myBooks: books,
loading: false,
});
}).catch(err => console.err('[componentDidMount] App -', err));
}
addBook = (book, newShelf) => {
const newBook = book;
newBook.shelf = newShelf;
this.setState(currentState => ({
myBooks: currentState.myBooks.concat([newBook]),
}));
}
setShelfBook = (book, books, newShelf) => {
const newBooks = books.map((myBook) => {
// Percorre por toda lista dos MyBooks já cadastrados para mudar shelf do livro atualizado
if (myBook.id === book.id) {
const newMyBook = myBook;
newMyBook.shelf = newShelf;
return newMyBook;
}
return myBook;
});
return newBooks;
}
movBookShelf = (book, newShelf) => {
const { myBooks, booksSearch } = this.state;
const newMyBooks = this.setShelfBook(book, myBooks, newShelf);
const newBooksSearch = this.setShelfBook(book, booksSearch, newShelf);
this.setState({
myBooks: newMyBooks,
booksSearch: newBooksSearch,
});
}
delBook = (book) => {
const { booksSearch } = this.state;
const newBooksSearch = this.setShelfBook(book, booksSearch, 'none');
this.setState(currentState => ({
myBooks: currentState.myBooks.filter(myBook => myBook.id !== book.id),
booksSearch: newBooksSearch,
}));
}
checkMyBooksHaveChanged = (resultUpdate) => {
const { myBooks } = this.state;
const currentLengthMyBooks = myBooks.length;
const { currentlyReading, wantToRead, read } = resultUpdate;
const newLengthMyBooks = currentlyReading.length + wantToRead.length + read.length;
return currentLengthMyBooks !== newLengthMyBooks;
}
getShelfBook = (book) => {
const { myBooks } = this.state;
const filterBook = myBooks.filter(myBook => myBook.id === book.id);
if (filterBook.length > 0) {
return filterBook[0].shelf;
}
return 'none';
}
addShelfBooksSearch = (booksSearch) => {
const books = booksSearch.map((bookSearch) => {
const book = bookSearch;
book.shelf = this.getShelfBook(book);
return book;
});
return books;
}
updateBook = (book, newShelf) => {
// Atualizando shelf de um livro
BooksAPI.update(book, newShelf).then((result) => {
// Caso consiga atualizar
if (newShelf === 'none') {
this.delBook(book);
} else if (this.checkMyBooksHaveChanged(result) === true) {
this.addBook(book, newShelf);
} else {
this.movBookShelf(book, newShelf);
}
});
}
updateQuery = (newQuery) => {
this.setState({
query: newQuery,
});
if (newQuery !== '') {
BooksAPI.search(newQuery).then((response) => {
const { error } = response;
const booksSearch = error ? [] : this.addShelfBooksSearch(response);
this.setState({
booksSearch,
});
}).catch(err => console.error('deu ruim', err));
}
}
render() {
const { myBooks, booksSearch, query } = this.state;
return (
<div className="app">
<Route
exact
path="/"
render={() => (
<HomePage myBooks={myBooks} updateBook={this.updateBook} />
)}
/>
<Route
path="/search"
render={() => (
<SearchPage
books={booksSearch}
query={query}
updateQuery={this.updateQuery}
updateBook={this.updateBook}
/>
)}
/>
</div>
);
}
}
export default BooksApp
/* App.test.jsx */
import React from 'react';
import { shallow, mount } from 'enzyme';
import { MemoryRouter } from 'react-router';
import { waitForState } from 'enzyme-async-helpers';
import App from './App';
import MyList from './components/HomePage/MyListsBooks/MyList';
import ListBooks from './components/ListBooks';
import Book from './components/ListBooks/Book';
describe('[component] App', () => {
const PATHS = {
homePage: '/',
searchPage: '/search',
};
const CONFIG_API_REQUEST = { timeout: 5000 };
const LIST_BOOKS = [
{
title: 'The Linux Command Line',
authors: [
'William E. Shotts, Jr.',
],
imageLinks: {
smallThumbnail: 'http://books.google.com/books/content?id=nggnmAEACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api',
thumbnail: 'http://books.google.com/books/content?id=nggnmAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api',
},
id: 'nggnmAEACAAJ',
shelf: 'read',
},
{
title: 'The Sebastian Thrun Handbook - Everything You Need to Know about Sebastian Thrun',
authors: [
'Andre Cantrell',
],
imageLinks: {
smallThumbnail: 'http://books.google.com/books/content?id=NqkKvgAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api',
thumbnail: 'http://books.google.com/books/content?id=NqkKvgAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api',
},
id: 'NqkKvgAACAAJ',
shelf: 'wantToRead',
},
{
title: 'Travel by Design',
authors: [
'Marlon G. Boarnet',
'Randall Crane',
],
imageLinks: {
smallThumbnail: 'http://books.google.com/books/content?id=f7EtoDfL6yYC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api',
thumbnail: 'http://books.google.com/books/content?id=f7EtoDfL6yYC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api',
},
id: 'f7EtoDfL6yYC',
shelf: 'currentlyReading',
},
];
it('check init state', () => {
const initStateExptected = {
myBooks: [],
booksSearch: [],
query: '',
loading: true,
};
const wrapper = shallow(<App />);
expect(wrapper.state()).toEqual(initStateExptected);
});
it('check loading state', async () => {
const wrapper = shallow(<App />);
await waitForState(wrapper, state => state.loading === false, CONFIG_API_REQUEST);
const { loading } = wrapper.state();
expect(loading).toBeFalsy();
});
describe('HomePage', () => {
it('check my lists books', () => {
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.homePage]}>
<App />
</MemoryRouter>
));
expect(wrapper.exists('MyListsBooks')).toBeTruthy();
});
it('check three my list', () => {
const lengthMyListExpected = 3;
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.homePage]}>
<App />
</MemoryRouter>
));
const myListsBooks = wrapper.find(MyList);
expect(myListsBooks).toHaveLength(lengthMyListExpected);
});
it('check three lists books', () => {
const lengthListsBooksExpected = 3;
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.homePage]}>
<App />
</MemoryRouter>
));
const myListsBooks = wrapper.find(ListBooks);
expect(myListsBooks).toHaveLength(lengthListsBooksExpected);
});
it('check empty books rendering init state', () => {
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.homePage]}>
<App />
</MemoryRouter>
));
expect(wrapper.exists('Book')).toBeFalsy();
});
it('check books rendering', () => {
const lengthBooksExpected = 3;
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.homePage]}>
<App />
</MemoryRouter>
));
const appComponent = wrapper.find(App).instance();
appComponent.setState({ myBooks: LIST_BOOKS });
wrapper.update();
const booksSearch = wrapper.find(Book);
expect(booksSearch).toHaveLength(lengthBooksExpected);
});
});
describe('SearchPage', () => {
it('check lists books', () => {
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.searchPage]}>
<App />
</MemoryRouter>
));
expect(wrapper.exists('ListBooks')).toBeTruthy();
});
it('check empty books rendering init state', () => {
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.searchPage]}>
<App />
</MemoryRouter>
));
expect(wrapper.exists('Book')).toBeFalsy();
});
it('check books rendering', () => {
const lengthBooksExpected = 3;
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.searchPage]}>
<App />
</MemoryRouter>
));
const appComponent = wrapper.find(App).instance();
appComponent.setState({ booksSearch: LIST_BOOKS });
wrapper.update();
const booksSearch = wrapper.find(Book);
expect(booksSearch).toHaveLength(lengthBooksExpected);
});
xit('check update query search book', () => {
const newQuery = 'react';
const wrapper = mount((
<MemoryRouter initialEntries={[PATHS.searchPage]}>
<App />
</MemoryRouter>
));
const search = wrapper.find('SearchBooksBar input');
const target = { value: newQuery };
search.simulate('change', { target });
wrapper.update();
console.log(wrapper.debug());
});
});
});
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.