Testing Lab 4: Nested Components
Objectives
- Test Setup
- Testing that Projects Display
- Testing Form Display
- Testing Form Cancel
Steps
Test Setup
Create the file
src\projects\__tests__\ProjectList-test.js
.Add the setup code below to test the component.
src\projects\__tests__\ProjectList-test.js
import { render, screen } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import ProjectList from '../ProjectList';
import { MOCK_PROJECTS } from '../MockProjects';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import { store } from '../../state';
describe('<ProjectList />', () => {
const setup = () =>
render(
<Provider store={store}>
<MemoryRouter>
<ProjectList projects={MOCK_PROJECTS} />
</MemoryRouter>
</Provider>
);
beforeEach(() => {});
test('should render without crashing', () => {
setup();
expect(screen).toBeDefined();
});
});Verify the initial test passes.
PASS src/projects/__tests__/ProjectList-test.js
Testing that Projects Display
Test that the
projects
display correctly.src\projects\__tests__\ProjectList-test.js
...
describe('<ProjectList />', () => {
const setup = () =>
render(
<Provider store={store}>
<MemoryRouter>
<ProjectList projects={MOCK_PROJECTS} />
</MemoryRouter>
</Provider>
);
beforeEach(() => {});
test('should render without crashing', () => {
setup();
expect(screen).toBeDefined();
});
+ test('should display list', () => {
+ setup();
+ expect(screen.getAllByRole('heading')).toHaveLength(MOCK_PROJECTS.length);
+ expect(screen.getAllByRole('img')).toHaveLength(MOCK_PROJECTS.length);
+ expect(screen.getAllByRole('link')).toHaveLength(MOCK_PROJECTS.length);
+ expect(screen.getAllByRole('button')).toHaveLength(MOCK_PROJECTS.length);
+ });
});
1. Verify the test passes.
```shell
PASS src/projects/__tests__/ProjectList-test.js
Testing Form Display
Modify the card component to add an
aria-label
so we can access the button in the test.src\projects\ProjectCard.js
...
function ProjectCard(props: ProjectCardProps) {
...
return (
<div className="card">
<img src={project.imageUrl} alt={project.name} />
<section className="section dark">
<Link to={'/projects/' + project.id}>
<h5 className="strong">
<strong>{project.name}</strong>
</h5>
<p>{formatDescription(project.description)}</p>
<p>Budget : {project.budget.toLocaleString()}</p>
</Link>
<button
+ aria-label={`edit ${project.name}`}
className=" bordered"
onClick={() => {
handleEditClick(project);
}}
>
<span className="icon-edit "></span>
Edit
</button>
</section>
</div>
);
}
export default ProjectCard;Modify the form component to add an
aria-label
and aname
(which gives an implicit role of form) so we can access the form in the test.src\projects\ProjectForm.js
...
function ProjectForm({ project: initialProject, onCancel }) {
...
return (
<form
+ aria-label="Edit a Project"
+ name="projectForm"
className="input-group vertical"
onSubmit={handleSubmit}
>
...
</form>
);
}
export default ProjectForm;Test that the form is displayed when edit is clicked.
src\projects\__tests__\ProjectList-test.js
...
describe('<ProjectList />', () => {
...
test('should display list', () => {
...
});
+ test('should display form when edit clicked', async () => {
+ setup();
+ // eslint-disable-next-line testing-library/render-result-naming-convention
+ const user = userEvent.setup();
+ await user.click(
+ screen.getByRole('button', { name: /edit Wisozk Group/i })
+ );
+ expect(
+ screen.getByRole('form', {
+ name: /edit a project/i,
+ })
+ ).toBeInTheDocument();
+ });
});Verify the test passes.
PASS src/projects/__tests__/ProjectList-test.js
Testing Form Cancel
- Test that the form is removed after clicking cancel.
src\projects\__tests__\ProjectList-test.js
...
describe('<ProjectList />', () => {
...
+ test('should display image and remove form when cancel clicked', async () => {
+ setup();
+ // eslint-disable-next-line testing-library/render-result-naming-convention
+ const user = userEvent.setup();
+ await user.click(
+ screen.getByRole('button', { name: /edit Wisozk Group/i })
+ );
+ await user.click(
+ screen.getByRole('button', {
+ name: /cancel/i,
+ })
+ );
+ expect(
+ screen.getByRole('img', {
+ name: /wisozk group/i,
+ })
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByRole('form', {
+ name: /edit a project/i,
+ })
+ ).not.toBeInTheDocument();
+ });
});
Verify the test passes.
PASS src/projects/__tests__/ProjectList-test.js