agentleFS
gohypergiantgohypergiant/agent-skills/skills/accelint-ts-testing/AGENTS.md

agent-skills / accelint-ts-testing

AGENTS.md25 starsChanged 54 days agoApache-2.0View on GitHub

Note: This document is mainly for agents and LLMs to follow when maintaining, generating, or refactoring vitest tests. Humans may also find it useful, but guidance here is optimized for automation and consistency by AI-assisted workflows. Expert-level vitest testing guidance designed for AI agents and LLMs. Each rule includes one-line summaries here, with links to detailed examples in the references/ folder. Load reference files only when you need detailed implementation guidance for a specific rule. Token efficiency principle: This guide…

We split this AGENTS.md into the rules it gives an agent

35 rules. About 0 are common, 29 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈29

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Check for existing setup files: Before writing tests, look for setup files that configure global mocks and utilities

    line 19
  2. Distinctive:

    Before writing any tests, check if the file actually needs testing:

    line 28
  3. Distinctive:

    Verify mock cleanup is configured globally:

    line 35
  4. Distinctive:

    If not present, recommend adding them.

    line 43
  5. Distinctive:

    Check common locations for test setup configuration:

    line 46
  6. Very specific:

    Check vitest.config.ts for configured setupFiles and globalSetup

    line 49
  7. Distinctive:

    Test utilities and helpers

    line 55
  8. Distinctive:

    If global config handles mocks, DO NOT add manual mock cleanup:

    line 59
  9. Distinctive:

    Before marking any test file as "complete" or "done", verify type correctness:

    line 72
  10. Very specific:

    Why this matters: Test files are typically excluded from tsconfig.json compilation (not in include paths), so running tsc at the project …

    line 74
  11. Distinctive:

    Use the project's package manager to run TypeScript:

    line 91
  12. Distinctive:

    Test data with missing or incorrect properties

    line 108
  13. Very specific:

    Do NOT use as any or @ts-ignore to bypass type checking

    line 115
  14. Distinctive:

    Update test data to match actual types

    line 116
  15. Distinctive:

    Add proper type annotations where TypeScript cannot infer

    line 118
  16. Distinctive:

    If you encounter type errors, STOP and fix them - do not proceed with "I'll fix types later"

    line 119
  17. Distinctive:

    When reviewing existing test code (skill invoked with file path or user asks to "review tests" or "audit tests"), follow this systematic …

    line 144
  18. Distinctive:

    Always load property-based-testing.md during test audits to check for PBT opportunities.

    line 147
  19. Distinctive:

    Check for violations of rules in sections 1.1-1.10 below.

    line 150
  20. Distinctive:

    Pure transformation functions: No side effects, deterministic → Multiple properties may apply

    line 159
  21. Very specific:

    Check if fast-check is installed (package.json devDependencies)

    line 164
  22. Distinctive:

    If installed: Recommend PBT improvements directly

    line 165
  23. Distinctive:

    If NOT installed: Suggest PBT as an option with user approval required

    line 166
  24. Distinctive:

    Use assets/output-report-template.md and include PBT opportunities in a dedicated section.

    line 169
  25. Distinctive:

    Don't wait for users to ask "would any benefit from PBT?" — proactively identify and suggest PBT opportunities as part of every test audit.

    line 192
  26. Distinctive:

    Place test files next to implementation.

    line 199
  27. Very specific:

    Use it.each for variations.

    line 207
  28. Distinctive:

    Test negative cases, fault injection, and recovery thoroughly.

    line 211
  29. Very specific:

    Use strict assertions (toEqual, toStrictEqual) over loose ones.

    line 215
  30. Distinctive:

    Prefer fakes > stubs > spies/mocks.

    line 219
  31. Distinctive:

    Test promises, async/await, and timers correctly.

    line 223
  32. Distinctive:

    Keep tests fast through efficient setup and avoiding expensive operations.

    line 227
  33. Distinctive:

    Use coverage, watch mode, benchmarking, and other vitest-specific features.

    line 231
  34. Distinctive:

    Use snapshots for appropriate cases.

    line 235
  35. Distinctive:

    Use fast-check for stronger coverage with generated inputs.

    line 239

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Vitest Best Practices

Note: This document is mainly for agents and LLMs to follow when maintaining, generating, or refactoring vitest tests. Humans may also find it useful, but guidance here is optimized for automation and consistency by AI-assisted workflows.


Abstract

