diff --git a/docs/jobs-queue/queues.mdx b/docs/jobs-queue/queues.mdx index e255a4f00..a1a13e7db 100644 --- a/docs/jobs-queue/queues.mdx +++ b/docs/jobs-queue/queues.mdx @@ -30,7 +30,9 @@ As mentioned above, you can queue jobs, but the jobs won't run unless a worker p ### Cron jobs -You can use the `jobs.autoRun` property to configure cron jobs: +The `jobs.autoRun` property allows you to configure cron jobs that automatically run queued jobs at specified intervals. Note that this does not _queue_ new jobs - only _runs_ jobs that are already in the specified queue. + +**Example**: ```ts export default buildConfig({ diff --git a/packages/next/src/views/LivePreview/index.client.tsx b/packages/next/src/views/LivePreview/index.client.tsx index 5eb0c7aaa..d5b03c985 100644 --- a/packages/next/src/views/LivePreview/index.client.tsx +++ b/packages/next/src/views/LivePreview/index.client.tsx @@ -427,7 +427,7 @@ const PreviewView: React.FC = ({ : currentEditor !== user?.id) && !isReadOnlyForIncomingUser && !showTakeOverModal && - // eslint-disable-next-line react-compiler/react-compiler + !documentLockStateRef.current?.hasShownLockedModal && !isLockExpired diff --git a/packages/payload/src/bin/index.ts b/packages/payload/src/bin/index.ts index e937254ca..3f87a9f1b 100755 --- a/packages/payload/src/bin/index.ts +++ b/packages/payload/src/bin/index.ts @@ -128,7 +128,7 @@ export const bin = async () => { queue, }) - await payload.db.destroy!() // close database connections after running jobs so process can exit cleanly + await payload.destroy() // close database connections after running jobs so process can exit cleanly return } diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 8d2e69fef..fdf111a39 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -322,9 +322,23 @@ export class BasePayload { return create(this, options) } + crons: Cron[] = [] db: DatabaseAdapter + decrypt = decrypt + destroy = async () => { + if (this.crons.length) { + // Remove all crons from the list before stopping them + const cronsToStop = this.crons.splice(0, this.crons.length) + await Promise.all(cronsToStop.map((cron) => cron.stop())) + } + + if (this.db?.destroy && typeof this.db.destroy === 'function') { + await this.db.destroy() + } + } + duplicate = async >( options: DuplicateOptions, ): Promise> => { @@ -334,11 +348,11 @@ export class BasePayload { email: InitializedEmailAdapter - encrypt = encrypt - // TODO: re-implement or remove? // errorHandler: ErrorHandler + encrypt = encrypt + extensions: (args: { args: OperationArgs req: graphQLRequest @@ -783,6 +797,8 @@ export class BasePayload { queue: cronConfig.queue, }) }) + + this.crons.push(job) }), ) } @@ -832,9 +848,7 @@ export const reload = async ( payload: Payload, skipImportMapGeneration?: boolean, ): Promise => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() payload.config = config diff --git a/packages/payload/src/queues/config/types/index.ts b/packages/payload/src/queues/config/types/index.ts index 8082be526..9d261113c 100644 --- a/packages/payload/src/queues/config/types/index.ts +++ b/packages/payload/src/queues/config/types/index.ts @@ -10,18 +10,20 @@ export type CronConfig = { * @default '* * * * *' (every minute). * * @example - * ┌───────────── minute (0 - 59) - * │ ┌───────────── hour (0 - 23) - * │ │ ┌───────────── day of the month (1 - 31) - * │ │ │ ┌───────────── month (1 - 12) - * │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) - * │ │ │ │ │ - * │ │ │ │ │ - * - '0 * * * *' every hour at minute 0 - * - '0 0 * * *' daily at midnight - * - '0 0 * * 0' weekly at midnight on Sundays - * - '0 0 1 * *' monthly at midnight on the 1st day of the month - * - '0/5 * * * *' every 5 minutes + * ┌───────────── (optional) second (0 - 59) + * │ ┌───────────── minute (0 - 59) + * │ │ ┌───────────── hour (0 - 23) + * │ │ │ ┌───────────── day of the month (1 - 31) + * │ │ │ │ ┌───────────── month (1 - 12) + * │ │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday) + * │ │ │ │ │ │ + * │ │ │ │ │ │ + * - '* 0 * * * *' every hour at minute 0 + * - '* 0 0 * * *' daily at midnight + * - '* 0 0 * * 0' weekly at midnight on Sundays + * - '* 0 0 1 * *' monthly at midnight on the 1st day of the month + * - '* 0/5 * * * *' every 5 minutes + * - '* * * * * *' every second */ cron?: string /** @@ -58,7 +60,10 @@ export type JobsConfig = { */ addParentToTaskLog?: boolean /** - * Queue cron jobs automatically on payload initialization. + * Allows you to configure cron jobs that automatically run queued jobs + * at specified intervals. Note that this does not _queue_ new jobs - only + * _runs_ jobs that are already in the specified queue. + * * @remark this property should not be used on serverless platforms like Vercel */ autoRun?: ((payload: Payload) => CronConfig[] | Promise) | CronConfig[] diff --git a/packages/ui/src/fields/Relationship/Input.tsx b/packages/ui/src/fields/Relationship/Input.tsx index bdc5b173d..8e7d75731 100644 --- a/packages/ui/src/fields/Relationship/Input.tsx +++ b/packages/ui/src/fields/Relationship/Input.tsx @@ -101,7 +101,7 @@ export const RelationshipInput: React.FC = (props) => { const valueRef = useRef(value) // the line below seems odd - // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix this + valueRef.current = value const [DocumentDrawer, , { isDrawerOpen, openDrawer }] = useDocumentDrawer({ diff --git a/packages/ui/src/providers/TableColumns/index.tsx b/packages/ui/src/providers/TableColumns/index.tsx index 463f27ddc..3af8e56bf 100644 --- a/packages/ui/src/providers/TableColumns/index.tsx +++ b/packages/ui/src/providers/TableColumns/index.tsx @@ -100,7 +100,7 @@ export const TableColumnsProvider: React.FC = ({ resetColumnsState, setActiveColumns, toggleColumn, - // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix + ...contextRef.current, }} > diff --git a/templates/plugin/dev/int.spec.ts b/templates/plugin/dev/int.spec.ts index 97b3c4d64..04e6982bf 100644 --- a/templates/plugin/dev/int.spec.ts +++ b/templates/plugin/dev/int.spec.ts @@ -9,9 +9,7 @@ import { customEndpointHandler } from '../src/endpoints/customEndpointHandler.js let payload: Payload afterAll(async () => { - if (payload.db.destroy) { - await payload.db.destroy() - } + await payload.destroy() }) beforeAll(async () => { diff --git a/test/_community/int.spec.ts b/test/_community/int.spec.ts index 6cc524d87..52676c058 100644 --- a/test/_community/int.spec.ts +++ b/test/_community/int.spec.ts @@ -38,9 +38,7 @@ describe('_Community Tests', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) // --__--__--__--__--__--__--__--__--__ diff --git a/test/access-control/int.spec.ts b/test/access-control/int.spec.ts index a91d17fee..e7854ffc1 100644 --- a/test/access-control/int.spec.ts +++ b/test/access-control/int.spec.ts @@ -54,9 +54,7 @@ describe('Access Control', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Fields', () => { diff --git a/test/admin-root/int.spec.ts b/test/admin-root/int.spec.ts index 7e16899b9..36a0bc539 100644 --- a/test/admin-root/int.spec.ts +++ b/test/admin-root/int.spec.ts @@ -39,9 +39,7 @@ describe('Admin (Root) Tests', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) // --__--__--__--__--__--__--__--__--__ diff --git a/test/array-update/int.spec.ts b/test/array-update/int.spec.ts index a34948ec6..2d42d48f2 100644 --- a/test/array-update/int.spec.ts +++ b/test/array-update/int.spec.ts @@ -17,9 +17,7 @@ describe('array-update', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should persist existing array-based data while updating and passing row ID', async () => { diff --git a/test/auth/custom-strategy/int.spec.ts b/test/auth/custom-strategy/int.spec.ts index 341e0b77f..01f8b4c6a 100644 --- a/test/auth/custom-strategy/int.spec.ts +++ b/test/auth/custom-strategy/int.spec.ts @@ -26,9 +26,7 @@ describe('AuthStrategies', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('create user', () => { diff --git a/test/auth/forgot-password-localized/int.spec.ts b/test/auth/forgot-password-localized/int.spec.ts index 0e5eaa308..e38f3897b 100644 --- a/test/auth/forgot-password-localized/int.spec.ts +++ b/test/auth/forgot-password-localized/int.spec.ts @@ -46,9 +46,7 @@ describe('Forgot password operation with localized fields', () => { }) afterAll(async () => { - if (typeof payload?.db.destroy === 'function') { - await payload?.db.destroy() - } + await payload.destroy() }) it('should successfully process forgotPassword operation with localized fields', async () => { diff --git a/test/auth/int.spec.ts b/test/auth/int.spec.ts index ec6e6c0e5..ea89fc74e 100644 --- a/test/auth/int.spec.ts +++ b/test/auth/int.spec.ts @@ -40,9 +40,7 @@ describe('Auth', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('GraphQL - admin user', () => { diff --git a/test/auth/removed-token/int.spec.ts b/test/auth/removed-token/int.spec.ts index b21ba502d..4260bc9b3 100644 --- a/test/auth/removed-token/int.spec.ts +++ b/test/auth/removed-token/int.spec.ts @@ -26,9 +26,7 @@ describe('Remove token from auth responses', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should not include token in response from /login', async () => { diff --git a/test/collections-graphql/int.spec.ts b/test/collections-graphql/int.spec.ts index 42435b1d1..1c13e1a8b 100644 --- a/test/collections-graphql/int.spec.ts +++ b/test/collections-graphql/int.spec.ts @@ -26,9 +26,7 @@ describe('collections-graphql', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('CRUD', () => { diff --git a/test/collections-rest/int.spec.ts b/test/collections-rest/int.spec.ts index 3bc84072f..553d2d4f2 100644 --- a/test/collections-rest/int.spec.ts +++ b/test/collections-rest/int.spec.ts @@ -33,9 +33,7 @@ describe('collections-rest', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/test/config/int.spec.ts b/test/config/int.spec.ts index 0b6b56887..26b5127a7 100644 --- a/test/config/int.spec.ts +++ b/test/config/int.spec.ts @@ -22,9 +22,7 @@ describe('Config', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('payload config', () => { diff --git a/test/custom-graphql/int.spec.ts b/test/custom-graphql/int.spec.ts index 9c18cab18..fb86c56f4 100644 --- a/test/custom-graphql/int.spec.ts +++ b/test/custom-graphql/int.spec.ts @@ -19,9 +19,7 @@ describe('Custom GraphQL', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) if (!['sqlite', 'sqlite-uuid'].includes(process.env.PAYLOAD_DATABASE || '')) { diff --git a/test/database/int.spec.ts b/test/database/int.spec.ts index a628f23a8..98c78074d 100644 --- a/test/database/int.spec.ts +++ b/test/database/int.spec.ts @@ -71,9 +71,7 @@ describe('database', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('id type', () => { diff --git a/test/database/postgres-relationships-v2-v3-migration/int.spec.ts b/test/database/postgres-relationships-v2-v3-migration/int.spec.ts index 0dc9eada2..f769cc0d0 100644 --- a/test/database/postgres-relationships-v2-v3-migration/int.spec.ts +++ b/test/database/postgres-relationships-v2-v3-migration/int.spec.ts @@ -46,6 +46,6 @@ describe('Postgres relationships v2-v3 migration', () => { expect(hasErr).toBeFalsy() await payload.db.dropDatabase({ adapter: payload.db as any }) - await payload.db.destroy() + await payload.destroy() }) }) diff --git a/test/database/up-down-migration/int.spec.ts b/test/database/up-down-migration/int.spec.ts index c4be9b37c..472a952cf 100644 --- a/test/database/up-down-migration/int.spec.ts +++ b/test/database/up-down-migration/int.spec.ts @@ -53,6 +53,6 @@ describe('SQL migrations', () => { await payload.db.migrateDown() await payload.db.dropDatabase({ adapter: payload.db as any }) - await payload.db.destroy?.() + await payload.destroy() }) }) diff --git a/test/dataloader/int.spec.ts b/test/dataloader/int.spec.ts index faf04d34a..b63f46ca6 100644 --- a/test/dataloader/int.spec.ts +++ b/test/dataloader/int.spec.ts @@ -35,9 +35,7 @@ describe('dataloader', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('graphql', () => { diff --git a/test/endpoints/int.spec.ts b/test/endpoints/int.spec.ts index ee91929ed..7d31ffd62 100644 --- a/test/endpoints/int.spec.ts +++ b/test/endpoints/int.spec.ts @@ -27,9 +27,7 @@ describe('Endpoints', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Collections', () => { diff --git a/test/fields-relationship/int.spec.ts b/test/fields-relationship/int.spec.ts index 6cc4d164d..e6b458221 100644 --- a/test/fields-relationship/int.spec.ts +++ b/test/fields-relationship/int.spec.ts @@ -33,9 +33,7 @@ describe('Relationship Fields', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Versioned Relationship Field', () => { diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts index 61fa97715..6de846436 100644 --- a/test/fields/int.spec.ts +++ b/test/fields/int.spec.ts @@ -53,9 +53,7 @@ describe('Fields', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/test/folders-browse-by-disabled/int.spec.ts b/test/folders-browse-by-disabled/int.spec.ts index a6cb8db5e..17afb242a 100644 --- a/test/folders-browse-by-disabled/int.spec.ts +++ b/test/folders-browse-by-disabled/int.spec.ts @@ -18,9 +18,7 @@ describe('folders', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/test/folders/int.spec.ts b/test/folders/int.spec.ts index a6cb8db5e..17afb242a 100644 --- a/test/folders/int.spec.ts +++ b/test/folders/int.spec.ts @@ -18,9 +18,7 @@ describe('folders', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/test/form-state/int.spec.ts b/test/form-state/int.spec.ts index d81d4ae73..eb614e002 100644 --- a/test/form-state/int.spec.ts +++ b/test/form-state/int.spec.ts @@ -38,9 +38,7 @@ describe('Form State', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should build entire form state', async () => { diff --git a/test/globals/int.spec.ts b/test/globals/int.spec.ts index 943e45f46..19315ec70 100644 --- a/test/globals/int.spec.ts +++ b/test/globals/int.spec.ts @@ -27,9 +27,7 @@ describe('globals', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('REST', () => { diff --git a/test/graphql/int.spec.ts b/test/graphql/int.spec.ts index 6006887fb..8946d81b7 100644 --- a/test/graphql/int.spec.ts +++ b/test/graphql/int.spec.ts @@ -20,9 +20,7 @@ describe('graphql', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('graphql', () => { diff --git a/test/helpers/startMemoryDB.ts b/test/helpers/startMemoryDB.ts index cd328a0d6..648a4118b 100644 --- a/test/helpers/startMemoryDB.ts +++ b/test/helpers/startMemoryDB.ts @@ -2,6 +2,12 @@ import dotenv from 'dotenv' import { MongoMemoryReplSet } from 'mongodb-memory-server' dotenv.config() +declare global { + // Add the custom property to the NodeJS global type + // eslint-disable-next-line no-var + var _mongoMemoryServer: MongoMemoryReplSet | undefined +} + // eslint-disable-next-line no-restricted-exports export default async () => { // @ts-expect-error diff --git a/test/helpers/stopMemoryDB.ts b/test/helpers/stopMemoryDB.ts index ec3f196ad..9aaa1a4b1 100644 --- a/test/helpers/stopMemoryDB.ts +++ b/test/helpers/stopMemoryDB.ts @@ -1,9 +1,38 @@ -// eslint-disable-next-line no-restricted-exports -export default async () => { +import { spawn } from 'child_process' + +try { if (global._mongoMemoryServer) { - console.log('Stopping memorydb...') - await global._mongoMemoryServer.stop() - console.log('Stopped memorydb') + // Spawn a detached process to stop the memory server. + // We need to stop the memory server in a seperate process, after the jest process has exited. + // This ensures that Cronjobs that may be started by payload (in the jest process) are stopped. + // Otherwise, we may shut down the memory server while the cronjob is still running, which can lead to mongo + // connection errors (if the cronjob tries to perform a db operation in between mongo shutting down and jest exiting) that are reported as failed tests. + const stopScript = ` + (async () => { + // Wait 300ms to ensure the jest process has exited + await new Promise(resolve => setTimeout(resolve, 300)); + try { + if (global._mongoMemoryServer) { + await global._mongoMemoryServer.stop(); + console.log('Stopped memorydb'); + } + } catch (error) { + console.error('Error stopping memorydb:', error); + } + process.exit(0); + })(); + ` + + const child = spawn(process.execPath, ['-e', stopScript], { + detached: true, + stdio: 'ignore', + }) + // Unreference the child process so it can run independently and so that jest can exit cleanly without open handles warnings + child.unref() + console.log('Spawned detached process to stop memorydb') } - process.exit(0) +} catch (error) { + console.error('Error stopping memorydb:', error) } + +process.exit(0) diff --git a/test/hooks/int.spec.ts b/test/hooks/int.spec.ts index ef3786fe5..c292c3725 100644 --- a/test/hooks/int.spec.ts +++ b/test/hooks/int.spec.ts @@ -38,9 +38,7 @@ describe('Hooks', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) if (isMongoose(payload)) { describe('transform actions', () => { diff --git a/test/joins/int.spec.ts b/test/joins/int.spec.ts index d2fac5431..a2e567f66 100644 --- a/test/joins/int.spec.ts +++ b/test/joins/int.spec.ts @@ -122,9 +122,7 @@ describe('Joins Field', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should populate joins using findByID', async () => { diff --git a/test/live-preview/int.spec.ts b/test/live-preview/int.spec.ts index ef392a36d..3fa1d9154 100644 --- a/test/live-preview/int.spec.ts +++ b/test/live-preview/int.spec.ts @@ -102,9 +102,7 @@ describe('Collections - Live Preview', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('handles `postMessage`', async () => { diff --git a/test/localization/int.spec.ts b/test/localization/int.spec.ts index 8a184a9f0..64a90ffb2 100644 --- a/test/localization/int.spec.ts +++ b/test/localization/int.spec.ts @@ -55,9 +55,7 @@ describe('Localization', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Localization with fallback true', () => { diff --git a/test/locked-documents/int.spec.ts b/test/locked-documents/int.spec.ts index 560569104..487f6400e 100644 --- a/test/locked-documents/int.spec.ts +++ b/test/locked-documents/int.spec.ts @@ -74,9 +74,7 @@ describe('Locked documents', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) afterEach(() => { diff --git a/test/login-with-username/int.spec.ts b/test/login-with-username/int.spec.ts index f16d18c78..66c2cbed5 100644 --- a/test/login-with-username/int.spec.ts +++ b/test/login-with-username/int.spec.ts @@ -17,9 +17,7 @@ describe('Login With Username Feature', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should not allow creation with neither email nor username', async () => { diff --git a/test/payload-cloud/int.spec.ts b/test/payload-cloud/int.spec.ts index 322d8c4d8..95a493f7c 100644 --- a/test/payload-cloud/int.spec.ts +++ b/test/payload-cloud/int.spec.ts @@ -16,9 +16,7 @@ describe('@payloadcms/plugin-cloud', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('tests', () => { diff --git a/test/plugin-cloud-storage/int.spec.ts b/test/plugin-cloud-storage/int.spec.ts index 861a5be0d..db3b64a77 100644 --- a/test/plugin-cloud-storage/int.spec.ts +++ b/test/plugin-cloud-storage/int.spec.ts @@ -25,9 +25,7 @@ describe('@payloadcms/plugin-cloud-storage', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) let client: AWS.S3Client diff --git a/test/plugin-form-builder/int.spec.ts b/test/plugin-form-builder/int.spec.ts index 3db963924..51b1af149 100644 --- a/test/plugin-form-builder/int.spec.ts +++ b/test/plugin-form-builder/int.spec.ts @@ -70,9 +70,7 @@ describe('@payloadcms/plugin-form-builder', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('plugin collections', () => { diff --git a/test/plugin-import-export/int.spec.ts b/test/plugin-import-export/int.spec.ts index c61ee3883..acd54ea06 100644 --- a/test/plugin-import-export/int.spec.ts +++ b/test/plugin-import-export/int.spec.ts @@ -31,9 +31,7 @@ describe('@payloadcms/plugin-import-export', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('graphql', () => { diff --git a/test/plugin-multi-tenant/int.spec.ts b/test/plugin-multi-tenant/int.spec.ts index b7e19750e..7df008e45 100644 --- a/test/plugin-multi-tenant/int.spec.ts +++ b/test/plugin-multi-tenant/int.spec.ts @@ -33,9 +33,7 @@ describe('@payloadcms/plugin-multi-tenant', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('tenants', () => { diff --git a/test/plugin-nested-docs/int.spec.ts b/test/plugin-nested-docs/int.spec.ts index 674fe4b18..caeda5984 100644 --- a/test/plugin-nested-docs/int.spec.ts +++ b/test/plugin-nested-docs/int.spec.ts @@ -18,9 +18,7 @@ describe('@payloadcms/plugin-nested-docs', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('seed', () => { diff --git a/test/plugin-redirects/int.spec.ts b/test/plugin-redirects/int.spec.ts index 6acf1cd57..b22b08ef8 100644 --- a/test/plugin-redirects/int.spec.ts +++ b/test/plugin-redirects/int.spec.ts @@ -27,9 +27,7 @@ describe('@payloadcms/plugin-redirects', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should add a redirects collection', async () => { diff --git a/test/plugin-search/int.spec.ts b/test/plugin-search/int.spec.ts index cf34f031b..1271d46f2 100644 --- a/test/plugin-search/int.spec.ts +++ b/test/plugin-search/int.spec.ts @@ -66,9 +66,7 @@ describe('@payloadcms/plugin-search', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should add a search collection', async () => { diff --git a/test/plugin-sentry/int.spec.ts b/test/plugin-sentry/int.spec.ts index 65908e269..f8c8f0fd9 100644 --- a/test/plugin-sentry/int.spec.ts +++ b/test/plugin-sentry/int.spec.ts @@ -16,9 +16,7 @@ describe('@payloadcms/plugin-sentry', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('tests', () => { diff --git a/test/plugin-seo/int.spec.ts b/test/plugin-seo/int.spec.ts index 5a04f776e..e3c527569 100644 --- a/test/plugin-seo/int.spec.ts +++ b/test/plugin-seo/int.spec.ts @@ -46,9 +46,7 @@ describe('@payloadcms/plugin-seo', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should add meta title', async () => { diff --git a/test/plugin-stripe/int.spec.ts b/test/plugin-stripe/int.spec.ts index c875a3e9b..aed0f2459 100644 --- a/test/plugin-stripe/int.spec.ts +++ b/test/plugin-stripe/int.spec.ts @@ -16,9 +16,7 @@ describe('Stripe Plugin', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('should create products', async () => { diff --git a/test/plugins/int.spec.ts b/test/plugins/int.spec.ts index e185d3691..6ab6520e7 100644 --- a/test/plugins/int.spec.ts +++ b/test/plugins/int.spec.ts @@ -17,9 +17,7 @@ describe('Collections - Plugins', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) it('created pages collection', async () => { diff --git a/test/query-presets/int.spec.ts b/test/query-presets/int.spec.ts index 5ce5e4d99..c157f70f5 100644 --- a/test/query-presets/int.spec.ts +++ b/test/query-presets/int.spec.ts @@ -53,9 +53,7 @@ describe('Query Presets', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('default access control', () => { diff --git a/test/queues/config.ts b/test/queues/config.ts index 2217f29e1..7f0c66ad8 100644 --- a/test/queues/config.ts +++ b/test/queues/config.ts @@ -96,6 +96,16 @@ export default buildConfigWithDefaults({ }, }, jobs: { + autoRun: [ + { + // Every second + cron: '* * * * * *', + limit: 100, + queue: 'autorunSecond', // name of the queue + }, + // add as many cron jobs as you want + ], + shouldAutoRun: () => true, jobsCollectionOverrides: ({ defaultJobsCollection }) => { return { ...defaultJobsCollection, diff --git a/test/queues/int.spec.ts b/test/queues/int.spec.ts index e0c72a0e9..4a5001154 100644 --- a/test/queues/int.spec.ts +++ b/test/queues/int.spec.ts @@ -24,9 +24,7 @@ describe('Queues', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { @@ -652,6 +650,29 @@ describe('Queues', () => { expect(allSimples.docs[0].title).toBe('hello!') }) + it('can create and autorun jobs', async () => { + await payload.jobs.queue({ + workflow: 'inlineTaskTest', + queue: 'autorunSecond', + input: { + message: 'hello!', + }, + }) + + // Do not call payload.jobs.run() + + // Autorun runs every second - so should definitely be done if we wait 2 seconds + await new Promise((resolve) => setTimeout(resolve, 2000)) + + const allSimples = await payload.find({ + collection: 'simple', + limit: 100, + }) + + expect(allSimples.totalDocs).toBe(1) + expect(allSimples?.docs?.[0]?.title).toBe('hello!') + }) + it('should respect deleteJobOnComplete true default configuration', async () => { const { id } = await payload.jobs.queue({ workflow: 'inlineTaskTest', @@ -1372,13 +1393,14 @@ describe('Queues', () => { // TODO: This test is flaky on supabase in CI, so we skip it for now return } - const amount = 500 payload.config.jobs.deleteJobOnComplete = false const job = await payload.jobs.queue({ workflow: 'parallelTask', - input: {}, + input: { + amount, + }, }) await payload.jobs.run() diff --git a/test/queues/payload-types.ts b/test/queues/payload-types.ts index eb7892fa4..b6b91c4f5 100644 --- a/test/queues/payload-types.ts +++ b/test/queues/payload-types.ts @@ -781,7 +781,9 @@ export interface WorkflowLongRunning { * via the `definition` "WorkflowParallelTask". */ export interface WorkflowParallelTask { - input?: unknown; + input: { + amount: number; + }; } /** * This interface was referenced by `Config`'s JSON-Schema diff --git a/test/queues/workflows/parallelTaskWorkflow.ts b/test/queues/workflows/parallelTaskWorkflow.ts index 1ae2d8ddd..ad755d226 100644 --- a/test/queues/workflows/parallelTaskWorkflow.ts +++ b/test/queues/workflows/parallelTaskWorkflow.ts @@ -2,9 +2,17 @@ import type { WorkflowConfig } from 'payload' export const parallelTaskWorkflow: WorkflowConfig<'parallelTask'> = { slug: 'parallelTask', - inputSchema: [], + inputSchema: [ + { + name: 'amount', + type: 'number', + required: true, + }, + ], handler: async ({ job, inlineTask }) => { - const taskIDs = Array.from({ length: 500 }, (_, i) => i + 1).map((i) => i.toString()) + const taskIDs = Array.from({ length: job.input.amount }, (_, i) => i + 1).map((i) => + i.toString(), + ) await Promise.all( taskIDs.map(async (taskID) => { diff --git a/test/relationships/int.spec.ts b/test/relationships/int.spec.ts index 0473db152..d8deded0a 100644 --- a/test/relationships/int.spec.ts +++ b/test/relationships/int.spec.ts @@ -49,9 +49,7 @@ describe('Relationships', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/test/select/int.spec.ts b/test/select/int.spec.ts index 31983fa03..851c5d228 100644 --- a/test/select/int.spec.ts +++ b/test/select/int.spec.ts @@ -36,9 +36,7 @@ describe('Select', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Local API - Base', () => { @@ -2153,7 +2151,7 @@ describe('Select', () => { it('graphQL - should retrieve fields against defaultPopulate', async () => { const query = `query { Pages { - docs { + docs { id, content { ... on Introduction { @@ -2161,7 +2159,7 @@ describe('Select', () => { doc { id, additional, - slug, + slug, } }, richTextLexical(depth: 1) diff --git a/test/sort/int.spec.ts b/test/sort/int.spec.ts index 2e18887dd..a71827ce0 100644 --- a/test/sort/int.spec.ts +++ b/test/sort/int.spec.ts @@ -25,9 +25,7 @@ describe('Sort', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('Local API', () => { diff --git a/test/storage-s3/int.spec.ts b/test/storage-s3/int.spec.ts index 91b533ef9..6fa8fdf86 100644 --- a/test/storage-s3/int.spec.ts +++ b/test/storage-s3/int.spec.ts @@ -39,9 +39,7 @@ describe('@payloadcms/storage-s3', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) afterEach(async () => { await clearTestBucket() diff --git a/test/uploads/int.spec.ts b/test/uploads/int.spec.ts index 73b645213..e7ba4d54a 100644 --- a/test/uploads/int.spec.ts +++ b/test/uploads/int.spec.ts @@ -37,9 +37,7 @@ describe('Collections - Uploads', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) describe('REST API', () => { diff --git a/test/versions/int.spec.ts b/test/versions/int.spec.ts index 097e22431..545d2fa7c 100644 --- a/test/versions/int.spec.ts +++ b/test/versions/int.spec.ts @@ -56,9 +56,7 @@ describe('Versions', () => { }) afterAll(async () => { - if (typeof payload.db.destroy === 'function') { - await payload.db.destroy() - } + await payload.destroy() }) beforeEach(async () => { diff --git a/tsconfig.base.json b/tsconfig.base.json index 15f492b2d..8d0bb793b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -31,7 +31,7 @@ } ], "paths": { - "@payload-config": ["./test/access-control/config.ts"], + "@payload-config": ["./test/_community/config.ts"], "@payloadcms/admin-bar": ["./packages/admin-bar/src"], "@payloadcms/live-preview": ["./packages/live-preview/src"], "@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],