Install in seconds
Install this skill
Copy the command and run it in your terminal. You can review the source before installing.
terminal
git clone https://github.com/Ohh-889/skyroc-admin

Works with Git. The repository opens in your current directory.

๐Ÿงช
QualityTypeScript

Frontend Testing

by Ohh-889

Generates Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities. Use when writing, reviewing, or improving frontend test coverage.

784 stars168 forksAdded 2026/07/20
adminantdreactreact-adminreact19tanstack-querytanstack-router

Documentation

README

Dify Frontend Testing Skill

This skill enables Codex to generate high-quality, comprehensive frontend tests for the Dify project following established conventions and best practices.

โš ๏ธ Authoritative Source: This skill is derived from web/testing/testing.md. Use Vitest mock/timer APIs (vi.*).

When to Apply This Skill

Apply this skill when the user:

  • Asks to write tests for a component, hook, or utility
  • Asks to review existing tests for completeness
  • Mentions Vitest, React Testing Library, RTL, or spec files
  • Requests test coverage improvement
  • Uses pnpm analyze-component output as context
  • Mentions testing, unit tests, or integration tests for frontend code
  • Wants to understand testing patterns in the Dify codebase

Do NOT apply when:

  • User is asking about backend/API tests (Python/pytest)
  • User is asking about E2E tests (Playwright/Cypress)
  • User is only asking conceptual questions without code context

Quick Reference

Tech Stack

Tool Version Purpose
Vitest 4.0.16 Test runner
React Testing Library 16.0 Component testing
jsdom - Test environment
nock 14.0 HTTP mocking
TypeScript 5.x Type safety

Key Commands

# Run all tests
pnpm test

# Watch mode
pnpm test:watch

# Run specific file
pnpm test path/to/file.spec.tsx

# Generate coverage report
pnpm test:coverage

# Analyze component complexity
pnpm analyze-component <path>

# Review existing test
pnpm analyze-component <path> --review

File Naming

  • Test files: ComponentName.spec.tsx (same directory as component)
  • Integration tests: web/__tests__/ directory

Test Structure Template

import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import Component from './index'

// โœ… Import real project components (DO NOT mock these)
// import Loading from '@/app/components/base/loading'
// import { ChildComponent } from './child-component'

// โœ… Mock external dependencies only
vi.mock('@/service/api')
vi.mock('next/navigation', () => ({
  useRouter: () => ({ push: vi.fn() }),
  usePathname: () => '/test',
}))

// โœ… Zustand stores: Use real stores (auto-mocked globally)
// Set test state with: useAppStore.setState({ ... })

// Shared state for mocks (if needed)
let mockSharedState = false

describe('ComponentName', () => {
  beforeEach(() => {
    vi.clearAllMocks()  // โœ… Reset mocks BEFORE each test
    mockSharedState = false  // โœ… Reset shared state
  })

  // Rendering tests (REQUIRED)
  describe('Rendering', () => {
    it('should render without crashing', () => {
      // Arrange
      const props = { title: 'Test' }
      
      // Act
      render(<Component {...props} />)
      
      // Assert
      expect(screen.getByText('Test')).toBeInTheDocument()
    })
  })

  // Props tests (REQUIRED)
  describe('Props', () => {
    it('should apply custom className', () => {
      render(<Component className="custom" />)
      expect(screen.getByRole('button')).toHaveClass('custom')
    })
  })

  // User Interactions
  describe('User Interactions', () => {
    it('should handle click events', () => {
      const handleClick = vi.fn()
      render(<Component onClick={handleClick} />)
      
      fireEvent.click(screen.getByRole('button'))
      
      expect(handleClick).toHaveBeenCalledTimes(1)
    })
  })

  // Edge Cases (REQUIRED)
  describe('Edge Cases', () => {
    it('should handle null data', () => {
      render(<Component data={null} />)
      expect(screen.getByText(/no data/i)).toBeInTheDocument()
    })

    it('should handle empty array', () => {
      render(<Component items={[]} />)
      expect(screen.getByText(/empty/i)).toBeInTheDocument()
    })
  })
})

Testing Workflow (CRITICAL)

โš ๏ธ Incremental Approach Required

NEVER generate all test files at once. For complex components or multi-file directories:

  1. Analyze & Plan: List all files, order by complexity (simple โ†’ complex)
  2. Process ONE at a time: Write test โ†’ Run test โ†’ Fix if needed โ†’ Next
  3. Verify before proceeding: Do NOT continue to next file until current passes
For each file:
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚ 1. Write test                          โ”‚
  โ”‚ 2. Run: pnpm test <file>.spec.tsx      โ”‚
  โ”‚ 3. PASS? โ†’ Mark complete, next file    โ”‚
  โ”‚    FAIL? โ†’ Fix first, then continue    โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Complexity-Based Order

Process in this order for multi-file testing:

  1. ๐ŸŸข Utility functions (simplest)
  2. ๐ŸŸข Custom hooks
  3. ๐ŸŸก Simple components (presentational)
  4. ๐ŸŸก Medium components (state, effects)
  5. ๐Ÿ”ด Complex components (API, routing)
  6. ๐Ÿ”ด Integration tests (index files - last)

When to Refactor First

  • Complexity > 50: Break into smaller pieces before testing
  • 500+ lines: Consider splitting before testing
  • Many dependencies: Extract logic into hooks first

๐Ÿ“– See references/workflow.md for complete workflow details and todo list format.

Testing Strategy

Path-Level Testing (Directory Testing)

