Claude Code Plugins

Community-maintained marketplace

Feedback

manage-react-component-tests

@talbenmoshe/zdr-tools
4
0

Create or update test files for React components. Use when user asks to "create component tests", "test MyComponent", "generate tests for component", "update component tests", or mentions needing tests for a React component. Generates vitest test files with render, mocked sub-components, and proper test structure focusing on logic and prop validation.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name manage-react-component-tests
description Create or update test files for React components. Use when user asks to "create component tests", "test MyComponent", "generate tests for component", "update component tests", or mentions needing tests for a React component. Generates vitest test files with render, mocked sub-components, and proper test structure focusing on logic and prop validation.

Manage React Component Tests Skill

This skill helps you create or update test files for React components. Tests follow a specific pattern with vitest, render from React Testing Library, and mocked sub-components to test logic and prop passing in isolation.

When to Use This Skill

Use this skill when you need to:

  • Create a new test file for a React component
  • Update an existing test file when the component changes
  • Generate test coverage for component logic and prop validation

The skill will generate/update:

  • A test file with vitest and React Testing Library imports
  • Mocked versions of all imported sub-components
  • A renderMyComponent helper function using render
  • Individual test cases for different component behaviors and prop permutations

Usage

Invoke this skill when the user asks to:

  • "Create tests for [MyComponent]"
  • "Generate a test file for [MyComponent]"
  • "I need tests for [MyComponent]"
  • "Update tests for [MyComponent]"
  • "The [MyComponent] changed, update its tests"
  • "Test [MyComponent]"

Core Principles

Testing Philosophy

  1. Logic-Focused: Test component logic, not UI appearance
  2. Prop Validation: Verify sub-components receive correct props
  3. Isolation: Mock all sub-components to test the component in isolation
  4. Callback Testing: Simulate callbacks to test handlers
  5. Unit Testing: Each component has its own tests; dependencies should have separate tests

Prerequisites

Before creating/updating component tests:

  1. Verify the component exists - The component you're testing must already be defined
  2. Check for existing test file - Use Glob to search for existing .spec.tsx file
  3. Identify sub-components - Determine what components are imported and rendered
  4. Verify @testing-library/react - Ensure it's installed (for render)

Create vs Update Decision

If test file exists: Update mode

  • Read the existing test file
  • Read the component definition
  • Compare and identify what's missing or outdated
  • Update the test to match current implementation

If test file does NOT exist: Create mode

  • Read the component definition
  • Identify all sub-components to mock
  • Generate complete test file from scratch

Test File Location

CRITICAL: Test files MUST be in the __tests__ folder, which is a SIBLING of the /src folder, NOT inside it.

Directory Structure

packages/
  my-package/
    src/
      components/
        MyComponent.tsx
    __tests__/              # Sibling to src/, NOT inside src/
      MyComponent.spec.tsx  # .tsx extension for React components

Naming Convention

For a component named MyComponent:

  • Test file: MyComponent.spec.tsx (matches component name exactly, with .tsx extension)
  • Located in: packages/my-package/__tests__/MyComponent.spec.tsx

Test File Structure

1. Imports

