Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/aygunbyr/react-testing-tutorial

React Testing Tutorial from Codevolution
https://github.com/aygunbyr/react-testing-tutorial

jest msw react-testing-library

Last synced: about 1 month ago
JSON representation

React Testing Tutorial from Codevolution

Awesome Lists containing this project

README

        

# React Testing Tutorial Notes

These notes have been taken while following React Testing Tutorial. I have been just taking notes that I need. It may not be helpful for you.

## Useful Links

[React Testing Tutorial - YouTube](https://www.youtube.com/playlist?list=PLC3y8-rFHvwirqe1KHFCHJ0RqNuN61SJd)

[Expect - Jest](https://jestjs.io/docs/expect)

[ByRole | Testing Library](https://testing-library.com/docs/queries/byrole/)

[Document conformance requirements for use of ARIA attributes in HTML](https://www.w3.org/TR/html-aria/#docconformance)

[Cheatsheet | Testing Library](https://testing-library.com/docs/react-testing-library/cheatsheet/)

[Testing Playground Chrome Extension](https://chrome.google.com/webstore/detail/testing-playground/hejbmebodbijjdhflfknehhcgaklhano)

[Custom Render](https://testing-library.com/docs/react-testing-library/setup#custom-render)

[MSW – Seamless API mocking library for browser and Node | Mock Service Worker](https://mswjs.io/)

[Install - Getting Started - Mock Service Worker Docs](https://mswjs.io/docs/getting-started/install)

[Node - Getting Started - Mock Service Worker Docs](https://mswjs.io/docs/getting-started/integrate/node)

## What to test ?

- Test component renders
- Test component renders with props
- Test component renders in different states
- Test component reacts to events

## What not to test ?

- Implementation details
- Third party code
- Code that is not important from a user point of view

## Priority Order for Queries

"Your test should resemble how users interact with your code (component, page, etc.) as much as possible"

1. getByRole (you can filter elements by name)
2. getByLabelText (good for form fields)
3. getByPlaceholderText
4. getByText (for non-interactive elements; div, span, paragraphs)
5. getByDisplayValue (current value of a form element)
6. getByAltText (image, area, input)
7. getByTitle
8. getByTestId

## queryBy and queryAllBy

### queryBy

- Returns the matching node for a query, and return null if no elements match
- Useful for asserting an element that is not present
- Throws an error if more than one match is found

### queryAllBy

- Returns an array of all matching nodes for a query, and return an empty array if no elements match

## findBy and findAllBy

### findBy

- Returns a Promise which resolves when an element is found which matches the given query
- The promise is rejected if no element is found or if more than one element is found after a default timeout of 1000ms

### findAllBy

- Returns a promise which resolves to an array of elements when any elements are found which match the given query
- The promise is rejected if no elements are found after a default timeout of 1000ms

## User Interactions

A click using a mouse or a keypress using a keyboard

Software has to respond to such interactions

Test should ensure the interactions are handled as expected

### user-event

A companion library for Testing Library that simulates user interactions by dispatching the events that would happen if the interaction took place in a browser

It is the recommended way to test user interactions with RTL

### fireEvent vs user-event

fireEvent is a method from RTL which is used to dispatch DOM events

user-event simulates full interactions, which may fire multiple events and do additional checks along the way

For example, we can dispatch the change event on an input field using fireEvent

When a user types into a text box, the element has to be focused, and then keyboard and input events are fired and the selection and value on the element are manipulated as they type

user-event allows you to describe a user interaction instead of a concrete event. It adds visibility and intractability checks along the way and manipulates the DOM just like a user interaction in the browser would. It factors in that the browser e.g. wouldn't let a user click a hidden element or type in a disabled text box

### Update the package @testing-library/user-event

CRA installs user-event but needs upgrading

userEvent.setup() was introduced in v14.

```
npm install @testing-library/user-event@latest
```

### Pointer Interactions

#### Convenience APIs (much easier to read and write)

- click()
- dblClick()
- tripleClick()
- hover()
- unhover()

#### Pointer APIs

- pointer({keys: '[MouseLeft]'})
- pointer({keys: '[MouseLeft][Mouseright]'})
- pointer('[MouseLeft][Mouseright]')
- pointer('[MouseLeft>]') (without releasing button)
- pointer('[/MouseLeft]') (releasing previously pressed button)

### Keyboard Interactions

#### Utility API

- clear()

```js
test('clear', async () => {
render();
await userEvent.clear(screen.getByRole('textbox'));
expect(screen.getByRole('textbox')).toHaveValue('');
});
```

- selectOptions()

```js
test('selectOptions', async () => {
render(

A
B
C
,
);
await userEvent.selectOptions(screen.getByRole('listbox'), ['1', 'C']);
expect(screen.getByRole('option', { name: 'A' }).selected).toBe(true);
expect(screen.getByRole('option', { name: 'B' }).selected).toBe(false);
expect(screen.getByRole('option', { name: 'C' }).selected).toBe(true);
});
```

- deselectOptions()

```js
test('deselectOptions', async () => {
render(

A

B

C
,
);
await userEvent.deselectOptions(screen.getByRole('listbox'), '2');
expect(screen.getByText('B').selected).toBe(false);
});
```

- upload()

```js
test('upload file', async () => {
render(


Upload file:

,
);
const file = new File(['hello'], 'hello.png', { type: 'image/png}' });
const input = screen.getByLabelText(/upload file/i);
await userEvent.upload(input, file);
expect(input.files[0].toBe(file));
expect(input.files.item(0)).toBe(file);
expect(input.files).toHaveLength(1);
});
```

#### Clipboard APIs

- copy()
- cut()
- paste()

#### Keyboard API

- keyboard('foo') // translates to: f, o, o
- keyboard('{Shift>}A{/Shift}') // translates to: Shift(down), A, Shift(up)

## Static analysis testing

Process of verifying that your code meets certain expectations without actually running it

- Ensure consistent style and formatting
- Check for common mistakes and possible bugs
- Limit the complexity of code and
- Verify type consistency

All types of tests run the code and then compare the outcome against known expected outputs to see if everything works OK

Static testing analyses aspects such as readability, consistency, error handling, type checking and alignment with best practises

Testing checks if your code works or not, whereas static analysis checks if it is written well or not

### Static analysis testing tools

- TypeScript
- ESlint
- Prettier
- Husky
- lint-staged

## Prettier

Prettier is a opinionated code formatter that ensures that all outputted code conforms to a consistent style

```
npm install --save-dev --save-exact prettier
```

### eslint-config-prettier

Installation

```
npm install --save-dev eslint-config-prettier
```

## Husky

Husky is a tool that helps improve your commits and more

### husky-init

```
npx husky-init && npm install
```

## lint-staged

Run linters (and formatters) against staged git files

Installation

```
npm install --save-dev lint-staged # requires further setup
```

Run tests before each push, it creates pre-push file:

```
npx husky add .husky/pre-push "npm test -- --watchAll=false"
```