Install
$ agentstack add skill-girijashankarj-cursor-handbook-test-data-factory ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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.
About
Skill: Test Data Factory
Create reusable, type-safe factory functions for generating test data with sensible defaults and easy overrides.
Trigger
When the user asks to create test data, mock data, fixtures, factories, or seed data for tests.
Prerequisites
- [ ] Entity/model to create factories for identified
- [ ] TypeScript interfaces or schema definitions available
- [ ] Testing framework known (Jest, Vitest, etc.)
Steps
Step 1: Identify Entities
- [ ] List all entities that need factories
- [ ] Identify relationships between entities (foreign keys, nested objects)
- [ ] Check existing factories in
tests/mocks/factories/to avoid duplicates
Step 2: Design Factory Structure
tests/mocks/factories/
├── index.ts # Re-exports all factories
├── user.factory.ts
├── order.factory.ts
├── product.factory.ts
└── helpers.ts # Shared helpers (randomId, timestamps, etc.)
Step 3: Create Helper Utilities
// tests/mocks/factories/helpers.ts
import { randomUUID } from 'crypto';
export const fakeId = () => randomUUID();
export const fakeDate = (daysAgo = 0) => {
const d = new Date();
d.setDate(d.getDate() - daysAgo);
return d.toISOString();
};
export const fakeMoney = (min = 1, max = 1000) =>
Math.round((Math.random() * (max - min) + min) * 100) / 100;
export const fakeEmail = (name = 'test') =>
`${name}-${Math.random().toString(36).slice(2, 8)}@example.com`;
export const pickRandom = (arr: T[]): T =>
arr[Math.floor(Math.random() * arr.length)];
Step 4: Create Entity Factory
Template for each entity:
// tests/mocks/factories/order.factory.ts
import { fakeId, fakeDate, fakeMoney } from './helpers';
interface Order {
id: string;
customerId: string;
status: 'PENDING' | 'CONFIRMED' | 'SHIPPED' | 'DELIVERED' | 'CANCELLED';
total: number;
items: OrderItem[];
createdAt: string;
updatedAt: string;
activeIndicator: boolean;
}
type OrderOverrides = Partial;
export function buildOrder(overrides: OrderOverrides = {}): Order {
return {
id: fakeId(),
customerId: fakeId(),
status: 'PENDING',
total: fakeMoney(10, 500),
items: [],
createdAt: fakeDate(),
updatedAt: fakeDate(),
activeIndicator: true,
...overrides,
};
}
export function buildOrders(count: number, overrides: OrderOverrides = {}): Order[] {
return Array.from({ length: count }, () => buildOrder(overrides));
}
// Pre-built scenarios
export const confirmedOrder = (overrides: OrderOverrides = {}) =>
buildOrder({ status: 'CONFIRMED', ...overrides });
export const cancelledOrder = (overrides: OrderOverrides = {}) =>
buildOrder({ status: 'CANCELLED', activeIndicator: false, ...overrides });
Step 5: Handle Relationships
// For entities with relationships:
export function buildOrderWithItems(
itemCount = 3,
overrides: OrderOverrides = {}
): Order {
const items = buildOrderItems(itemCount);
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
return buildOrder({ items, total, ...overrides });
}
Step 6: Create Database Fixtures (for integration tests)
// tests/mocks/factories/db-fixtures.ts
export async function seedTestUser(db: Database, overrides = {}) {
const user = buildUser(overrides);
await db.query(
'INSERT INTO users (id, email, name, created_at) VALUES ($1, $2, $3, $4)',
[user.id, user.email, user.name, user.createdAt]
);
return user;
}
export async function cleanupTestData(db: Database) {
await db.query('DELETE FROM order_items WHERE id LIKE $1', ['test-%']);
await db.query('DELETE FROM orders WHERE id LIKE $1', ['test-%']);
await db.query('DELETE FROM users WHERE id LIKE $1', ['test-%']);
}
Step 7: Create Index File
// tests/mocks/factories/index.ts
export * from './helpers';
export * from './user.factory';
export * from './order.factory';
export * from './product.factory';
Step 8: Validate
- [ ] Factories produce valid entities (pass schema validation)
- [ ] Overrides work correctly (custom values replace defaults)
- [ ] Batch creation works (
buildOrders(10)) - [ ] Scenario builders produce correct states
- [ ] No real PII in factory defaults (use fake data)
Rules
- ALWAYS use
buildprefix for factory functions (notcreate— reserve that for DB operations) - ALWAYS return plain objects (not class instances) for unit test factories
- ALWAYS make every field overridable via the overrides parameter
- NEVER use real PII — use fake emails (
@example.com), fake names, fake IDs - NEVER use
Math.random()for IDs — userandomUUID()or sequential IDs - Defaults should produce a valid entity that passes validation
- Use scenario builders for common test states (e.g.,
confirmedOrder(),adminUser()) - Separate in-memory factories (unit tests) from DB seed functions (integration tests)
Completion
Type-safe factories for all requested entities with helpers, scenarios, and index file. Ready to use in tests.
If a Step Fails
- No TypeScript interfaces: Infer from database schema or API response shapes
- Complex relationships: Start with leaf entities, build up to aggregates
- Faker.js dependency: Use lightweight helpers instead if project avoids large test deps
- Circular dependencies: Break cycle with lazy factory references or factory functions
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: girijashankarj
- Source: girijashankarj/cursor-handbook
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.