frontend-testing
- Repo stars 143,731
- Author updated Live
- Author repo dify
- Domain
- AI
- Compatible agents
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- Trust score
- 88 / 100 · community maintained
- Author / version / license
- @langgenius · no license declared
- Token usage
- Lean
- Setup complexity
- Guided setup
- External API key
- Not required
- Operating systems
- Unspecified (assume cross-platform)
- Runtime requirements
- Python
- Permissions
-
- Read-only
- Write / modify
- Shell exec
- Network behavior
- Local-only
- Install commands
- 26 variants
Profile is derived at build time from SKILL.md and install vectors. Subject to drift from author intent.
Heads up: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: frontend-testing
description: Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities…
category: ai
runtime: Python
---
# frontend-testing output preview
## PART A: Task fit
- Use case: Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities. Triggers on testing, spec files, coverage, Vitest, RTL, unit tests, integration tests, or write/review test requests..
- Inputs: target material, constraints, expected output, and acceptance criteria.
- Evidence boundary: follow “When to Apply This Skill / Quick Reference / Key Commands” and do not present inference as author intent.
## PART B: Execution result
- **01** The card summarizes the use case; runtime output centers on “Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities. Triggers on testing, spec files, coverage, Vitest, RTL, unit tests, integration tests, or write/review test requests.”.
- **02** When the source has headings, the agent prioritizes “When to Apply This Skill / Quick Reference / Key Commands” so the result follows the author’s structure.
- **03** Typical output includes task judgment, concrete steps, required commands or file edits, validation, and follow-up options.
- **04** Risk context follows the fingerprint: read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
## Running Rules
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding scope.
- Return the result, validation criteria, and next iteration options. The source does not require a stable slash command. After installation, invoke the skill by name and describe the task.
Name target files or source material, expected output, forbidden changes, and whether network or shell access is allowed. Permission fingerprint: read files, write/modify files, run shell commands.
Start with a small task and check whether the result follows “When to Apply This Skill / Quick Reference / Key Commands”. Inspect diffs, logs, previews, or tests before expanding scope.
Confirm the final output includes a concrete result, evidence, and next action. If it stays generic, tighten inputs, boundaries, and acceptance criteria.
---
name: frontend-testing
description: Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities…
category: ai
source: langgenius/dify
---
# frontend-testing
## When to use
- Generate Vitest + React Testing Library tests for Dify frontend components, hooks, and utilities. Triggers on testing…
- Use it when the task has clear inputs, repeatable steps, and validation criteria.
## What to provide
- Target material, scope, expected result, and forbidden changes.
- Whether network, commands, file writes, or external services are allowed.
## Execution rules
- Organize steps around “When to Apply This Skill / Quick Reference / Key Commands” and keep inference separate from source facts.
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding the task.
## Output requirements
- Return the deliverable, key evidence, validation method, and next action.
- Mark missing information as unknown; do not invent commands, platforms, or dependencies. The author source anchors workflow facts; repository files anchor sources and commands; Fluxly only adds fit, limitations, and quality judgment.
skill "frontend-testing" {
input -> user goal + target files + boundaries + acceptance criteria
context -> When to Apply This Skill / Quick Reference / Key Commands
rules -> SKILL.md triggers / order / output contract
runtime -> Python | read files, write/modify files, run shell commands | mostly runs locally
guardrails -> usually needs no extra API key + small-sample validation + diff/log review
output -> copyable result + checklist + next iteration
} 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/docs/test.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-componentoutput 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 (Cucumber + Playwright under
e2e/) - User is only asking conceptual questions without code context
Quick Reference
Key Commands
Run these commands from web/. From the repository root, prefix them with pnpm -C web.
# 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.tsxinside a same-level__tests__/directory - Placement rule: Component, hook, and utility tests must live in a sibling
__tests__/folder at the same level as the source under test. For example,foo/index.tsxmaps tofoo/__tests__/index.spec.tsx, andfoo/bar.tsmaps tofoo/__tests__/bar.spec.ts. - 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:
- Analyze & Plan: List all files, order by complexity (simple → complex)
- Process ONE at a time: Write test → Run test → Fix if needed → Next
- 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:
- 🟢 Utility functions (simplest)
- 🟢 Custom hooks
- 🟡 Simple components (presentational)
- 🟡 Medium components (state, effects)
- 🔴 Complex components (API, routing)
- 🔴 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.mdfor 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
indexfile) - 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/*) or dify-ui primitives (@langgenius/dify-ui/*) - ❌ DO NOT mock sibling/child components in the same directory
See Test Structure Template for correct import/mock patterns.
nuqs Query State Testing (Required for URL State Hooks)
When a component or hook uses useQueryState / useQueryStates:
- ✅ Use
NuqsTestingAdapter(prefer shared helpers inweb/test/nuqs-testing.tsx) - ✅ Assert URL synchronization via
onUrlUpdate(searchParams,options.history) - ✅ For custom parsers (
createParser), keepparseandserializebijective and add round-trip edge cases (%2F,%25, spaces, legacy encoded values) - ✅ Verify default-clearing behavior (default values should be removed from URL when applicable)
- ⚠️ Only mock
nuqsdirectly when URL behavior is explicitly out of scope for the test
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 (
getByRolewith accessiblename,getByLabelText,getByPlaceholderText,getByText, and scopedwithin(...)) - Treat
getByTestIdas a last resort. If a control cannot be found by role/name, label, landmark, or dialog scope, fix the component accessibility first instead of adding or relying ondata-testid. - Remove production
data-testidattributes when semantic selectors can cover the behavior. Keep them only for non-visual mocked boundaries, editor/browser shims such as Monaco, canvas/chart output, or third-party widgets with no accessible DOM in the test environment. - Do not assert decorative icons by test id. Assert the named control that contains them, or mark decorative icons
aria-hidden. - 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)
- Rendering: Component renders without crashing
- Props: Required props, optional props, default values
- 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 practicesreferences/async-testing.md- Async operations and API callsreferences/domain-components.md- Workflow, Dataset, Configuration testingreferences/common-patterns.md- Frequently used testing patternsreferences/checklist.md- Test generation checklist and validation steps
Authoritative References
Primary Specification (MUST follow)
web/docs/test.md- The canonical testing specification. This skill is derived from this document.
Reference Examples in Codebase
web/utils/classnames.spec.ts- Utility function testsweb/app/components/base/radio/__tests__/index.spec.tsx- Component testsweb/__mocks__/provider-context.ts- Mock factory example
Project Configuration
web/vite.config.ts- Vite/Vitest configurationweb/vitest.setup.ts- Test environment setupweb/scripts/analyze-component.js- Component analysis tool- Modules are not mocked automatically. Global mocks live in
web/vitest.setup.ts(for examplereact-i18next,next/image); mock other modules likekyormimelocally in test files.
Decide Fit First
Design Intent
How To Use It
Boundaries And Review