Expert-level vitest testing guidance designed for AI agents and LLMs. Each rule includes one-line summaries here, with links to detailed examples in the references/ folder. Load reference files only when you need detailed implementation guidance for a specific rule.

Token efficiency principle: This guide focuses on expert-level insights and non-obvious patterns. It assumes understanding of basic vitest concepts (describe, it, expect, vi) and focuses on decisions experts make: when to mock vs use real code, how to structure tests for maintainability, and performance optimization patterns.


How to Use This Guide

  1. Start here: Scan the rule summaries to identify relevant patterns
  2. Check for existing setup files: Before writing tests, look for setup files that configure global mocks and utilities
  3. Load references as needed: Click through to detailed examples only when implementing
  4. Progressive loading: Each reference file is self-contained with examples

This structure minimizes context usage while providing complete implementation guidance when needed.

Workflow: Before Writing Tests

0. Verify the file contains testable behavior Before writing any tests, check if the file actually needs testing:

  • Does it contain functions or logic? → Test it
  • Does it only export constants, types, or data? → Skip testing it

Files without behavior (constants files, type definitions, GLSL uniform declarations, pure data files) don't need tests. Testing expect(CONSTANT).toBe(value) provides no value and wastes CI time.

1. Check vitest.config.ts for global configuration Verify mock cleanup is configured globally:

// Look for these settings:
clearMocks: true      // Mock cleanup configured?
mockReset: true       // Mock reset configured?
restoreMocks: true    // Mock restore configured?

If not present, recommend adding them. This eliminates the entire class of mock cleanup errors.

2. Discover existing test setup files Check common locations for test setup configuration:

  • test/setup.{ts,js} or testing/setup.{ts,js}
  • vitest.setup.{ts,js} or src/test/setup.{ts,js}
  • Check vitest.config.ts for configured setupFiles and globalSetup

3. Analyze setup file contents When found, identify:

  • Global mocks (fetch, timers, etc.)
  • Custom matchers (e.g., @testing-library/jest-dom)
  • Test utilities and helpers
  • Environment configuration

4. Only add per-test cleanup for non-mock resources If global config handles mocks, DO NOT add manual mock cleanup:

  • ❌ Don't add vi.clearAllMocks() (handled by config)
  • ✅ Do clean up listeners, connections, custom state

Principle: Configuration over repetition Mock cleanup is a safety concern. Configure it once globally to make forgetting impossible. Manual cleanup in every test violates DRY and creates maintenance burden.

See vitest-features.md and performance.md for detailed examples.

Workflow: Before Marking Test Files Complete

CRITICAL: This workflow is MANDATORY. Never skip type checking test files.

Before marking any test file as "complete" or "done", verify type correctness:

Why this matters: Test files are typically excluded from tsconfig.json compilation (not in include paths), so running tsc at the project root won't catch type errors in tests. Type errors in tests can cause:

  • Runtime failures that should have been caught at compile time
  • Incorrect test behavior due to type mismatches
  • False confidence from tests that don't actually test what they claim

Verification steps:

  1. Navigate to the package directory (CRITICAL for monorepos): For monorepos or multi-package projects, you MUST cd into the specific package directory before running type checking. TypeScript needs to run from where the tsconfig.json and node_modules are located for that package.
# Example for monorepo:
cd packages/my-package
# Then run tsc from here
  1. Check test file directly with TypeScript: Use the project's package manager to run TypeScript:
# Detect which package manager to use:
# - npm: npm exec tsc -- --noEmit path/to/test.test.ts
# - pnpm: pnpm exec tsc --noEmit path/to/test.test.ts
# - bun: bunx tsc --noEmit path/to/test.test.ts
# - yarn: yarn exec tsc --noEmit path/to/test.test.ts

To detect the package manager, check for:

  • bun.lockb or bun.lock → use bunx
  • pnpm-lock.yaml → use pnpm exec
  • yarn.lock → use yarn exec
  • package-lock.json → use npm exec
  1. Look for common type issues:
  • Mock types not matching actual implementation types
  • Test data with missing or incorrect properties
  • Assertion types that don't match expected values
  • Missing type parameters on generic functions
  • Incorrect use of type guards or type assertions
  1. Fix all type errors before marking complete (NON-NEGOTIABLE) This step is MANDATORY, not optional. Type errors in tests are as critical as type errors in production code.
  • Do NOT use as any or @ts-ignore to bypass type checking
  • Update test data to match actual types
  • Fix mock return types to match implementation
  • Add proper type annotations where TypeScript cannot infer
  • If you encounter type errors, STOP and fix them - do not proceed with "I'll fix types later"

