react-testing-library
, a minimalist solution designed for testing React components.
react-dom
and react-dom/test-utild
, and the library is designed so that the one who uses it, without any problems would apply in his work best testing practices. The react-testing-library
is based on the following principle: the more the testing process resembles a real session with an application — the more confidently we can say that when an application gets into production, it will work as expected.
data-testid
. This is a common practice that allows you to work with elements whose signatures are meaningless or impractical for a given purpose.
react-testing-library
is a replacement for the enzyme . Using the enzyme
, you can follow the same principles that are laid down in the library considered here, but in this case they are more difficult to adhere because of the additional funds provided by the enzyme
(that is, everything that helps in the details of the test implementation). Details about this can be found here .
react-testing-library
intended for react-dom
, it is also suitable for React Native through the use of this small configuration file .
react-testing-library
.
import React from 'react' import {render, Simulate, wait} from 'react-testing-library' // import 'react-testing-library/extend-expect' // Mock- __mocks__ import axiosMock from 'axios' import GreetingFetcher from '../greeting-fetcher' test('displays greeting when clicking Load Greeting', async () => { // Arrange axiosMock.get.mockImplementationOnce(({name}) => Promise.resolve({ data: {greeting: `Hello ${name}`} }) ) const { getByLabelText, getByText, getByTestId, container } = render(<GreetingFetcher />) // Act getByLabelText('name').value = 'Mary' Simulate.click(getByText('Load Greeting')) // mock- `get` // , await wait(() => getByTestId('greeting-text')) // Assert expect(axiosMock.get).toHaveBeenCalledTimes(1) expect(axiosMock.get).toHaveBeenCalledWith(url) // ! expect(getByTestId('greeting-text')).toHaveTextContent( 'Hello Mary' ) // DOM! expect(container.firstChild).toMatchSnapshot() })
GreetingFletcher
can display some HTML code, for example, like this:
<div> <label for="name-input">Name</label> <input id="name-input" /> <button>Load Greeting</button> <div data-testid="greeting-text"></div> </div>
Load Greeting
button, which will cause a request to the server to load some text in which the specified name is used.
<input />
field, as a result, you can set its value
parameter to a certain value. Common sense suggests that you can use the id
property in the CSS selector: #name-input
. But is the user doing this to find the input field? Definitely not so! The user looks at the screen and finds the field with the signature Name
in which he enters the data. Therefore, this is exactly what our test with getByLabelText
. It detects a control based on its label.
enzyme
, to search for a button, for example, with the inscription Load Greeting
, a CSS selector is used or a search is made on the displayName
of the component constructor. But when the user wants to download some text from the server, he does not think about the details of the program’s implementation, instead he searches for the button labeled Load Greetings
and clicks on it. This is exactly what our test does with the help of the getByText
helper function.
wait
construct, again, simulates user behavior. Here organized waiting for the appearance of text on the screen. The system will wait as long as necessary. In our test, we use a mock object for this, so the text is output almost instantly. But our test doesn't care how long it takes. We do not need to use setTimeout
or something similar in the test.
data-testid
attribute is used; that same “emergency exit” used in situations where searching for elements using some other mechanism does not make sense. In such cases, data-testid
definitely better than alternative methods.
queryByTestId
method. Read about it here . However, due to the response to the above publication and this fantastic performance , additional methods were added to the library.
react-dom/test-utils
.
wait
method is great for this. (Many thanks to Lukash Gandertsky, who suggested this as a replacement for flushPromises
API, which is now considered obsolete).
div
element using document.createElement
, then uses ReactDOM.render
to output data to this div
.
render
function returns the following objects and utility functions:
div
element into which the component was drawn.
ReactDOM.unmountComponentAtNode
to unmount a component (for example, to simplify testing componentWillUnmount
).
alt
attribute.
data-testid
.
queryByText
). They, instead of giving an error when there is no element, return null
, which can be useful if you need to check the DOM for the absence of the element.
lo world
will match Hello World
.
/^Hello World$/
will match Hello World
.
(text, el) => el.tagName === 'SPAN' && text.startsWith('Hello')
will result in the selection of a span
element whose text content begins with Hello
.
react-testing-library
is that it does not have auxiliary methods that allow you to test the implementation details of components. It is aimed at developing tests that promote the application of best practices in the field of software testing and development. We hope the react-testing-library is useful for you.
Source: https://habr.com/ru/post/353076/