Import Rules:

  • Import React (required for this project's JSX transform)
  • Import vitest utilities from 'vitest'
  • Import render and screen from '@testing-library/react'
  • Import the component being tested
  • DO NOT import sub-components (they will be mocked)

Example:

import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import { MyComponent } from '../src/components/MyComponent';

2. Mocking Sub-Components

All imported sub-components must be mocked to test the component in isolation.

Pattern:

// Mock all sub-component modules
vi.mock('../src/components/SubComponentA', () => ({
  SubComponentA: vi.fn(() => <div data-testid="mock-sub-component-a">SubComponentA</div>)
}));

vi.mock('../src/components/SubComponentB', () => ({
  SubComponentB: vi.fn(() => <div data-testid="mock-sub-component-b">SubComponentB</div>)
}));

Rules:

  • Place mocks at the top of the file, after imports
  • Use vi.fn() to create a mock function that returns a simple <div>
  • Add data-testid for easy querying in tests
  • Mock EVERY component imported by the component under test

3. Main Describe Block

describe('MyComponent', () => {
  // Helper function
  function renderMyComponent(props?: Partial<MyComponentProps>) {
    // ...
  }

  // Reset mocks before each test
  beforeEach(() => {
    vi.clearAllMocks();
  });

  // Test cases
  it('should render sub-components with correct props', () => {
    // Test...
  });
});

Structure Rules:

  • Main describe uses the component name
  • Contains one renderMyComponent helper function at the top
  • Includes beforeEach to clear mocks
  • All test cases use the renderMyComponent helper

4. renderMyComponent Helper Function

Purpose: Factory function that renders the component with default or custom props.

Pattern:

function renderMyComponent(props?: Partial<MyComponentProps>) {
  const defaultProps: MyComponentProps = {
    title: 'Test Title',
    onSubmit: vi.fn(),
    items: [],
  };

  return render(<MyComponent {...defaultProps} {...props} />);
}

Rules:

  • Accept partial props (optional)
  • Define sensible defaults for all required props
  • Use vi.fn() for callback props
  • Spread defaults first, then custom props
  • Return the result of render()

5. Testing Sub-Component Props

Access the mock to verify props:

import { SubComponentA } from '../src/components/SubComponentA';

it('should pass correct props to SubComponentA', () => {
  renderMyComponent({ title: 'My Title', count: 5 });

  expect(SubComponentA).toHaveBeenCalledWith(
    expect.objectContaining({
      title: 'My Title',
      count: 5
    }),
    expect.anything() // React context
  );
});

Rules:

  • Import the mocked component at the top
  • Use expect(MockedComponent).toHaveBeenCalledWith()
  • Use expect.objectContaining() to match props
  • Use expect.anything() as second arg (React context)

6. Testing Callbacks

Simulate callback invocation to test handlers:

it('should call onSubmit when button is clicked', () => {
  const mockOnSubmit = vi.fn();
  const { SubButton } = require('../src/components/SubButton');

  renderMyComponent({ onSubmit: mockOnSubmit });

  // Get the onClick prop passed to SubButton
  const onClickProp = SubButton.mock.calls[0][0].onClick;

  // Simulate the click
  onClickProp();

  expect(mockOnSubmit).toHaveBeenCalled();
});

Rules:

  • Pass vi.fn() as callback props
  • Extract callback from mock's call arguments
  • Invoke the callback to test the handler
  • Assert the handler was called correctly

7. Testing Conditional Rendering

Test different branches:

it('should render ErrorMessage when error prop is provided', () => {
  const { ErrorMessage } = require('../src/components/ErrorMessage');

  renderMyComponent({ error: 'Something went wrong' });

  expect(ErrorMessage).toHaveBeenCalledWith(
    expect.objectContaining({
      message: 'Something went wrong'
    }),
    expect.anything()
  );
});

it('should not render ErrorMessage when no error', () => {
  const { ErrorMessage } = require('../src/components/ErrorMessage');

  renderMyComponent({ error: null });

  expect(ErrorMessage).not.toHaveBeenCalled();
});

8. Testing Lists and Iterations

Test components rendered in loops:

it('should render ListItem for each item', () => {
  const { ListItem } = require('../src/components/ListItem');
  const items = [
    { id: '1', name: 'Item 1' },
    { id: '2', name: 'Item 2' },
    { id: '3', name: 'Item 3' }
  ];

  renderMyComponent({ items });

  expect(ListItem).toHaveBeenCalledTimes(3);
  expect(ListItem).toHaveBeenNthCalledWith(
    1,
    expect.objectContaining({ id: '1', name: 'Item 1' }),
    expect.anything()
  );
  expect(ListItem).toHaveBeenNthCalledWith(
    2,
    expect.objectContaining({ id: '2', name: 'Item 2' }),
    expect.anything()
  );
  expect(ListItem).toHaveBeenNthCalledWith(
    3,
    expect.objectContaining({ id: '3', name: 'Item 3' }),
    expect.anything()
  );
});

Workflow

Create Workflow

  1. Identify the component - Determine which component to test
  2. Locate the component file - Use Glob to find the component definition
  3. Read the component - Understand props, sub-components, logic branches
  4. Identify sub-components - List all imported components to mock
  5. Ensure __tests__ exists - Create folder if needed (sibling to /src)
  6. Verify @testing-library/react - Check package.json
  7. Create test file in __tests__/MyComponent.spec.tsx with:
    • All required imports (including React)
    • Mock declarations for all sub-components
    • Main describe block
    • renderMyComponent helper function
    • beforeEach to clear mocks
    • Test cases covering all scenarios

Update Workflow

  1. Read existing test and component - Compare current state
  2. Identify changes:
    • New sub-components → Add mocks
    • Changed props → Update test cases
    • New logic branches → Add test cases
    • Removed functionality → Remove tests
  3. Apply updates using Edit tool - Targeted changes only
  4. Verify coverage - Ensure all logic branches tested

Update Guidelines

  • Preserve structure - Use Edit tool, not Write
  • Maintain consistency - Follow existing patterns
  • Keep descriptive names - Clear, behavior-focused
  • Don't delete passing tests - Only update broken/obsolete tests
  • Add missing coverage - Test new logic and props

Best Practices

  1. Test Logic, Not UI - Focus on props passed and callbacks invoked
  2. Mock All Sub-Components - Test the component in complete isolation
  3. Descriptive Test Names - Explain expected behavior clearly
  4. Clear Mocks Between Tests - Use beforeEach with vi.clearAllMocks()
  5. Test All Branches - Cover conditional rendering, loops, error states
  6. Test Callbacks - Simulate sub-component callbacks to test handlers
  7. Use expect.objectContaining - Match specific props without over-specifying

Common Pitfalls to Avoid

  1. Don't Import Sub-Components Normally - They should be mocked, not imported
  2. Don't Forget React Import - Required for JSX in this project
  3. Don't Forget beforeEach - Mocks persist between tests
  4. Don't Test UI Appearance - Focus on logic and prop passing
  5. Don't Skip expect.anything() - It's needed as the second argument for React context
  6. Don't Forget to Mock Everything - ALL sub-components must be mocked

Example Reference

See examples.md in the same directory for complete working examples of:

  • Simple component with sub-components
  • Component with conditional rendering
  • Component with lists and iterations
  • Component with callbacks and handlers
  • Component with complex prop passing
  • Component with multiple branches

Important Notes

File Organization

  • Tests in __tests__/ at package root (sibling to /src)
  • Use .tsx extension
  • Match component name exactly

Dependencies

  • Ensure @testing-library/react is installed
  • Use vi.mock() for all sub-components
  • Mock at the module level, not inside tests

Test Quality

  • Many small tests > few large tests
  • Test happy path and error cases
  • Test all conditional branches
  • Descriptive test names
  • Simple, focused tests

Running Tests

After creating/updating:

  1. Run pnpm test to verify tests pass
  2. Run pnpm lint to check linting
  3. Run pnpm build to verify TypeScript compiles

Mocking Best Practices

  • Always use vi.fn() for mock components
  • Return simple <div> elements with data-testid
  • Clear mocks in beforeEach
  • Import mocked components when you need to assert on them
  • Use expect.objectContaining() to verify props