Feature: Variants and States System
Add support for predefined factory variations that allow users to define different states or variants of a factory and apply them selectively.
Motivation
When testing, it's common to need variations of the same entity - for example, an admin user vs regular user, a published post vs draft post, or a deleted record vs active record. This feature would provide a clean API for defining and using these variations.
Proposed Features
-
Variant registration and application system
- Register named variants with specific overrides
- Apply single or multiple variants when building
-
State management
- Define common states (active, deleted, archived, etc.)
- Support for state transitions
-
Support for both static and dynamic variants
- Static: Fixed property overrides
- Dynamic: Functions that compute overrides
-
Handle variant conflicts appropriately
- Clear precedence rules when multiple variants modify same fields
- Option to merge or replace conflicting values
-
Multiple variants can be applied simultaneously
- Compose variants together
- Control order of application
Implementation Requirements
- TypeScript discriminated union support for type-safe variants
- Clear inheritance behavior for composed factories
- Efficient variant storage and lookup
- Support for async variant functions
- Integration with existing
extend() and compose() methods
Example API
const UserFactory = new Factory<User>((faker) => ({
id: faker.string.uuid(),
name: faker.person.fullName(),
email: faker.internet.email(),
role: 'user',
status: 'active',
isVerified: false
}))
.variant('admin', {
role: 'admin',
permissions: ['read', 'write', 'delete']
})
.variant('verified', {
isVerified: true,
verifiedAt: new Date()
})
.variant('deleted', (faker) => ({
status: 'deleted',
deletedAt: faker.date.recent()
}));
// Usage
const adminUser = UserFactory.build({ variant: 'admin' });
const verifiedAdmin = UserFactory.build({ variants: ['admin', 'verified'] });
const deletedUser = UserFactory.build({ variant: 'deleted' });
// With states
const PostFactory = new Factory<Post>((faker) => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
status: 'draft'
}))
.state('published', {
status: 'published',
publishedAt: new Date()
})
.state('archived', {
status: 'archived',
archivedAt: new Date()
});
// State transitions
const post = PostFactory.build({ state: 'draft' });
const publishedPost = PostFactory.transition(post, 'published');
TypeScript Support
// Discriminated unions
type User = BaseUser | AdminUser | DeletedUser;
const factory = new Factory<User>()
.variant<AdminUser>('admin', { type: 'admin', ... })
.variant<DeletedUser>('deleted', { type: 'deleted', ... });
// Type inference
const admin = factory.build({ variant: 'admin' }); // Type: AdminUser
Testing Requirements
- Unit tests for variant registration and application
- Tests for variant conflict resolution
- Type safety tests with discriminated unions
- Performance tests with many variants
- Integration tests with other factory methods
Feature: Variants and States System
Add support for predefined factory variations that allow users to define different states or variants of a factory and apply them selectively.
Motivation
When testing, it's common to need variations of the same entity - for example, an admin user vs regular user, a published post vs draft post, or a deleted record vs active record. This feature would provide a clean API for defining and using these variations.
Proposed Features
Variant registration and application system
State management
Support for both static and dynamic variants
Handle variant conflicts appropriately
Multiple variants can be applied simultaneously
Implementation Requirements
extend()andcompose()methodsExample API
TypeScript Support
Testing Requirements