payload-integration-test-utils
v1.0.0
Published
Opinionated integration test helpers providing a ready-to-use Payload instance for vitest.
Maintainers
Readme
payload-integration-test-utils
Opinionated integration test helpers providing a ready-to-use Payload instance for vitest.
Installation
npm install -D payload-integration-test-utilsDepending on your used database
npm install -D @testcontainers/mongodbor
npm install -D @testcontainers/postgresqlUsage
1. Create a global setup file
Create a file that re-exports the setup and teardown functions:
// test/setupIntegrationTest.ts
export {setup, teardown} from 'payload-integration-test-utils';2. Configure Vitest
Reference the global setup file and set DB_TYPE plus the corresponding Docker image MONGO_DB_IMAGE|POSTGRES_IMAGE.
// vitest.config.ts
import {defineConfig} from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
name: 'mongodb',
include: ['./test/integration/**/*.test.ts'],
globalSetup: './test/setupIntegrationTest.ts',
testTimeout: 30000,
hookTimeout: 30000,
fileParallelism: false,
env: {
DB_TYPE: 'mongodb',
MONGO_DB_IMAGE: 'mongo:8.0',
},
},
},
],
},
});3. Write tests
Use getTestContextFor to get a Payload Local API instance wired to the containerized database:
// test/integration/posts.test.ts
import type {CollectionConfig} from 'payload';
import {expect, it} from 'vitest';
import {getTestContextFor} from 'payload-integration-test-utils';
const Posts: CollectionConfig = {
slug: 'posts',
fields: [{type: 'text', name: 'title'}],
};
const ctx = getTestContextFor({collections: [Posts]});
it('creates and retrieves a document', async () => {
const created = await ctx.payload.create({
collection: 'posts',
data: {title: 'Hello World'},
});
const result = await ctx.payload.find({collection: 'posts'});
expect(result.totalDocs).toBe(1);
expect(result.docs[0].id).toBe(created.id);
});
it('starts each test with a clean database', async () => {
const count = await ctx.payload.count({collection: 'posts'});
expect(count.totalDocs).toBe(0);
});You can also test globals, or combine both:
import type {CollectionConfig, GlobalConfig} from 'payload';
import {getTestContextFor} from 'payload-integration-test-utils';
const Posts: CollectionConfig = {
slug: 'posts',
fields: [{type: 'text', name: 'title'}],
};
const Settings: GlobalConfig = {
slug: 'settings',
fields: [{type: 'text', name: 'siteTitle'}],
};
// collections only
const ctx = getTestContextFor({collections: [Posts]});
// globals only
const ctx = getTestContextFor({globals: [Settings]});
// both
const ctx = getTestContextFor({collections: [Posts], globals: [Settings]});How It Works
Global Setup (setup / teardown)
The setup function reads DB_TYPE from the Vitest project env and starts the corresponding Testcontainer:
| DB_TYPE | Container image env | Container |
|------------|---------------------|-----------------------|
| mongodb | MONGO_DB_IMAGE | MongoDBContainer |
| postgres | POSTGRES_IMAGE | PostgreSqlContainer |
It sets DATABASE_URL and DATABASE_TYPE as process environment variables so the Payload adapter can connect. The
teardown function stops the container.
getTestContextFor(options)
Registers Vitest lifecycle hooks and returns a context object.
Options:
| Property | Type | Default | Description |
|----------------|----------------------|------------|------------------------------------|
| collections | CollectionConfig[] | [] | Collections to register and clean |
| globals | GlobalConfig[] | [] | Globals to register |
| tsOutputFile | string | /dev/null| Path to generate Payload types to |
Lifecycle hooks:
beforeAll— initializes a Payload instance with the given collections and globals using the database from the global setupbeforeEach— deletes all documents from every provided collectionafterAll— deletes all documents from every provided collectionctx.payload— getter that returns theBasePayloadinstance for Local API calls
getPayloadInstance(collections, globals, tsOutputFile?)
Lower-level function used by getTestContextFor. Creates (or returns a cached) Payload instance based on
DATABASE_TYPE and DATABASE_URL environment variables. Caches by URL so repeated calls in the same test file reuse
the same instance.
Type Generation
Pass tsOutputFile to generate Payload types:
const ctx = getTestContextFor({collections: [Posts], tsOutputFile: './test/payload-types.ts'});Defaults to /dev/null (disabled).
License
MIT
Todo
- [ ] Github Actions