When assigned to test a directory/path, test ALL content within that path:

  • Test all components, hooks, utilities in the directory (not just index file)
  • Use incremental approach: one file at a time, verify each before proceeding
  • Goal: 100% coverage of ALL files in the directory

Integration Testing First

Prefer integration testing when writing tests for a directory:

  • โœ… Import real project components directly (including base components and siblings)
  • โœ… Only mock: API services (@/service/*), next/navigation, complex context providers
  • โŒ DO NOT mock base components (@/app/components/base/*)
  • โŒ DO NOT mock sibling/child components in the same directory

See Test Structure Template for correct import/mock patterns.

Core Principles

1. AAA Pattern (Arrange-Act-Assert)

Every test should clearly separate:

  • Arrange: Setup test data and render component
  • Act: Perform user actions
  • Assert: Verify expected outcomes

2. Black-Box Testing

  • Test observable behavior, not implementation details
  • Use semantic queries (getByRole, getByLabelText)
  • Avoid testing internal state directly
  • Prefer pattern matching over hardcoded strings in assertions:
// โŒ Avoid: hardcoded text assertions
expect(screen.getByText('Loading...')).toBeInTheDocument()

// โœ… Better: role-based queries
expect(screen.getByRole('status')).toBeInTheDocument()

// โœ… Better: pattern matching
expect(screen.getByText(/loading/i)).toBeInTheDocument()

3. Single Behavior Per Test

Each test verifies ONE user-observable behavior:

// โœ… Good: One behavior
it('should disable button when loading', () => {
  render(<Button loading />)
  expect(screen.getByRole('button')).toBeDisabled()
})

// โŒ Bad: Multiple behaviors
it('should handle loading state', () => {
  render(<Button loading />)
  expect(screen.getByRole('button')).toBeDisabled()
  expect(screen.getByText('Loading...')).toBeInTheDocument()
  expect(screen.getByRole('button')).toHaveClass('loading')
})

4. Semantic Naming

Use should <behavior> when <condition>:

it('should show error message when validation fails')
it('should call onSubmit when form is valid')
it('should disable input when isReadOnly is true')

Required Test Scenarios

Always Required (All Components)

  1. Rendering: Component renders without crashing
  2. Props: Required props, optional props, default values
  3. Edge Cases: null, undefined, empty values, boundary conditions

Conditional (When Present)

Feature Test Focus
useState Initial state, transitions, cleanup
useEffect Execution, dependencies, cleanup
Event handlers All onClick, onChange, onSubmit, keyboard
API calls Loading, success, error states
Routing Navigation, params, query strings
useCallback/useMemo Referential equality
Context Provider values, consumer behavior
Forms Validation, submission, error display

Coverage Goals (Per File)

For each test file generated, aim for:

  • โœ… 100% function coverage
  • โœ… 100% statement coverage
  • โœ… >95% branch coverage
  • โœ… >95% line coverage

Note: For multi-file directories, process one file at a time with full coverage each. See references/workflow.md.

Detailed Guides

For more detailed information, refer to:

  • references/workflow.md - Incremental testing workflow (MUST READ for multi-file testing)
  • references/mocking.md - Mock patterns, Zustand store testing, and best practices
  • references/async-testing.md - Async operations and API calls
  • references/domain-components.md - Workflow, Dataset, Configuration testing
  • references/common-patterns.md - Frequently used testing patterns
  • references/checklist.md - Test generation checklist and validation steps

Authoritative References

Primary Specification (MUST follow)

  • web/testing/testing.md - The canonical testing specification. This skill is derived from this document.

Reference Examples in Codebase

  • web/utils/classnames.spec.ts - Utility function tests
  • web/app/components/base/button/index.spec.tsx - Component tests
  • web/__mocks__/provider-context.ts - Mock factory example

Project Configuration

  • web/vitest.config.ts - Vitest configuration
  • web/vitest.setup.ts - Test environment setup
  • web/scripts/analyze-component.js - Component analysis tool
  • Modules are not mocked automatically. Global mocks live in web/vitest.setup.ts (for example react-i18next, next/image); mock other modules like ky or mime locally in test files.

More from Ohh-889

Other Claude Code skills by this author in the directory.

โœจ
1w ago

Code Simplifier

Simplifies and refines code for clarity, consistency, and maintainability while preserving all functionality. Automatically improves recently modified code based on project standards.
Quality
+0%784168
๐Ÿ“
1w ago

Component Documentation

Automates component documentation by analyzing source code, demos, and existing docs to generate MDX files with live demos, API tables, and type definitions.
Writing
+0%784168
โ™ป๏ธ
1w ago

Component Refactoring

Refactors high-complexity React components when complexity > 50 or lines > 300. Provides patterns for extracting hooks, splitting sub-components, simplifying conditionals, and separating API logic. Use before testing to improve maintainability. Not for simple components or third-party wrappers.
Frontend
+0%784168
๐Ÿ“
1w ago

Doc Coauthoring

Guides users through a structured workflow for co-authoring documentation, proposals, technical specs, and decision docs. Helps transfer context, refine content, and verify reader understanding.
Writing
+0%784168
๐Ÿ› ๏ธ
2w ago

Feature Development

A systematic workflow for implementing new features, from codebase exploration and requirements clarification to architecture design, implementation, and quality review.
Quality
+0%784168
๐Ÿ”
1w ago

Frontend Code Review

Reviews frontend code (TSX, TS, JS) for code quality, performance, and business logic issues using a predefined checklist. Supports reviewing staged changes or specific files before commit.
Quality
+0%784168