TestJS.help

JavaScript Testing Made Simple

Master JavaScript Testing

Learn testing best practices with real-world examples for React, Vue, and Angular. From unit tests to integration testing, we've got you covered with modern tools and techniques.

Always up-to-date
Production-ready examples
Best practices included
Beginner
5 min read

Getting Started with React Testing

Learn the fundamentals of testing React applications with Vitest and Testing Library.

TestJS Team
2024-01-15
01
BasicsVitestTesting Library

Getting Started with React Testing

Testing is a crucial part of building reliable React applications. In this guide, we'll explore the fundamentals of testing React components using Vitest and React Testing Library.

Why Test React Applications?

Testing helps us:

  • Catch bugs early in the development process
  • Ensure components work as expected
  • Maintain code quality over time
  • Build confidence when refactoring

Setting Up Your Testing Environment

First, let's set up Vitest and React Testing Library:

npm install -D vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event

Create a vite.config.ts file with testing configuration:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/test/setup.ts',
  },
})

Your First React Test

Let's start with a simple component test:

// Button.tsx
interface ButtonProps {
  children: React.ReactNode;
  onClick?: () => void;
  disabled?: boolean;
}

export function Button({ children, onClick, disabled }: ButtonProps) {
  return (
    <button 
      onClick={onClick} 
      disabled={disabled}
      className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-300"
    >
      {children}
    </button>
  );
}

Now let's test it:

// Button.test.tsx
import { render, screen } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import { Button } from './Button';

describe('Button', () => {
  it('renders button with text', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
  });

  it('calls onClick when clicked', async () => {
    const user = userEvent.setup();
    const handleClick = vi.fn();
    
    render(<Button onClick={handleClick}>Click me</Button>);
    
    await user.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when disabled prop is true', () => {
    render(<Button disabled>Click me</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});

Testing Best Practices

1. Test Behavior, Not Implementation

Focus on what the component does, not how it does it:

// ❌ Bad - testing implementation details
expect(wrapper.find('.button-class')).toHaveLength(1);

// ✅ Good - testing behavior
expect(screen.getByRole('button')).toBeInTheDocument();

2. Use Meaningful Test Names

Write descriptive test names that explain the expected behavior:

// ❌ Bad
it('test button', () => {});

// ✅ Good
it('should call onClick handler when button is clicked', () => {});

3. Arrange, Act, Assert Pattern

Structure your tests clearly:

it('should update counter when increment button is clicked', async () => {
  // Arrange
  const user = userEvent.setup();
  render(<Counter />);
  
  // Act
  await user.click(screen.getByRole('button', { name: 'Increment' }));
  
  // Assert
  expect(screen.getByText('Count: 1')).toBeInTheDocument();
});

Common Testing Patterns

Testing Props

it('should display the correct title', () => {
  render(<Card title="Test Title" />);
  expect(screen.getByText('Test Title')).toBeInTheDocument();
});

Testing Conditional Rendering

it('should show loading state when loading is true', () => {
  render(<DataComponent loading={true} />);
  expect(screen.getByText('Loading...')).toBeInTheDocument();
});

Testing User Interactions

it('should toggle visibility when button is clicked', async () => {
  const user = userEvent.setup();
  render(<ToggleComponent />);
  
  const button = screen.getByRole('button', { name: 'Toggle' });
  await user.click(button);
  
  expect(screen.getByText('Content is visible')).toBeInTheDocument();
});

Next Steps

Now that you understand the basics, you can:

  • Learn about testing more complex components
  • Explore mocking external dependencies
  • Practice testing forms and user input
  • Discover testing custom hooks

Happy testing! 🧪

More Content Coming Soon!

We're working on comprehensive testing guides for Vue, Angular, and more advanced React patterns. Check back soon for new articles and examples.

Want to be notified? Follow us for updates!