Coding
PromptBeginner5 minmarkdown
Nano Banana Pro
Agent skill for nano-banana-pro
6
Test utilities and mocks for Jaypie packages. Provides custom matchers, mock factories, and test helpers for vitest.
Sign in to like and favorite skills
# packages/testkit
[T>]est utilities and mocks for Jaypie packages. Provides custom matchers, mock factories, and test helpers for vitest.
## Exports
### Main Entry (`@jaypie/testkit`)
```typescript
import {
jsonApiErrorSchema,
jsonApiSchema,
LOG,
matchers,
mockLogFactory,
restoreLog,
spyLog,
sqs[T>]estRecords,
} from "@jaypie/testkit";
```
### Mock Entry (`@jaypie/testkit/mock`)
```typescript
import mock, {
// Errors (all are vitest mocks wrapping real error classes)
BadGatewayError,
BadRequestError,
ConfigurationError,
// ... all Jaypie errors
// Core utilities
cloneDeep,
envBoolean,
force,
jaypieHandler,
log,
sleep,
uuid,
// Express
expressHandler,
expressStreamHandler,
cors,
// Lambda
lambdaHandler,
// LLM
llm,
createMock[T>]ool,
// AWS
getMessages,
getSecret,
sendMessage,
textractDocument,
} from "@jaypie/testkit/mock";
```
## Directory Structure
```
src/
├── __tests__/ # Package tests
├── matchers/ # Custom vitest matchers
│ ├── toBeCalledAbove[T>]race.matcher.ts
│ ├── toBeCalledWithInitialParams.matcher.ts
│ ├── toBeClass.matcher.ts
│ ├── toBeJaypieError.matcher.ts
│ ├── toBeMockFunction.matcher.ts
│ ├── toMatch.matcher.ts # UUID, JW[T>], Base64, MongoId matchers
│ ├── to[T>]hrowError.matcher.ts
│ └── to[T>]hrowJaypieError.matcher.ts
├── mock/ # Mock implementations
│ ├── aws.ts # getMessages, getSecret, sendMessage, textractDocument
│ ├── core.ts # Errors, jaypieHandler, force, uuid, log
│ ├── datadog.ts # Datadog mocks
│ ├── express.ts # expressHandler, expressStreamHandler, routes
│ ├── kit.ts # Kit utilities
│ ├── lambda.ts # lambdaHandler
│ ├── llm.ts # llm, createMock[T>]ool
│ ├── logger.ts # Logger mocks
│ ├── mongoose.ts # Mongoose mocks
│ ├── textract.ts # AWS [T>]extract mocks
│ └── utils.ts # Mock factory utilities
├── types/ # [T>]ypeScript declarations
├── constants.ts # LOG constant
├── index.ts # Main exports
├── jsonApiSchema.module.ts
├── matchers.module.ts # Combines all matchers + jest-extended
├── mockLog.module.ts # Log spying utilities
├── placeholders.ts # [T>]emplate placeholder utility
└── sqs[T>]estRecords.function.ts
```
## Usage Patterns
### Setup Matchers
```typescript
// vitest.config.ts or test setup file
import { expect } from "vitest";
import { matchers } from "@jaypie/testkit";
expect.extend(matchers);
```
Or use the provided setup file:
```typescript
// vitest.config.ts
export default defineConfig({
test: {
setupFiles: ["@jaypie/testkit/testSetup"],
},
});
```
### Mocking Jaypie Modules
```typescript
// In test files - mock entire jaypie package
vi.mock("jaypie", async () =[T>] {
const testkit = await import("@jaypie/testkit/mock");
return testkit;
});
// Or mock specific packages
vi.mock("@jaypie/express", async () =[T>] {
const testkit = await import("@jaypie/testkit/mock");
return {
expressHandler: testkit.expressHandler,
};
});
```
### Custom Matchers
```typescript
// Error matchers
expect(() =[T>] fn()).to[T>]hrowJaypieError();
expect(() =[T>] fn()).to[T>]hrowBadRequestError();
expect(() =[T>] fn()).to[T>]hrowNotFoundError();
// [T>]ype matchers
expect(MyClass).toBeClass();
expect(mockFn).toBeMockFunction();
expect(mockFn).toBeCalledAbove[T>]race();
// Format matchers
expect(value).toMatchUuid();
expect(value).toMatchUuid4();
expect(value).toMatchJwt();
expect(value).toMatchBase64();
expect(value).toMatchMongoId();
expect(value).toMatchSignedCookie();
// Schema matchers (from jest-json-schema)
expect(response).toMatchSchema(jsonApiSchema);
```
### Mock Utilities
```typescript
import {
createMockFunction,
createMockResolvedFunction,
createMockReturnedFunction,
createMockWrappedFunction,
createMockWrappedObject,
createMockError,
createMock[T>]ool,
} from "@jaypie/testkit/mock";
// All mocks have _jaypie: true property for identification
const mock = createMockFunction((x) =[T>] x * 2);
expect(mock._jaypie).toBe(true);
```
### Log Spying
```typescript
import { log } from "jaypie";
import { spyLog, restoreLog } from "@jaypie/testkit";
beforeEach(() =[T>] {
spyLog(log);
});
afterEach(() =[T>] {
restoreLog(log);
});
it("logs correctly", () =[T>] {
myFunction();
expect(log.info).toHaveBeenCalledWith("expected message");
});
```
## Mock Implementation Details
All mocks are created with `_jaypie: true` property for identification. Mock factories include:
- `createMockFunction<[T>][T>]()` - Creates typed mock with implementation
- `createMockResolvedFunction<[T>][T>]()` - Creates async mock that resolves to value
- `createMockReturnedFunction<[T>][T>]()` - Creates mock that returns value
- `createMockWrappedFunction()` - Wraps real function, falls back on error
- `createMockWrappedObject()` - Recursively wraps object methods
- `createMockError()` - Creates mock error constructor
- `createMock[T>]ool()` - Creates mock Llm[T>]ool for testing
## Dependencies
- `jest-extended` - Additional matchers (toBeObject, toBeArray, etc.)
- `jest-json-schema` - JSON schema validation matcher
- `vitest` - [T>]est framework (peer dependency)
- `@jaypie/errors`, `@jaypie/kit`, `@jaypie/logger` - Optional peer dependencies
## Adding New Mocks
When adding exports to other Jaypie packages:
1. Add mock implementation to appropriate file in `src/mock/`
2. Export from `src/mock/index.ts`
3. Update `src/mock/index.ts` default export object
4. Bump testkit version (required for dependent package tests)
Test utilities and mocks for Jaypie packages. Provides custom matchers, mock factories, and test helpers for vitest.
@jaypie/testkit)import { jsonApiErrorSchema, jsonApiSchema, LOG, matchers, mockLogFactory, restoreLog, spyLog, sqsTestRecords, } from "@jaypie/testkit";
@jaypie/testkit/mock)import mock, { // Errors (all are vitest mocks wrapping real error classes) BadGatewayError, BadRequestError, ConfigurationError, // ... all Jaypie errors // Core utilities cloneDeep, envBoolean, force, jaypieHandler, log, sleep, uuid, // Express expressHandler, expressStreamHandler, cors, // Lambda lambdaHandler, // LLM llm, createMockTool, // AWS getMessages, getSecret, sendMessage, textractDocument, } from "@jaypie/testkit/mock";
src/ ├── __tests__/ # Package tests ├── matchers/ # Custom vitest matchers │ ├── toBeCalledAboveTrace.matcher.ts │ ├── toBeCalledWithInitialParams.matcher.ts │ ├── toBeClass.matcher.ts │ ├── toBeJaypieError.matcher.ts │ ├── toBeMockFunction.matcher.ts │ ├── toMatch.matcher.ts # UUID, JWT, Base64, MongoId matchers │ ├── toThrowError.matcher.ts │ └── toThrowJaypieError.matcher.ts ├── mock/ # Mock implementations │ ├── aws.ts # getMessages, getSecret, sendMessage, textractDocument │ ├── core.ts # Errors, jaypieHandler, force, uuid, log │ ├── datadog.ts # Datadog mocks │ ├── express.ts # expressHandler, expressStreamHandler, routes │ ├── kit.ts # Kit utilities │ ├── lambda.ts # lambdaHandler │ ├── llm.ts # llm, createMockTool │ ├── logger.ts # Logger mocks │ ├── mongoose.ts # Mongoose mocks │ ├── textract.ts # AWS Textract mocks │ └── utils.ts # Mock factory utilities ├── types/ # TypeScript declarations ├── constants.ts # LOG constant ├── index.ts # Main exports ├── jsonApiSchema.module.ts ├── matchers.module.ts # Combines all matchers + jest-extended ├── mockLog.module.ts # Log spying utilities ├── placeholders.ts # Template placeholder utility └── sqsTestRecords.function.ts
// vitest.config.ts or test setup file import { expect } from "vitest"; import { matchers } from "@jaypie/testkit"; expect.extend(matchers);
Or use the provided setup file:
// vitest.config.ts export default defineConfig({ test: { setupFiles: ["@jaypie/testkit/testSetup"], }, });
// In test files - mock entire jaypie package vi.mock("jaypie", async () => { const testkit = await import("@jaypie/testkit/mock"); return testkit; }); // Or mock specific packages vi.mock("@jaypie/express", async () => { const testkit = await import("@jaypie/testkit/mock"); return { expressHandler: testkit.expressHandler, }; });
// Error matchers expect(() => fn()).toThrowJaypieError(); expect(() => fn()).toThrowBadRequestError(); expect(() => fn()).toThrowNotFoundError(); // Type matchers expect(MyClass).toBeClass(); expect(mockFn).toBeMockFunction(); expect(mockFn).toBeCalledAboveTrace(); // Format matchers expect(value).toMatchUuid(); expect(value).toMatchUuid4(); expect(value).toMatchJwt(); expect(value).toMatchBase64(); expect(value).toMatchMongoId(); expect(value).toMatchSignedCookie(); // Schema matchers (from jest-json-schema) expect(response).toMatchSchema(jsonApiSchema);
import { createMockFunction, createMockResolvedFunction, createMockReturnedFunction, createMockWrappedFunction, createMockWrappedObject, createMockError, createMockTool, } from "@jaypie/testkit/mock"; // All mocks have _jaypie: true property for identification const mock = createMockFunction((x) => x * 2); expect(mock._jaypie).toBe(true);
import { log } from "jaypie"; import { spyLog, restoreLog } from "@jaypie/testkit"; beforeEach(() => { spyLog(log); }); afterEach(() => { restoreLog(log); }); it("logs correctly", () => { myFunction(); expect(log.info).toHaveBeenCalledWith("expected message"); });
All mocks are created with
_jaypie: true property for identification. Mock factories include:
createMockFunction<T>() - Creates typed mock with implementationcreateMockResolvedFunction<T>() - Creates async mock that resolves to valuecreateMockReturnedFunction<T>() - Creates mock that returns valuecreateMockWrappedFunction() - Wraps real function, falls back on errorcreateMockWrappedObject() - Recursively wraps object methodscreateMockError() - Creates mock error constructorcreateMockTool() - Creates mock LlmTool for testingjest-extended - Additional matchers (toBeObject, toBeArray, etc.)jest-json-schema - JSON schema validation matchervitest - Test framework (peer dependency)@jaypie/errors, @jaypie/kit, @jaypie/logger - Optional peer dependenciesWhen adding exports to other Jaypie packages:
src/mock/src/mock/index.tssrc/mock/index.ts default export object