Net Ninja React Testing Tutorial
import { render, screen } from '@testing-library/react';
import App from './App';
test('describes what is being tested (name of test)', () => {
// render component to test
render(<App />);
// find elements to interact with
// `screen` looks into DOM
const linkElement = screen.getByText(/learn react/i);
// assert with `expect` (part of Jest testing library)
expect(linkElement).toBeInTheDocument();
});itis an alias of thetestfunction
- only returns 1 element
- error on multiple matches
- general use
- used with async await
- does not error on no match, returns null
- used for finding lack of existence of elements
- returns list of elements
- testing for user input recommended
- heading (ex. h1), button, etc
- forms
- last resort
- best practice to create test folder in component folder
- name as Component.test.js
const h1Element = screen.getByRole("heading", { name: /text between tags/i });- looks for specific text in between
<h1 data-testid="header-1">100</h1>const h1Element = screen.getByTestId("header-1");it('find by example', async () => {
render( <Header title="todo" />);
const h1Element = await screen.findByText(/todo/i);
expect(h1Element).toBeInTheDocument();
});
asyncandawaitare required
it('query by example', () => {
render( <Header title="todo" />);
const h1Element = screen.queryByText(/no/i);
expect(h1Element).not.toBeInTheDocument
});
it('get all by example', () => {
render( <Header title="todo" />);
const h1Elements = screen.getAllByText(/anime/i);
expect(h1Elements.length).toBe(9001);
});
const MockTodoFooter = ({ numberOfIncompleteTasks }) => {
return (
<BrowserRouter>
<TodoFooter
numberOfIncompleteTasks={numberOfIncompleteTasks}
/>
</BrowserRouter>
)
}
it('rendering a mock component wrapped with BrowserRouter', () => {
render(<MockTodoFooter numberOfIncompleteTasks={5} />);
const element = screen.getByText(/5 tasks left/i);
expect(element).toBeInTheDocument();
});
- expects element to be visible to the user
- the element can be in the document but not visible to user
- expects element to contain
tag
- useful when getting by test id
- assert values
- if any assertion fails, the entire test case fails
- negates
expectlogic
- group common tests
- can nest blocks
describe('cool tests only', () => {
if('cool test 1', () => {
...
}
if('cool test 2', () => {
...
}
})
- used when a component is passed a function as a prop
const mockedSetTodo = jest.fn();
it('mock function test', () => {
render(<AddInput fruitList={[]} setFruits={fruits} />);
});
it('fire input test', () => {
render(<AddInput fruitList={[]} setFruits={fruits} />);
const inputElement = screen.getByPlaceholderText(/Add a new fruit here.../i);
fireEvent.click(inputElement)
fireEvent.change(inputElement, { target: { value: "Orange" } })
expect(inputElement.value).toBe("Orange");
});
it('button click test', () => {
...
const buttonElement = screen.getByRole("button", { name: /Add/i});
fireEvent.click(buttonElement)
});
- testing multiple components
- we test the parent component
const addTask = (tasks) => {
const inputElement = screen.getByPlaceholderText(/Add a new task here.../i);
const buttonElement = screen.getByRole("button", { name: /Add/i} );
tasks.forEach((task) => {
fireEvent.change(inputElement, { target: { value: task } });
fireEvent.click(buttonElement);
})
}
- bundle repetitive test code into functions
it('should render multiple items', () => {
render( <MockTodo />);
addTask(["task 1", "task 2", "task 3"])
const divElements = screen.getAllByTestId("task-container");
expect(divElements.length).toBe(3)
});
- can have multiple elements with same test id
- found in the mocks/ directory directly adjacent to node_modules/
- naming and location is important
- src/mocks/axios.js
const mockResponse = {
data: {
results: [
{
name: {
first: "Shinichi",
last: "Akiyama"
},
login: {
username: "kanzakinao"
}
}
]
}
}
export default {
get: jest.fn().mockResolvedValue(mockResponse)
}
- will run before/after each test in a describe block
beforeEach(() => {
console.log('run before each test');
})