mirror of
https://github.com/xtr-dev/payload-automation.git
synced 2025-12-10 00:43:23 +00:00
Remove migration guide, test helpers, and test setup files
- Delete `MIGRATION-v0.0.37.md` as it is no longer necessary - Remove outdated files: `test-helpers.ts`, `test-setup.ts`, `test-trigger.ts`, and `vitest.config.ts` - Streamline project by eliminating obsolete and unused test-related files and configurations
This commit is contained in:
@@ -1,225 +0,0 @@
|
||||
# Migration Guide: v0.0.36 to v0.0.37
|
||||
|
||||
## Overview
|
||||
|
||||
Version 0.0.37 introduces significant refactoring and cleanup changes focused on simplifying the plugin architecture and removing unused features. This version removes several deprecated components and consolidates trigger handling.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
### 1. Removed Components and Files
|
||||
|
||||
The following components and modules have been completely removed:
|
||||
|
||||
#### Components
|
||||
- `TriggerWorkflowButton` - Manual workflow triggering component
|
||||
- `WorkflowExecutionStatus` - Workflow execution status display component
|
||||
|
||||
#### Plugin Modules
|
||||
- `init-global-hooks.ts` - Global hook initialization (functionality moved to main plugin)
|
||||
- `init-step-tasks.ts` - Step task initialization (functionality integrated elsewhere)
|
||||
- `init-webhook.ts` - Webhook initialization (functionality removed)
|
||||
- `init-workflow-hooks.ts` - Workflow hook initialization (functionality moved to main plugin)
|
||||
|
||||
#### Triggers
|
||||
- `webhook-trigger.ts` - Webhook trigger support has been removed
|
||||
- `cron-trigger.ts` - Cron/scheduled trigger support has been removed
|
||||
- `cron-scheduler.ts` - Cron scheduling system has been removed
|
||||
|
||||
#### Tests
|
||||
- `webhook-triggers.spec.ts` - Webhook trigger integration tests
|
||||
|
||||
### 2. Cron/Scheduled Workflows Removal
|
||||
|
||||
Cron trigger functionality has been completely removed from the plugin. If you were using cron triggers in your workflows:
|
||||
|
||||
**Migration Path:**
|
||||
- Use external scheduling services like GitHub Actions or Vercel Cron
|
||||
- Trigger workflows via webhook endpoints from external schedulers
|
||||
- Implement custom scheduling in your application using libraries like `node-cron`
|
||||
|
||||
**Example with GitHub Actions:**
|
||||
```yaml
|
||||
name: Trigger Workflow
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 9 * * *' # Daily at 9 AM
|
||||
jobs:
|
||||
trigger:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Workflow
|
||||
run: |
|
||||
curl -X POST https://your-app.com/api/workflows/trigger/your-workflow-id
|
||||
```
|
||||
|
||||
### 3. Webhook Trigger Removal
|
||||
|
||||
Webhook triggers have been removed. If you were using webhook triggers:
|
||||
|
||||
**Migration Path:**
|
||||
- Implement custom webhook endpoints in your PayloadCMS application
|
||||
- Use collection or global hooks to trigger workflows based on document changes
|
||||
- Create manual trigger endpoints using the workflow executor directly
|
||||
|
||||
### 4. Architecture Changes
|
||||
|
||||
#### ExecutorRegistry Removal
|
||||
The `executorRegistry` singleton pattern has been removed. WorkflowExecutor instances are now created on-demand for each execution.
|
||||
|
||||
**What this means:**
|
||||
- No shared state between workflow executions
|
||||
- Each execution is completely independent
|
||||
- Better memory management and isolation
|
||||
|
||||
#### Hook Registration Consolidation
|
||||
Hook registration logic has been consolidated into the main plugin file:
|
||||
- Collection hooks are now registered directly in `plugin/index.ts`
|
||||
- Global hooks are handled through the new `plugin/global-hook.ts` module
|
||||
- Simplified hook management with better TypeScript typing
|
||||
|
||||
## Non-Breaking Changes
|
||||
|
||||
### 1. Trigger Module Refactoring
|
||||
|
||||
Triggers have been reorganized into a dedicated `triggers/` directory with improved modularity:
|
||||
|
||||
- `triggers/collection-trigger.ts` - Collection-based triggers
|
||||
- `triggers/global-trigger.ts` - Global document triggers
|
||||
- `triggers/index.ts` - Trigger exports
|
||||
- `triggers/types.ts` - Trigger type definitions
|
||||
|
||||
### 2. Field Helper Improvements
|
||||
|
||||
New `triggerField` helper function standardizes virtual field creation across all trigger modules:
|
||||
|
||||
```typescript
|
||||
// Before (manual virtual field creation)
|
||||
{
|
||||
name: '__builtin_collection',
|
||||
type: 'text',
|
||||
admin: { hidden: true },
|
||||
virtual: true,
|
||||
access: { read: () => false, update: () => false }
|
||||
}
|
||||
|
||||
// After (using helper)
|
||||
triggerField('collection', {
|
||||
type: 'text',
|
||||
// helper handles virtual field setup automatically
|
||||
})
|
||||
```
|
||||
|
||||
### 3. TypeScript Improvements
|
||||
|
||||
- Replaced 'any' types with proper TypeScript types
|
||||
- Added `CollectionAfterChangeHook` and `PayloadRequest` type usage
|
||||
- Improved type safety throughout the codebase
|
||||
|
||||
### 4. Code Organization
|
||||
|
||||
#### New File Structure
|
||||
```
|
||||
src/
|
||||
├── plugin/
|
||||
│ ├── collection-hook.ts # Collection hook logic
|
||||
│ ├── global-hook.ts # Global hook logic (new)
|
||||
│ └── index.ts # Main plugin (consolidated)
|
||||
├── triggers/ # Trigger modules (new directory)
|
||||
├── fields/
|
||||
│ └── parameter.ts # Moved from triggers/helpers.ts
|
||||
```
|
||||
|
||||
#### ESLint Configuration
|
||||
- Disabled `perfectionist/sort-object-types` and `perfectionist/sort-objects` rules
|
||||
- Allows natural object property ordering without enforced alphabetical sorting
|
||||
|
||||
## Migration Steps
|
||||
|
||||
### 1. Update Imports
|
||||
|
||||
If you were importing removed components or modules, remove these imports:
|
||||
|
||||
```typescript
|
||||
// Remove these imports - no longer available
|
||||
import { TriggerWorkflowButton } from '@xtr-dev/payload-automation/client'
|
||||
import { WorkflowExecutionStatus } from '@xtr-dev/payload-automation/client'
|
||||
```
|
||||
|
||||
### 2. Update Workflow Configurations
|
||||
|
||||
If your workflows used cron or webhook triggers, you'll need to modify them:
|
||||
|
||||
**Before:**
|
||||
```javascript
|
||||
{
|
||||
trigger: {
|
||||
type: 'cron',
|
||||
schedule: '0 9 * * *'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```javascript
|
||||
{
|
||||
trigger: {
|
||||
type: 'collection', // Use collection or global triggers instead
|
||||
collection: 'your-collection',
|
||||
operation: 'create'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Replace Webhook Functionality
|
||||
|
||||
If you were using webhook triggers, implement custom webhook handling:
|
||||
|
||||
```typescript
|
||||
// In your PayloadCMS config
|
||||
export default buildConfig({
|
||||
endpoints: [
|
||||
{
|
||||
path: '/trigger-workflow/:workflowId',
|
||||
method: 'post',
|
||||
handler: async (req) => {
|
||||
const { workflowId } = req.params
|
||||
// Implement your workflow triggering logic here
|
||||
// Use the WorkflowExecutor directly if needed
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Update Custom Components
|
||||
|
||||
If you built custom components using the removed ones as reference, update them to work with the new architecture.
|
||||
|
||||
## Benefits of This Release
|
||||
|
||||
1. **Simplified Architecture**: Consolidated plugin initialization reduces complexity
|
||||
2. **Better Memory Management**: On-demand executor creation eliminates shared state issues
|
||||
3. **Improved Type Safety**: Proper TypeScript typing throughout
|
||||
4. **Reduced Bundle Size**: Removal of unused code reduces package size
|
||||
5. **Better Maintainability**: Cleaner code organization and module structure
|
||||
6. **More Reliable**: External scheduling is more robust than in-process cron jobs
|
||||
|
||||
## Testing Your Migration
|
||||
|
||||
After migrating:
|
||||
|
||||
1. **Test Existing Workflows**: Ensure collection and global triggers still work as expected
|
||||
2. **Verify External Triggers**: Test any external webhook or scheduling implementations
|
||||
3. **Check Custom Components**: Validate any custom UI components that interact with workflows
|
||||
4. **Run Integration Tests**: Execute your test suite to catch any breaking changes
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter issues migrating from v0.0.36 to v0.0.37:
|
||||
|
||||
1. Check that you're not using any of the removed components or features
|
||||
2. Verify your workflow trigger types are supported (collection, global, manual)
|
||||
3. Update any custom integrations that relied on removed modules
|
||||
4. Consider the external scheduling alternatives for cron functionality
|
||||
|
||||
For additional support, please refer to the plugin documentation or open an issue in the project repository.
|
||||
@@ -1,216 +0,0 @@
|
||||
import nock from 'nock'
|
||||
|
||||
/**
|
||||
* Mock HTTP requests to httpbin.org for testing
|
||||
*/
|
||||
export const mockHttpBin = {
|
||||
/**
|
||||
* Mock a successful POST request to httpbin.org/post
|
||||
*/
|
||||
mockPost: (expectedData?: any) => {
|
||||
return nock('https://httpbin.org')
|
||||
.post('/post')
|
||||
.reply(200, {
|
||||
args: {},
|
||||
data: JSON.stringify(expectedData || {}),
|
||||
files: {},
|
||||
form: {},
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'br, gzip, deflate',
|
||||
'Accept-Language': '*',
|
||||
'Content-Type': 'application/json',
|
||||
'Host': 'httpbin.org',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'User-Agent': 'PayloadCMS-Automation/1.0'
|
||||
},
|
||||
json: expectedData || {},
|
||||
origin: '127.0.0.1',
|
||||
url: 'https://httpbin.org/post'
|
||||
}, {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Credentials': 'true'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock a GET request to httpbin.org/get
|
||||
*/
|
||||
mockGet: () => {
|
||||
return nock('https://httpbin.org')
|
||||
.get('/get')
|
||||
.reply(200, {
|
||||
args: {},
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Host': 'httpbin.org',
|
||||
'User-Agent': 'PayloadCMS-Automation/1.0'
|
||||
},
|
||||
origin: '127.0.0.1',
|
||||
url: 'https://httpbin.org/get'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock HTTP timeout
|
||||
*/
|
||||
mockTimeout: (path: string = '/delay/10') => {
|
||||
return nock('https://httpbin.org')
|
||||
.get(path)
|
||||
.replyWithError({
|
||||
code: 'ECONNABORTED',
|
||||
message: 'timeout of 2000ms exceeded'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock HTTP error responses
|
||||
*/
|
||||
mockError: (status: number, path: string = '/status/' + status) => {
|
||||
return nock('https://httpbin.org')
|
||||
.get(path)
|
||||
.reply(status, {
|
||||
error: `HTTP ${status} Error`,
|
||||
message: `Mock ${status} response`
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock invalid URL to simulate network errors
|
||||
*/
|
||||
mockNetworkError: (url: string = 'invalid-url-that-will-fail') => {
|
||||
return nock('https://' + url)
|
||||
.get('/')
|
||||
.replyWithError({
|
||||
code: 'ENOTFOUND',
|
||||
message: `getaddrinfo ENOTFOUND ${url}`
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock HTML response (non-JSON)
|
||||
*/
|
||||
mockHtml: () => {
|
||||
return nock('https://httpbin.org')
|
||||
.get('/html')
|
||||
.reply(200, '<!DOCTYPE html><html><head><title>Test</title></head><body>Test HTML</body></html>', {
|
||||
'Content-Type': 'text/html'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mock all common endpoints for error scenarios
|
||||
*/
|
||||
mockAllErrorScenarios: () => {
|
||||
// HTML response for invalid JSON test
|
||||
nock('https://httpbin.org')
|
||||
.get('/html')
|
||||
.reply(200, '<!DOCTYPE html><html><head><title>Test</title></head><body>Test HTML</body></html>', {
|
||||
'Content-Type': 'text/html'
|
||||
})
|
||||
|
||||
// 404 error
|
||||
nock('https://httpbin.org')
|
||||
.get('/status/404')
|
||||
.reply(404, {
|
||||
error: 'Not Found',
|
||||
message: 'The requested resource was not found'
|
||||
})
|
||||
|
||||
// 500 error
|
||||
nock('https://httpbin.org')
|
||||
.get('/status/500')
|
||||
.reply(500, {
|
||||
error: 'Internal Server Error',
|
||||
message: 'Server encountered an error'
|
||||
})
|
||||
|
||||
// 503 error for retry tests
|
||||
nock('https://httpbin.org')
|
||||
.get('/status/503')
|
||||
.times(3) // Allow 3 retries
|
||||
.reply(503, {
|
||||
error: 'Service Unavailable',
|
||||
message: 'Service is temporarily unavailable'
|
||||
})
|
||||
|
||||
// POST endpoint for circular reference and other POST tests
|
||||
nock('https://httpbin.org')
|
||||
.post('/post')
|
||||
.times(5) // Allow multiple POST requests
|
||||
.reply(200, (uri, requestBody) => ({
|
||||
args: {},
|
||||
data: JSON.stringify(requestBody),
|
||||
json: requestBody,
|
||||
url: 'https://httpbin.org/post'
|
||||
}))
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up all nock mocks
|
||||
*/
|
||||
cleanup: () => {
|
||||
nock.cleanAll()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fixtures for common workflow configurations
|
||||
*/
|
||||
export const testFixtures = {
|
||||
// Function to create workflow data that bypasses parameter validation
|
||||
createWorkflow: async (payload: any, workflowData: any) => {
|
||||
// Insert directly into database to bypass parameter field validation
|
||||
const result = await payload.db.create({
|
||||
collection: 'workflows',
|
||||
data: workflowData
|
||||
})
|
||||
return result
|
||||
},
|
||||
basicWorkflow: {
|
||||
name: 'Test Basic Workflow',
|
||||
description: 'Basic workflow for testing',
|
||||
triggers: [
|
||||
{
|
||||
type: 'collection-hook' as const,
|
||||
parameters: {
|
||||
collectionSlug: 'posts',
|
||||
hook: 'afterChange'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
httpRequestStep: (url: string = 'https://httpbin.org/post', expectedData?: any) => ({
|
||||
name: 'http-request',
|
||||
type: 'http-request-step',
|
||||
parameters: {
|
||||
url,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: expectedData || {
|
||||
message: 'Test request',
|
||||
data: '$.trigger.doc'
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
createDocumentStep: (collectionSlug: string = 'auditLog') => ({
|
||||
name: 'create-audit',
|
||||
type: 'create-document',
|
||||
parameters: {
|
||||
collectionSlug,
|
||||
data: {
|
||||
message: 'Test document created',
|
||||
sourceId: '$.trigger.doc.id'
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
testPost: {
|
||||
content: 'Test post content for workflow trigger'
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
import { MongoMemoryReplSet } from 'mongodb-memory-server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Payload } from 'payload'
|
||||
import nock from 'nock'
|
||||
import config from './payload.config.js'
|
||||
|
||||
// Configure nock to intercept fetch requests properly in Node.js 22
|
||||
nock.disableNetConnect()
|
||||
nock.enableNetConnect('127.0.0.1')
|
||||
|
||||
// Set global fetch to use undici for proper nock interception
|
||||
import { fetch } from 'undici'
|
||||
global.fetch = fetch
|
||||
|
||||
let mongod: MongoMemoryReplSet | null = null
|
||||
let payload: Payload | null = null
|
||||
|
||||
// Global test setup - runs once for all tests
|
||||
beforeAll(async () => {
|
||||
// Start MongoDB in-memory replica set
|
||||
mongod = await MongoMemoryReplSet.create({
|
||||
replSet: {
|
||||
count: 1,
|
||||
dbName: 'payload-test',
|
||||
},
|
||||
})
|
||||
|
||||
const mongoUri = mongod.getUri()
|
||||
process.env.DATABASE_URI = mongoUri
|
||||
|
||||
console.log('🚀 MongoDB in-memory server started:', mongoUri)
|
||||
|
||||
// Initialize Payload with test config
|
||||
payload = await getPayload({
|
||||
config: await config,
|
||||
local: true
|
||||
})
|
||||
|
||||
console.log('✅ Payload initialized for testing')
|
||||
}, 60000)
|
||||
|
||||
// Global test teardown - runs once after all tests
|
||||
afterAll(async () => {
|
||||
if (payload) {
|
||||
console.log('🛑 Shutting down Payload...')
|
||||
// Payload doesn't have a shutdown method, but we can clear the cache
|
||||
delete (global as any).payload
|
||||
payload = null
|
||||
}
|
||||
|
||||
if (mongod) {
|
||||
console.log('🛑 Stopping MongoDB in-memory server...')
|
||||
await mongod.stop()
|
||||
mongod = null
|
||||
}
|
||||
}, 30000)
|
||||
|
||||
// Export payload instance for tests
|
||||
export const getTestPayload = () => {
|
||||
if (!payload) {
|
||||
throw new Error('Payload not initialized. Make sure test setup has run.')
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
// Helper to clean all collections
|
||||
export const cleanDatabase = async () => {
|
||||
if (!payload) return
|
||||
|
||||
try {
|
||||
// Clean up workflow runs first (child records)
|
||||
const runs = await payload.find({
|
||||
collection: 'workflow-runs',
|
||||
limit: 1000
|
||||
})
|
||||
|
||||
for (const run of runs.docs) {
|
||||
await payload.delete({
|
||||
collection: 'workflow-runs',
|
||||
id: run.id
|
||||
})
|
||||
}
|
||||
|
||||
// Clean up workflows
|
||||
const workflows = await payload.find({
|
||||
collection: 'workflows',
|
||||
limit: 1000
|
||||
})
|
||||
|
||||
for (const workflow of workflows.docs) {
|
||||
await payload.delete({
|
||||
collection: 'workflows',
|
||||
id: workflow.id
|
||||
})
|
||||
}
|
||||
|
||||
// Clean up audit logs
|
||||
const auditLogs = await payload.find({
|
||||
collection: 'auditLog',
|
||||
limit: 1000
|
||||
})
|
||||
|
||||
for (const log of auditLogs.docs) {
|
||||
await payload.delete({
|
||||
collection: 'auditLog',
|
||||
id: log.id
|
||||
})
|
||||
}
|
||||
|
||||
// Clean up posts
|
||||
const posts = await payload.find({
|
||||
collection: 'posts',
|
||||
limit: 1000
|
||||
})
|
||||
|
||||
for (const post of posts.docs) {
|
||||
await payload.delete({
|
||||
collection: 'posts',
|
||||
id: post.id
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Database cleanup failed:', error)
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
import type { Payload } from 'payload'
|
||||
import { getPayload } from 'payload'
|
||||
import config from './payload.config'
|
||||
|
||||
async function testWorkflowTrigger() {
|
||||
console.log('Starting workflow trigger test...')
|
||||
|
||||
// Get payload instance
|
||||
const payload = await getPayload({ config })
|
||||
|
||||
try {
|
||||
// Create a test user
|
||||
const user = await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: 'test@example.com',
|
||||
password: 'password123'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Created test user:', user.id)
|
||||
|
||||
// Create a workflow with collection trigger
|
||||
const workflow = await payload.create({
|
||||
collection: 'workflows',
|
||||
data: {
|
||||
name: 'Test Post Creation Workflow',
|
||||
description: 'Triggers when a post is created',
|
||||
triggers: [
|
||||
{
|
||||
type: 'collection-trigger',
|
||||
collectionSlug: 'posts',
|
||||
operation: 'create'
|
||||
}
|
||||
],
|
||||
steps: [
|
||||
{
|
||||
name: 'log-post',
|
||||
step: 'http-request-step',
|
||||
input: {
|
||||
url: 'https://httpbin.org/post',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: {
|
||||
message: 'Post created',
|
||||
postId: '$.trigger.doc.id',
|
||||
postTitle: '$.trigger.doc.title'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
user: user.id
|
||||
})
|
||||
|
||||
console.log('Created workflow:', workflow.id)
|
||||
|
||||
// Create a post to trigger the workflow
|
||||
console.log('Creating post to trigger workflow...')
|
||||
const post = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'Test Post',
|
||||
content: 'This should trigger the workflow',
|
||||
_status: 'published'
|
||||
},
|
||||
user: user.id
|
||||
})
|
||||
|
||||
console.log('Created post:', post.id)
|
||||
|
||||
// Wait a bit for workflow to execute
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
|
||||
// Check for workflow runs
|
||||
const runs = await payload.find({
|
||||
collection: 'workflow-runs',
|
||||
where: {
|
||||
workflow: {
|
||||
equals: workflow.id
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Workflow runs found:', runs.totalDocs)
|
||||
|
||||
if (runs.totalDocs > 0) {
|
||||
console.log('✅ SUCCESS: Workflow was triggered!')
|
||||
console.log('Run status:', runs.docs[0].status)
|
||||
console.log('Run context:', JSON.stringify(runs.docs[0].context, null, 2))
|
||||
} else {
|
||||
console.log('❌ FAILURE: Workflow was not triggered')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error)
|
||||
} finally {
|
||||
await payload.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
testWorkflowTrigger().catch(console.error)
|
||||
@@ -1,17 +0,0 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
threads: false, // Prevent port/DB conflicts
|
||||
pool: 'forks',
|
||||
poolOptions: {
|
||||
forks: {
|
||||
singleFork: true
|
||||
}
|
||||
},
|
||||
testTimeout: 30000, // 30 second timeout for integration tests
|
||||
setupFiles: ['./dev/test-setup.ts']
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user