AgentStack
SKILL verified MIT Self-run

Jest Test

skill-agentcto-claude-skills-jest-test · by AgentCTO

>

No reviews yet
0 installs
4 views
0.0% view→install

Install

$ agentstack add skill-agentcto-claude-skills-jest-test

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Jest Test? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Jest Test

Write, review, and improve Jest tests following production-quality patterns and best practices for TypeScript and JavaScript projects.

Before starting, consult [references/jest-guide.xml](references/jest-guide.xml) -- a comprehensive playbook covering core principles, the full matcher catalog, async testing patterns, mocking strategies, data-driven tests, error handling, anti-patterns, and CI/CD integration. Reference it throughout the workflow.

Workflow Overview

Analyze --> Plan --> Write Tests --> Review
    ^                    |             |
    +---- Revise --------+             |
                         +-- Fix ------+

Follow steps 1-4 in order. If the user provides existing tests for review, skip to Step 4.

Step 1: Analyze

Read the source code to understand what needs testing. Identify:

  • Functions and methods -- Public API surface that needs coverage
  • Dependencies -- External modules, services, or APIs that need mocking (see `` in jest-guide.xml)
  • Async operations -- Promises, async/await, callbacks that need special handling (see ``)
  • Edge cases -- Error paths, boundary values, null/undefined inputs
  • State management -- Setup/teardown needs for consistent test state

If the user provides a file path, read it. If they describe functionality without providing code, ask them to share the relevant source files.

Step 2: Plan

Determine the test strategy before writing code. Decide:

What to test:

  • Test behavior, not implementation details (see `` in jest-guide.xml)
  • Cover the happy path, error paths, and edge cases
  • Prioritize public API surface over internal helpers

Test organization (see `` for structure templates):

  • One describe block per function, class, or logical grouping
  • Descriptive test names that read as specifications: 'should return empty array when no items match filter'
  • Group related tests with nested describe blocks

Mocking strategy (see `` for the full pattern catalog):

  • Mock external dependencies (APIs, databases, file system)
  • Mock expensive operations (network calls, heavy computation)
  • Do NOT mock the unit under test
  • Use jest.spyOn when you need to verify calls while keeping the original behavior

Coverage goals (see ` in `):

  • Services: 98% across all metrics
  • Repositories/data access: 95%
  • Utilities: 90%
  • Global minimum: 95% statements, branches, functions, lines

Step 3: Write Tests

Generate tests following the patterns in jest-guide.xml. Apply these rules consistently:

Test structure

Every test file follows this skeleton:

import { ServiceUnderTest } from '../service-under-test';

// Mock dependencies at the top
jest.mock('../dependency-module');

describe('ServiceUnderTest', () => {
  let service: ServiceUnderTest;
  let mockDependency: jest.Mocked;

  beforeEach(() => {
    // Arrange: fresh instance and mocks for each test
    mockDependency = new DependencyModule() as jest.Mocked;
    service = new ServiceUnderTest(mockDependency);
  });

  afterEach(() => {
    jest.clearAllMocks();
    jest.restoreAllMocks();
  });

  describe('methodName', () => {
    test('should return expected result for valid input', async () => {
      // Arrange
      mockDependency.fetch.mockResolvedValue(testData);
      // Act
      const result = await service.methodName(input);
      // Assert
      expect(result).toEqual(expected);
    });

    test('should throw when dependency fails', async () => {
      // Arrange
      mockDependency.fetch.mockRejectedValue(new Error('Network error'));
      // Act & Assert
      await expect(service.methodName(input)).rejects.toThrow('Network error');
    });
  });
});

Choosing matchers

Select the right matcher from `` in jest-guide.xml:

| Scenario | Matcher | Why | |----------|---------|-----| | Primitive comparison | toBe() | Strict === equality | | Object/array comparison | toEqual() | Deep equality, ignores undefined | | Strict object comparison | toStrictEqual() | Includes undefined properties | | Partial object match | toMatchObject() | Only checks specified keys | | Array contains item | toContain() (primitives) / toContainEqual() (objects) | Subset checking | | Floating point | toBeCloseTo() | Avoids precision errors | | Error thrown | toThrow() | Wrap in expect(() => ...) for sync |

Async tests

All async tests must include assertion counting (see ``):

test('async operation', async () => {
  expect.assertions(1); // Prevents false positives
  const result = await service.fetchData();
  expect(result).toBeDefined();
});

For error cases, use .rejects:

test('rejects on failure', async () => {
  expect.assertions(1);
  await expect(service.fetchData()).rejects.toThrow('Network error');
});

Mock cleanup

Always clean up mocks (see ` in `):

afterEach(() => {
  jest.clearAllMocks();   // Reset call history
  jest.restoreAllMocks(); // Restore original implementations
});

Data-driven tests

Use test.each for parameterized tests (see ``):

test.each([
  ['valid@email.com', true],
  ['invalid', false],
  ['', false],
])('validates email "%s" as %s', (email, expected) => {
  expect(isValidEmail(email)).toBe(expected);
});

