e2e/data-factory/README.md
A minimal test data factory for Ghost e2e tests, written in TypeScript.
e2e/data-factory/ # Source files (TypeScript) - committed to git
├── factory.ts # Base factory class (adds the persistence lane)
├── factories/ # Factory implementations
│ ├── member-factory.ts
│ ├── post-factory.ts
│ ├── tag-factory.ts
│ └── ...
├── persistence/
│ ├── adapter.ts # Persistence interface
│ └── adapters/ # Adapter implementations (API, Knex, etc)
├── setup.ts # Setup helper functions
└── index.ts # Main exports
Entity shapes, randomised defaults and shared helpers (id/slug generators,
Lexical document builders) live in @tryghost/test-data and are re-exported
from the @/data-factory barrel.
This is part of the Ghost e2e test suite. All dependencies are managed by the main Ghost monorepo.
Start Ghost development server (provides database):
pnpm dev
Configure database connection (optional - uses Ghost's database by default):
cp e2e/data-factory/.env.example e2e/data-factory/.env
# Edit .env if using different database credentials
Build the e2e package (includes data-factory):
cd e2e && pnpm build
Option 1: Use setup helpers (recommended)
import {createPostFactory, PostFactory} from '../data-factory';
// Create factory with API persistence
const postFactory: PostFactory = createPostFactory(page.request);
// Build in-memory only (not persisted)
const draftPost = postFactory.build({
title: 'My Draft',
status: 'draft'
});
// Create and persist to database
const publishedPost = await postFactory.create({
title: 'My Published Post',
status: 'published'
});
Option 2: Manual setup
import {PostFactory} from '../data-factory/factories/post-factory';
import {GhostAdminApiAdapter} from '../data-factory/persistence/adapters/ghost-api';
const adapter = new GhostAdminApiAdapter(page.request, 'posts');
const postFactory = new PostFactory(adapter);
// Now you can build or create
const post = await postFactory.create({
title: 'My Published Post',
status: 'published'
});
@tryghost/test-data — it owns the
entity's Admin API response shape and randomised defaultsFactory<TOptions, TResult> whose
build() derives the write/create payload from that builder (see
tag-factory.ts for a 1:1 delegation, member-factory.ts and
post-factory.ts for shapes where the write payload differs from the
response — flattened relations, dropped response-only fields)entityType property (used for persistence)setup.ts for convenient usage in testsExample:
import {Factory} from '../factory';
import {member} from '@tryghost/test-data';
export class MemberFactory extends Factory<Partial<Member>, Member> {
entityType = 'members';
build(options: Partial<Member> = {}): Member {
return {
...toCreatePayload(member()), // response shape -> write payload
...options
};
}
}
Then create a setup helper:
// In setup.ts
export function createMemberFactory(httpClient: HttpClient): MemberFactory {
const adapter = new GhostAdminApiAdapter(httpClient, 'members');
return new MemberFactory(adapter);
}