-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Labels
enhancementNew feature or requestNew feature or requestgood first issueGood for newcomersGood for newcomershelp wantedExtra attention is neededExtra attention is neededonlydust-waveContribute to awesome OSS repos during OnlyDust's open source weekContribute to awesome OSS repos during OnlyDust's open source week
Description
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()andcompose()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: AdminUserTesting 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
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestgood first issueGood for newcomersGood for newcomershelp wantedExtra attention is neededExtra attention is neededonlydust-waveContribute to awesome OSS repos during OnlyDust's open source weekContribute to awesome OSS repos during OnlyDust's open source week