In this lesson, we will explore how to test different features of our page.
- Testing with Vitest
- Testing different features
Imagine you are working for a group messaging application. The key feature that needs to be added is to both display the users in the group chat and to be able to change the online status of the user. The company also wants you to build a test suite for each of these features.
- Build test suite for display functionality
- Build display for users as well as their online status
- Build test suite for change functionality
- Build editing functionality to change the online status of a user
- Testing Library: https://testing-library.com/
Before we begin coding, let's complete the initial setup for this lesson:
- Go to the provided GitHub repository link.
- Fork the repository to your GitHub account.
- Clone the forked repository to your local machine.
- Open the project in VSCode.
- Run
npm install
to install all necessary dependencies.
The user should be able to:
- See other users
- Change any user's status
- The company wants a testing suite for each of these features
- Determine if we need to expand the component tree.
- Determine where to implement new hooks, state, or props.
git checkout -b feature-testing
Run json-server to serve our API:
npm run server
This will run the server on http://localhost:4000
. Open http://localhost:4000/users
in your browser and review the existing data structure.
Now, start the React app:
npm run dev
Visit http://localhost:3000
—you should see the application running.
Take a moment to familiarize yourself with the application and components.
Before the functionality of the code is complete, we want to first build out our test suite.
Folder Structure:
└── __tests__
├── App.test.jsx
├── setup.jsx
└── test_suites
├── ChangeStatus.test.jsx
└── DisplayUsers.test.jsx
Update setup.jsx
:
import { afterEach } from 'vitest'
import { cleanup } from '@testing-library/react'
import '@testing-library/jest-dom/vitest'
import fetch from 'node-fetch';
global.fetch = fetch;
global.baseUsers = [...];
global.setFetchResponse = (val) => {
global.fetch = vi.fn(() => Promise.resolve({
json: () => Promise.resolve(val),
ok: true,
status: 200
}));
}
afterEach(() => {
cleanup();
});
Update app.test.jsx
:
import './test_suites/DisplayUsers.test'
import './test_suites/ChangeStatus.test'
Update DisplayUsers.test.jsx
:
import React from 'react';
import { render } from '@testing-library/react';
import App from '../../components/App';
import '@testing-library/jest-dom';
describe('Our app will', () => {
test('displays all users on startup', async () => {
global.setFetchResponse(global.baseUsers);
let { findAllByTestId } = render(<App />);
const userItems = await findAllByTestId('user-item');
expect(userItems).toHaveLength(global.baseUsers.length);
});
});
Update App.jsx
:
import { useState, useEffect } from 'react'
import UserList from './UserList'
function App() {
const [users, setUsers] = useState([])
useEffect(() => {
fetch('http://localhost:6001/users')
.then(r => r.json())
.then(data => setUsers(data))
}, [])
return (<div><UserList users={users} /></div>)
}
export default App;
Commit changes:
git commit -am "render items on page load"
Update ChangeStatus.test.jsx
:
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import App from '../../components/App';
import '@testing-library/jest-dom';
describe('Our App will', () => {
test('edit the status of the user', async () => {
global.setFetchResponse(global.baseUsers);
const { findAllByTestId } = render(<App />);
const statusButtons = await findAllByTestId('status-item');
global.setFetchResponse({...});
fireEvent.click(statusButtons[0]);
expect(fetch).toHaveBeenCalledWith(...);
});
});
Update App.jsx
:
function changeStatus(updatedUser) {
fetch(`http://localhost:6001/users/${updatedUser.id}`, {...})
.then(r => r.json())
.then(data => {...})
}
Update UserList.jsx
:
function UserList({ users, changeStatus }) {
function onClick(user) {...}
return (
<ul>
{users.map((user) => (
<div data-testid="user-item" key={user.id}>
<p data-testid="status-item" onClick={() => onClick(user)}>{user.status}</p>
</div>
))}
</ul>
);
}
export default UserList;
Commit changes:
git commit -am "add edit user functionality to the user object"
git push origin feature-testing
git checkout main
git pull origin main
git branch -d feature-testing
- Add comments to code.
- Update README.
- Remove unnecessary/commented-out code.
- Ensure
vite.config.js
connects with tests. - Research different testing methods if unsure.
This guide ensures proper implementation and testing using Vitest. 🚀