From Pragmatic Claude
Use when writing or reviewing JavaScript or TypeScript code and tests under the team engineering standards, especially when validating input or setting up mocks in a Jest or Vitest test.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pragmatic-claude:engineering-standards-javascriptThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Language-specific engineering standards for JavaScript and TypeScript, derived from the team's base standards. RFC 2119 keywords (MUST, SHOULD) carry their standard meanings.
Language-specific engineering standards for JavaScript and TypeScript, derived from the team's base standards. RFC 2119 keywords (MUST, SHOULD) carry their standard meanings.
REQUIRED BACKGROUND: engineering-standards owns the general rules (PR readiness, size, test types and requirements, the mocking philosophy, deployment). Read it first. This skill adds only the JS/TS specifics and never restates the base.
Prefer Zod schemas for validation and parsing over hand-written type guards, manual if checks, or casting with as. A schema is one source of truth: it validates at runtime and gives you the static type through z.infer, so the shape and the check can't drift.
Validate at the boundaries of the application. Parse untrusted or untyped data the moment it enters the app, then work with typed values inside. Boundaries include:
any or unknown: JSON.parse output, untyped DB rows, files read off disk.Use schema.parse(input) when a bad value should throw and fail fast at the edge, or schema.safeParse(input) when you want to handle the error path yourself. Never cast across a boundary (input as User): as is a compile-time assertion with no runtime check, so malformed data flows straight in.
import { z } from 'zod';
const CreateUser = z.object({
email: z.string().email(),
age: z.number().int().min(0),
});
type CreateUser = z.infer<typeof CreateUser>; // type derived from the schema
app.post('/users', (req, res) => {
const body = CreateUser.parse(req.body); // throws at the boundary on bad input
// body is typed CreateUser from here on
});
Prefer mockDeep for mocking objects, services, and interfaces. Use mockDeep<T>() from jest-mock-extended (Jest) or vitest-mock-extended (Vitest) instead of hand-written jest.fn() object literals or jest.mock() module mocks.
Why:
T, so a change to the real interface breaks the test at compile time instead of passing against a stale shape.client.user.findMany() works with no extra wiring.jest.fn(). The whole surface is mocked, and every call is a spy you can assert on.This is the base rule "spy on the interface and verify call parameters" made concrete: a mockDeep<T>() is the typed interface spy. Inject it (constructor or parameter) rather than jest.mock()-ing the module, per the base rule "prefer dependency injection over global mocking".
// Jest: 'jest-mock-extended' Vitest: 'vitest-mock-extended'
import { mockDeep, mockReset } from 'jest-mock-extended';
import type { OrderService } from './order-service';
const orders = mockDeep<OrderService>(); // fully typed, deep-mocked
beforeEach(() => mockReset(orders)); // fresh per test, no bleed
test('charges the customer once', async () => {
orders.payments.charge.mockResolvedValue({ id: 'ch_1', status: 'paid' });
await placeOrder(orders, cart); // inject the mock
expect(orders.payments.charge).toHaveBeenCalledWith(cart.total);
});
jest.fn() or vi.fn() is enough.jest.mock() or vi.mock() at the boundary.as instead of parsing it. The type says one thing, runtime does another. Parse at the boundary with Zod.interface and a separate runtime validator that drift apart. Derive the type from the schema with z.infer.jest.fn() per method. It drifts from the real type and rots silently. Use mockDeep<T>().mockReset in beforeEach: call counts and return values leak between tests.jest.mock() when the dependency could be injected. It's global, harder to read, and hides the seam.npx claudepluginhub igorjs/pragmatic-claude --plugin pragmatic-claudeCreates, edits, and verifies skills using a test-driven development approach with pressure scenarios and subagents.