Vibe coding with AI course · Module 11: Spotify Clone
Testing - Jest & React Testing Library
In this lesson2
Writing tests for React components.
Setup
npm install --save-dev @testing-library/react @testing-library/jest-dom jestComponent Tests
// Button.tsx
export function Button({ onClick, children }: {
onClick: () => void;
children: React.ReactNode
}) {
return (
<button onClick={onClick} className="btn">
{children}
</button>
);
}
// Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';
describe('Button', () => {
it('renders children', () => {
render(<Button onClick={() => {}}>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
fireEvent.click(screen.getByText('Click'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});See you soon!
Code for this lesson: App.tsx
'use client';
import { useState } from 'react';
export default function CreatePlaylistModal() {
const [isOpen, setIsOpen] = useState(true);
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [isPublic, setIsPublic] = useState(true);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (name.trim()) {
alert(`Created playlist: ${name}`);
setIsOpen(false);
}
};
if (!isOpen) {
return (
<div className="min-h-screen bg-black text-white flex items-center justify-center">
<button
onClick={() => setIsOpen(true)}
className="px-6 py-3 bg-green-500 text-black font-semibold rounded-full hover:bg-green-400"
>
Create Playlist
</button>
</div>
);
}
return (
<div className="min-h-screen bg-black/75 flex items-center justify-center p-4">
<div className="bg-gray-900 rounded-lg max-w-md w-full p-6 text-white">
<h2 className="text-2xl font-bold mb-6">Create Playlist</h2>
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label className="block text-sm font-semibold mb-2">
Name
</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="My Playlist"
className="w-full bg-gray-800 text-white px-4 py-3 rounded outline-none focus:ring-2 focus:ring-green-500"
autoFocus
/>
</div>
<div className="mb-4">
<label className="block text-sm font-semibold mb-2">
Description (Optional)
</label>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Add a description..."
className="w-full bg-gray-800 text-white px-4 py-3 rounded outline-none resize-none focus:ring-2 focus:ring-green-500"
rows={3}
/>
</div>
<div className="mb-6">
<label className="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
checked={isPublic}
onChange={(e) => setIsPublic(e.target.checked)}
className="w-5 h-5"
/>
<span>Make playlist public</span>
</label>
</div>
<div className="flex gap-3">
<button
type="button"
onClick={() => setIsOpen(false)}
className="flex-1 py-3 border border-gray-700 rounded-full font-semibold hover:border-white"
>
Cancel
</button>
<button
type="submit"
disabled={!name.trim()}
className="flex-1 py-3 bg-green-500 rounded-full text-black font-semibold hover:bg-green-400 disabled:bg-gray-700 disabled:text-gray-500"
>
Create
</button>
</div>
</form>
</div>
</div>
);
}Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. Which libraries do we install to test React components?
2. What is fireEvent.click() used for in a test?
Hands-on tasks in the game
- Click in order
Click the elements to build the testing utilities import:
- Vertical ordering
Order the steps of a test that checks a button click: