mirror of
https://github.com/xtr-dev/payload-automation.git
synced 2025-12-10 17:03:22 +00:00
Major Features: • Add persistent error tracking for timeout/network failures that bypasses PayloadCMS output limitations • Implement smart error classification (timeout, DNS, connection, network) with duration-based detection • Add comprehensive test infrastructure with MongoDB in-memory testing and enhanced mocking • Fix HTTP request handler error preservation with detailed context storage • Add independent execution tracking with success/failure status and duration metrics Technical Improvements: • Update JSONPath documentation to use correct $.trigger.doc syntax across all step types • Fix PayloadCMS job execution to use runByID instead of run() for reliable task processing • Add enhanced HTTP error handling that preserves outputs for 4xx/5xx status codes • Implement proper nock configuration with undici for Node.js 22 fetch interception • Add comprehensive unit tests for WorkflowExecutor with mocked PayloadCMS instances Developer Experience: • Add detailed error information in workflow context with URL, method, timeout, attempts • Update README with HTTP error handling patterns and enhanced error tracking examples • Add test helpers and setup infrastructure for reliable integration testing • Fix workflow step validation and JSONPath field descriptions Breaking Changes: None - fully backward compatible 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
125 lines
2.9 KiB
TypeScript
125 lines
2.9 KiB
TypeScript
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)
|
|
}
|
|
} |