Forbidden patterns

Never include any of the patterns listed in `` in jest-guide.xml:

  • No .only or .skip -- these break CI
  • No empty test bodies -- every test must have assertions
  • No real timers -- use jest.useFakeTimers() (see ``)
  • No unhandled async -- always await and use expect.assertions()

Step 4: Review

Audit tests (generated or user-provided) against the reference. Check each area and report findings.

Anti-pattern scan

Check against every item in `` in jest-guide.xml:

  • [ ] Tests verify behavior, not implementation details
  • [ ] Mocks are cleaned up in afterEach
  • [ ] No real setTimeout/setInterval -- fake timers used instead
  • [ ] All async operations are properly awaited
  • [ ] No .only, .skip, or .todo in committed code

Async safety

  • [ ] Every async test has expect.assertions(n) or expect.hasAssertions()
  • [ ] Promise rejections are tested with .rejects.toThrow()
  • [ ] No floating promises (async calls without await)

Mock hygiene

  • [ ] afterEach includes jest.clearAllMocks() and/or jest.restoreAllMocks()
  • [ ] Mocks are scoped to the narrowest level needed
  • [ ] jest.spyOn used when original behavior should be preserved
  • [ ] Module mocks use jest.mock() at the top of the file (hoisting)

Coverage and completeness

  • [ ] Happy path covered for all public methods
  • [ ] Error paths tested (rejected promises, thrown exceptions)
  • [ ] Edge cases covered (empty inputs, null/undefined, boundary values)
  • [ ] Coverage meets thresholds from ``

CI readiness

Check against `` quality gates:

  • [ ] No .only / .skip / .todo
  • [ ] No console.log statements in test files
  • [ ] Coverage thresholds configured and met
  • [ ] All async tests have assertion counts

Present review results as a checklist with pass/fail and specific fix recommendations.

Examples

Example 1: Writing tests for a service

User says: "Write tests for this UserService"

Actions:

  1. Read the UserService source to identify methods, dependencies, and async operations
  2. Plan: mock the UserRepository dependency, test CRUD methods, cover error paths
  3. Generate a complete test file with describe/test blocks, proper mocking, async handling, and assertion counting
  4. Verify no anti-patterns, all async tests have expect.assertions(), mocks cleaned up in afterEach

Result: A complete user-service.test.ts file with tests for each public method, mocked dependencies, error path coverage, and proper cleanup.

Example 2: Reviewing existing tests

User says: "Review my test file for issues"

Actions:

  1. Skip to Step 4 (Review)
  2. Scan for anti-patterns: implementation testing, missing mock cleanup, real timers, unhandled async
  3. Check async safety: assertion counts, proper await, rejects handling
  4. Check mock hygiene: cleanup in afterEach, proper scoping
  5. Present findings with specific line references and fixes

Result: A review report like:

  • FAIL: Line 15 -- missing expect.assertions() in async test
  • FAIL: Line 42 -- setTimeout used instead of fake timers
  • WARN: No afterEach cleanup -- mock state may leak between tests
  • PASS: All tests verify behavior, not implementation
  • RECOMMENDATION: Add test.each for the repetitive validation tests on lines 60-90

Example 3: Mocking guidance

User says: "How do I mock this external API client?"

Actions:

  1. Read the source to understand the API client's interface
  2. Show the relevant mocking pattern from `` in jest-guide.xml
  3. Provide a concrete example using jest.mock() for the module and mockResolvedValue / mockRejectedValue for async methods
  4. Include cleanup pattern

Result: A focused code snippet showing module mock setup, typed mocks, return value configuration, and cleanup -- ready to paste into the test file.

Troubleshooting

Issue: Tests pass locally but fail in CI

Cause: Test order dependency -- a mock or state from one test leaks into another. Tests run in a different order in CI. Solution: Add afterEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); }) to every describe block. Run locally with --runInBand to reproduce order-dependent failures. Check for shared mutable state outside of beforeEach.

Issue: Mock is not being used (original function still runs)

Cause: jest.mock() calls are hoisted to the top of the file, but the mock path may not match the import path exactly. Or jest.doMock() was used without a subsequent dynamic require(). Solution: Ensure the path in jest.mock('path') exactly matches the import statement. For aliased paths (@/services/...), verify moduleNameMapper in Jest config. Check that the mock is defined before the module-under-test is imported.

Issue: Async test times out

Cause: A promise is never resolved or rejected, or done() is never called in a callback-style test. Solution: Check that all async operations are properly awaited. For callback tests, ensure done() is called in both success and error paths (wrap in try/catch). Add expect.assertions(n) to catch silent non-execution. Increase timeout if the operation is legitimately slow: test('slow op', async () => {...}, 10000).

Issue: Coverage threshold not met

Cause: Uncovered branches (often error paths, default switch cases, or early returns). Solution: Run jest --coverage and inspect the HTML report at coverage/lcov-report/index.html. Look for red-highlighted lines -- these are uncovered. Common gaps: catch blocks, null checks, default cases in switch statements. Add targeted tests for each uncovered branch.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.