cypress-test-data-generator
v2.1.1
Published
Cypress plugin for generating test data using Faker
Maintainers
Readme
Cypress Test Data Generator
Generate realistic, reproducible test data for Cypress tests
Installation • Quick Start • Scenarios • Mocking • CLI • Schemas • Generators
Why This Plugin?
Writing realistic test data by hand is tedious and error-prone. This plugin provides 40+ data generators powered by Faker.js plus the Cypress-native wiring to use them without boilerplate.
// Before: manual test data
const user = { name: 'Test User', email: '[email protected]', age: 25 };
// After: rich, realistic, reproducible
cy.generateUser({ seed: 42 }).then((user) => {
// { id, firstName, lastName, email, age, address: { street, city, state, zipCode, country } }
});Key Features
- 40+ Generators — Users, products, orders, invoices, social profiles, and more
- Relational scenarios —
cy.scenario({ users, ordersPerUser, productsPerOrder })returns linked entities with guaranteed foreign keys (no manual ID wiring) - One-line API mocking —
cy.mockApi('/api/users', { generator: 'generateUser', count: 20, paginated: true })replaces ~15 lines ofcy.interceptboilerplate - Native Cypress commands —
cy.generateUser(),cy.scenario(),cy.mockApi(), and 40+ more, chainable and aliasable ctdgCLI — generate fixtures outside Cypress (npx ctdg generateUser --count 1000 --seed 42 -o users.json)- Runtime Zod schemas — validate real API responses against the exact shape the generator produces
- Reproducible Data — seed support, with hermetic per-call Faker instances that never leak state between calls
- Internationalization — 10 built-in locales (en, de, fr, es, it, pt_BR, ja, zh_CN, ko, ru) with automatic fallback to
enfor unknown codes - Fully typed — TypeScript definitions shipped for every generator, option, and return shape
Installation
npm install --save-dev cypress-test-data-generator
# Optional: install zod only if you plan to use the schemas subpath
npm install --save-dev zodSetup
1. Register the tasks in cypress.config.js:
const { defineConfig } = require('cypress');
const dataGenerator = require('cypress-test-data-generator');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
dataGenerator.registerTasks(on, config);
return config;
},
},
});2. Load the native Cypress commands in cypress/support/e2e.js:
import 'cypress-test-data-generator/commands';That's it. You now have cy.generateUser(), cy.scenario(), cy.mockApi(), and 40+ other chainable commands available in every spec.
Quick Start
// Native Cypress commands — chainable, aliasable, fully typed
cy.generateUser({ seed: 12345, locale: 'de' }).as('user');
cy.get('@user').then((user) => {
cy.visit('/register');
cy.get('#email').type(user.email);
});
// Relational data — one call, full FK integrity
cy.scenario({ users: 3, ordersPerUser: 2, productsPerOrder: 4 }).then((s) => {
// s.orders[0].userId === s.users[i].id for some i
// s.orders[0].products are real entries from s.products
// s.orders[0].shippingAddress === the user's address
});
// Kill cy.intercept boilerplate — one line mocks an endpoint with generated data
cy.mockApi('/api/users', {
generator: 'generateUser',
count: 20,
paginated: true, // wraps in { data, meta } envelope
seed: 42,
}).as('users');
cy.visit('/users');
cy.wait('@users');
// Raw cy.task still works if you prefer
cy.task('generateProduct', { seed: 1 });Relational Scenarios — cy.scenario()
Instead of manually wiring IDs between generateUser/generateOrder/generateReview calls, generate a linked bundle in one shot:
cy.scenario({
users: 3, // 3 users
ordersPerUser: 2, // 6 orders total, each tied to a user
productsPerOrder: 4, // each order contains 4 products from a shared catalog
reviewsPerProduct: 1, // each product gets 1 review by a random user
seed: 42, // reproducible
}).then(({ users, products, orders, reviews }) => {
// Foreign keys are guaranteed:
// order.userId → real users[i].id
// order.shippingAddress → users[i].address
// order.products[] → entries from the shared `products` catalog
// review.productId → real products[i].id
// review.userId → real users[i].id
});API Mocking — cy.mockApi()
One line replaces ~15 lines of cy.intercept + fixture + pagination boilerplate.
// Basic list endpoint
cy.mockApi('/api/users', { generator: 'generateUser', count: 20 });
// Paginated
cy.mockApi('/api/products', {
generator: 'generateProduct',
count: 10,
paginated: true,
page: 1,
pageSize: 10,
total: 247,
});
// → { data: [...10 products], meta: { page, pageSize, total, totalPages } }
// Error case
cy.mockApi('/api/users/999', { status: 404, body: { error: 'not found' } });
// Relational bundle
cy.mockApi('/api/bootstrap', { scenario: { users: 3, ordersPerUser: 2 } });
// Transform before serving
cy.mockApi('/api/suggestions', {
generator: 'generateProduct',
count: 50,
transform: (items) => items.slice(0, 3).map((p) => p.name),
});All options: method, generator, count, seed, locale, paginated, page, pageSize, total, status, headers, delay, body, scenario, transform.
Outside Cypress — the ctdg CLI
The plugin ships a ctdg binary so you can generate deterministic test data outside Cypress — for Jest, Playwright, Storybook, local dev seeding, CI bootstrap scripts, or anywhere you need realistic fixtures.
# A single user
npx ctdg generateUser --seed 42 --pretty
# 1000 products as an array, written to a file
npx ctdg generateProduct --count 1000 --seed 1 -o fixtures/products.json
# Newline-delimited JSON — great for piping into tools
npx ctdg generateUser --count 500 --format jsonl > users.jsonl
# Relational bundle
npx ctdg generateScenario \
--users 3 --ordersPerUser 2 --productsPerOrder 4 --reviewsPerProduct 1 \
--seed 42 -o fixtures/scenario.json
# Localized
npx ctdg generateUser --locale de --count 10
# Discover what's available
npx ctdg --list
npx ctdg --helpUse it in a package.json script to bake fixtures as part of your build:
{
"scripts": {
"fixtures:generate": "ctdg generateScenario --users 50 --ordersPerUser 5 --seed 1 -o src/__fixtures__/scenario.json"
}
}Available Generators
| Generator | Description |
|-----------|-------------|
| generateUser | Complete user profile with address and preferences |
| generateAddress | Standalone address with coordinates |
| Generator | Description |
|-----------|-------------|
| generateProduct | Product with SKU, pricing, stock status |
| generateProductWithRelations | Product with related products |
| generateOrder | Order with products and shipping |
| generateReview | Product review with rating |
| generateCategory | Category with hierarchy support |
| generateCart | Shopping cart with items |
| generateWishlist | User wishlist |
| generateReturn | Return/refund request |
| generateInventory | Product inventory |
| generateCoupon | Discount coupon |
| generateShippingMethod | Shipping option |
| generatePaymentMethod | Payment method |
| Generator | Description |
|-----------|-------------|
| generateSocialProfile | Social media profile (Twitter, Instagram, etc.) |
| generateComment | Comment with replies support |
| generateNotification | App notification |
| generateMessage | Chat/direct message |
| Generator | Description |
|-----------|-------------|
| generateCompany | Company with industry and revenue |
| generateInvoice | Invoice with line items |
| generateEmployee | Employee with department and salary |
| generateProject | Project with team and milestones |
| generateTicket | Support ticket |
| generateMeeting | Meeting with attendees |
| generateJobListing | Job posting |
| Generator | Description |
|-----------|-------------|
| generateBankAccount | Bank account with balance |
| generateLoan | Loan with terms and payments |
| generateInsurancePolicy | Insurance policy |
| generateCreditCard | Credit card details |
| generateTransaction | Financial transaction |
| generateSubscription | Subscription plan |
| Generator | Description |
|-----------|-------------|
| generateBlogPost | Blog post with SEO metadata |
| generateEvent | Event with tickets and speakers |
| Generator | Description |
|-----------|-------------|
| generateTravelItinerary | Travel plan with flights and hotels |
| generateVehicle | Vehicle with specifications |
| Generator | Description |
|-----------|-------------|
| generateProperty | Property listing with agent info |
| Generator | Description |
|-----------|-------------|
| generateRestaurant | Restaurant with hours and features |
| generateMenuItem | Menu item with nutrition info |
| generateFoodOrder | Food delivery order |
| Generator | Description |
|-----------|-------------|
| generateApiResponse | API response with pagination |
| generateLogEntry | Application log entry |
| Generator | Description |
|-----------|-------------|
| generateMedicalRecord | Medical record |
| generateEducation | Education record |
Usage Examples
E-commerce Testing
describe('Shopping Flow', () => {
it('completes checkout with generated data', () => {
cy.task('generateProduct').then((product) => {
cy.task('generateCart', { itemCount: 3 }).then((cart) => {
cy.task('generateUser').then((user) => {
// Use generated data in your test
expect(cart.items).to.have.length(3);
expect(cart.total).to.be.greaterThan(0);
});
});
});
});
it('displays order history', () => {
cy.task('generateOrder', { productCount: 5 }).then((order) => {
expect(order.products).to.have.length(5);
const sum = order.products.reduce((acc, p) => acc + p.price, 0);
// totalAmount is rounded to 2 decimals, so compare with tolerance.
expect(order.totalAmount).to.be.closeTo(sum, 0.01);
});
});
});Business Application Testing
describe('Invoice Management', () => {
it('creates invoice with line items', () => {
cy.task('generateInvoice', { itemCount: 5 }).then((invoice) => {
expect(invoice.invoiceNumber).to.match(/^INV-\d{6}$/);
expect(invoice.items).to.have.length(5);
expect(invoice.total).to.be.greaterThan(invoice.subtotal); // Includes tax
});
});
});
describe('Employee Directory', () => {
it('filters by department', () => {
cy.task('generateEmployee', { department: 'Engineering' }).then((emp) => {
expect(emp.department).to.equal('Engineering');
expect(emp.employeeId).to.match(/^EMP-\d{6}$/);
});
});
});Social Features Testing
describe('Social Feed', () => {
it('displays user notifications', () => {
cy.task('generateNotification', { type: 'payment' }).then((notif) => {
expect(notif.type).to.equal('payment');
expect(notif.priority).to.be.oneOf(['low', 'medium', 'high', 'urgent']);
});
});
it('shows social profile', () => {
cy.task('generateSocialProfile', { platform: 'instagram' }).then((profile) => {
expect(profile.platform).to.equal('instagram');
expect(profile.followers).to.be.a('number');
expect(profile.isVerified).to.be.a('boolean');
});
});
});Common Options
All generators accept these common options:
| Option | Type | Description |
|--------|------|-------------|
| seed | number \| string | Seed for reproducible data generation |
| locale | string | Locale code — en, de, fr, es, it, pt_BR, ja, zh_CN, ko, or ru. Unknown codes fall back to en. |
| strict | boolean | (generateUser only) Throw on invalid input instead of returning { error }. Will become the default in v3. |
Reproducible Tests with Seeds
const seed = 12345;
// These will always generate identical data
cy.task('generateUser', { seed }).then((user1) => {
cy.task('generateUser', { seed }).then((user2) => {
expect(user1.email).to.equal(user2.email);
expect(user1.firstName).to.equal(user2.firstName);
});
});Localized Data
// German names and addresses
cy.task('generateUser', { locale: 'de' }).then((user) => {
// User with German-style data
});
// French company
cy.task('generateCompany', { locale: 'fr' }).then((company) => {
// Company with French-style data
});Runtime Schemas
Every generator ships a matching Zod schema at the cypress-test-data-generator/schemas subpath. Validate real API responses against the exact shape the generator produces — one source of truth for tests and contracts:
import {
UserSchema,
ProductSchema,
OrderSchema,
} from 'cypress-test-data-generator/schemas';
describe('Checkout API', () => {
it('backend returns the same User shape the generator produces', () => {
cy.request('/api/users/123').then(({ body }) => {
const result = UserSchema.safeParse(body);
expect(result.success, JSON.stringify(result.error)).to.be.true;
});
});
});Schemas are also usable for asserting generator output directly:
cy.task('generateOrder', { productCount: 3 }).then((order) => {
expect(OrderSchema.safeParse(order).success).to.be.true;
});
zodis an optional peer dependency — only install it if you import the schemas subpath. Install withnpm install --save-dev zod.
Error Handling
By default, generateUser returns an { error: string } object on invalid input so tests can continue:
cy.task('generateUser', { ageMin: 50, ageMax: 30 }).then((result) => {
// Returns: { error: 'Max 30 should be greater than min 50' }
});Strict mode (recommended)
Pass strict: true to make invalid input throw. Test runners surface this as a clear failure instead of silently passing malformed data downstream:
cy.task('generateUser', { strict: true, ageMin: 50, ageMax: 30 });
// → task rejects, test fails with 'Max 30 should be greater than min 50'Deprecation notice. The default
{ error }return shape will be removed in v3 —strict: truewill become the default. Adoptstrictin new code to avoid a future breaking change.
All other generators already throw on invalid input (e.g. generateOrder({ productCount: 0 })).
Requirements
| Dependency | Version | Notes |
|------------|---------|-------|
| Cypress | 13.0.0+ | Required |
| Node.js | 18+ | Required |
| zod | 3.23.0+ | Optional peer — only if you use cypress-test-data-generator/schemas |
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see the LICENSE file for details.
Made by Ahmad Waqar
