Testing Library React em 4 minutos...
Tags: testing, react, nextjs, frontend
Published: 2021-03-10 23:40:32

Para começar vamos entender o que é o Testing Library. Bom para simplificar é uma biblioteca voltada para testes unitários de aplicações frontend.
Link da biblioteca: https://testing-library.com/

Show!
Agora vamos começar pois temos 4 minutos...rs

1) Primeiro passo é ter um projeto react, então vamos criar um básico.

* Separe uma pasta onde vamos criar nosso projeto
* Abra o terminal nessa pasta e digite o comando abaixo
* npx create-react-app my-app (my-app é o nome do seu projeto)
* Abra a pasta gerada pelo comando no terminal com: cd my-app
* Rode o projeto digitando o seguinte comando no terminal: npm run start

2) Bom demais, nesses comando conseguimos ter um projeto react rodando e ainda já deixar instalado a biblioteca testing-library. Caso queira instalar em algum projeto existente basta fazer os passos abaixo:

* npm install --save-dev @testing-library/react

OBS: com --save deixamos documentado no package.json o que instalamos para quem clonar nosso repositório conseguir rodar sem problemas, o -dev é por que utilizamos essa lib(biblioteca) somente para testar em ambiente de desenvolvimento e não queremos que afete o pacote gerado para deploy em produção! ;-)

3) Agora vamos fazer nosso primeiro teste:
* Crie um arquivo no seu projeto no mesmo lugar que estiver o arquivo que deseja testar com o nome do component/arquivo, ex: button.test.jsx

OBS: Usamos .test quando é um arquivo de testes completos dos comportamento do componente e vamos fazer um regressivo mesmo. E quando queremos apenas fazer uma documentação/especificação do componente usamos .spec, ou seja, fazemos um arquivo desses quando queremos testar apenas o básico e seguindo muitas vezes as premissas que fizeram criar o componente.

* Então vamos mostrar nosso componente e estudar o que pode ser testado:

```javascript
import React from "react";
import PropTypes from "prop-types";
import cs from "classnames";
import './Button.scss';


const Button = ({ kind, gtmCategory, gtmAction, gtmLabel, onClick, className, children, ...otherProps }) => {
    return <button
    onClick={onClick}
    {...otherProps}
    className={cs(`button ${className}`, kind ? `button--${kind}` : null)}
    data-gtm-event-category={gtmCategory}
    data-gtm-event-action={gtmAction}
    data-gtm-event-label={gtmLabel}
    >
        {children}
    </button>
};

Button.propTypes = {
    onClick: PropTypes.func,
    children: PropTypes.any,
    kind: PropTypes.any,
    gtmCategory: PropTypes.any,
    gtmAction: PropTypes.any,
    gtmLabel: PropTypes.any,
    otherProps: PropTypes.any
};

export default Button;

```

* Então vamos para nosso teste: 

```javascript
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import Button from './Button';

test('render button', () => {
    const { getByText } = render(<Button>TESTE 1</Button>);
    const linkElement = getByText('TESTE 1');
    expect(linkElement).toBeInTheDocument();
});

test('render button with kind', () => {
    const { getByText } = render(<Button kind="disabled">TESTE 2</Button>);
    const linkElement = getByText('TESTE 2');
    expect(linkElement).toBeInTheDocument();
});
```

* Algumas explicações sobre nossos testes:
* Fizemos primeiro um render básico do nosso componente passando nenhuma props. Nesse teste dizemos o render do componente na linha 6, utilizando uma das facilidades da lib testing-library pois ela permite pesquisar no código renderizado um text especifico, que no nosso caso foi o título do botão.

* Então para testar mesmo nosso primeiro render esperamos que encontrasse nosso titulo do botão na tela renderizada, utilizando o expect, na linha 8. Nesse caso o expect é uma das ferramentas do próprio Jest(lib que cuida dos testes).

* No segundo teste fizemos uso de uma variação de layout que nosso componente permitia, passando uma props a mais e vendo se conseguimos pegar mesmo assim o título do mesmo.

* Agora se perguntarmos se esses testes estão cobrindo todo nosso componente o que você diria? Se você disse não então prestou atenção no nosso código e viu que temos também uma ação no nosso botão e não passamos por ela, abaixo vamos escrever esse teste juntos:

```javascript
import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import Button from './Button';

test('render button', () => {
    const { getByText } = render(<Button>TESTE 1</Button>);
    const linkElement = getByText('TESTE 1');
    expect(linkElement).toBeInTheDocument();
});

test('render button with kind', () => {
    const { getByText } = render(<Button kind="disabled">TESTE 2</Button>);
    const linkElement = getByText('TESTE 2');
    expect(linkElement).toBeInTheDocument();
});

test('render and click button', () => {
    const mockFunction = jest.fn();
    const { getByText } = render(
        <Button kind="disabled" onClick={()=>mockFunction()}>TESTE 2</Button>
    );
    
    fireEvent.click(getByText('TESTE 2'));
    expect(mockFunction).toBeCalled();
})
```

Nesse último teste fizemos uma function mocada usando jest.fn() que simula uma function e contabiliza quando é acionada, assim fica fácil de testarmos o que esperamos. Basicamente renderizamos nosso botão, depois usamos o fireEvent para disparar um click no botão e usamos no expect a nossa function mocada que nos informa se foi acionada ou não, e então temos nosso resultado esperado com o toBeCalled, ou seja, essa function foi acionada? simm

Com isso terminamos o básico de um teste de componente, seguindo algumas coisas básicas e muito utilizadas em todos testes...

ahh caso queira ver o quanto que cobrimos nosso componente basta executar esse comando no terminal:
npm run coverage

Então vai ser gerado uma pasta na raiz do seu projeto com o nome coverage e então basta abrir a pasta dentro e abrir no navegador o index.html, ai vai ter uma amostra de coberturas de todos seus componentes e telas. Nesse caso ficou assim o do nosso componente:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyxfnnn4qzhjjb1gzhjm.png)