Example type errors to catch:

// ❌ Type error: property 'email' is missing
const user = createUser({ name: 'Alice' })

// ✅ Correct: all required properties provided
const user = createUser({ name: 'Alice', email: 'alice@example.com' })

// ❌ Type error: vi.fn() returns unknown, not User
const mockGetUser = vi.fn().mockReturnValue({ id: 1 })

// ✅ Correct: explicitly type the mock
const mockGetUser = vi.fn<() => User>().mockReturnValue({ id: 1, name: 'Alice', email: 'test@example.com' })

Principle: Type-safe tests prevent silent failures Type errors in tests are as critical as type errors in production code. Catch them before marking work complete.

CRITICAL REMINDER: This workflow is NOT optional. Running tsc --noEmit against test files is a REQUIRED step before marking test work as complete. If you skip this step, you risk shipping broken tests that provide false confidence.

Workflow: Test Code Review/Audit

When reviewing existing test code (skill invoked with file path or user asks to "review tests" or "audit tests"), follow this systematic approach:

1. Load property-based-testing.md for pattern detection Always load property-based-testing.md during test audits to check for PBT opportunities.

2. Identify anti-patterns and violations Check for violations of rules in sections 1.1-1.10 below.

3. Check for property-based testing opportunities For each test file, analyze the code under test and identify high-value PBT patterns:

ALWAYS check for these patterns:

  • Encode/decode pairs: Functions like encode()/decode(), serialize()/deserialize(), toJSON()/fromJSON() → Suggest roundtrip property
  • Normalization functions: normalize(), sanitize(), format() → Suggest idempotence property
  • Validator + normalizer pairs: isValid() + normalize() → Suggest "isValid(normalize(x)) always true"
  • Pure transformation functions: No side effects, deterministic → Multiple properties may apply
  • Sorting/ordering functions: sort(), compare() → Suggest ordering + idempotence properties
  • Data structure operations: Custom collections with invariants → Suggest invariant properties

When identifying PBT opportunities:

  • Check if fast-check is installed (package.json devDependencies)
  • If installed: Recommend PBT improvements directly
  • If NOT installed: Suggest PBT as an option with user approval required

4. Generate report using template Use assets/output-report-template.md and include PBT opportunities in a dedicated section.

Example PBT opportunity detection:

// Code under test:
function get<T>(obj: Record<string, T>, path: string): T | undefined

// Example-based test found:
it('gets nested value', () => {
  expect(get({ a: { b: 1 } }, 'a.b')).toBe(1)
})

// PBT opportunity identified:
// ✅ EXCELLENT CANDIDATE for property-based testing
// Pattern: Pure function with clear invariants
// Properties to test:
// 1. get(obj, path) returns undefined for non-existent paths
// 2. get(obj, path) preserves type (type preservation)
// 3. get(obj, path) never throws on valid inputs

Principle: Proactive improvement suggestions Don't wait for users to ask "would any benefit from PBT?" — proactively identify and suggest PBT opportunities as part of every test audit.


1. General

1.1 Organization

Place test files next to implementation; one test file per module. View detailed examples

1.2 AAA Pattern

Structure tests as Arrange, Act, Assert for clarity. View detailed examples

1.3 Parameterized Tests

Use it.each for variations; one behavior per test. View detailed examples

1.4 Error Handling

Test negative cases, fault injection, and recovery thoroughly. View detailed examples

1.5 Assertions

Use strict assertions (toEqual, toStrictEqual) over loose ones. View detailed examples

1.6 Test Doubles

Prefer fakes > stubs > spies/mocks; avoid over-mocking. View detailed examples

1.7 Async Testing

Test promises, async/await, and timers correctly. View detailed examples

1.8 Performance

Keep tests fast through efficient setup and avoiding expensive operations. View detailed examples

1.9 Vitest Features

Use coverage, watch mode, benchmarking, and other vitest-specific features. View detailed examples

1.10 Snapshot Testing

Use snapshots for appropriate cases; avoid common pitfalls. View detailed examples

1.11 Property-Based Testing

Use fast-check for stronger coverage with generated inputs; test encode/decode pairs, validators, normalizers, and invariants. View detailed examples

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.