diff --git a/backend/__tests__/integration/picpeakExport.test.js b/backend/__tests__/integration/picpeakExport.test.js index bb443d6c..70fa9f83 100644 --- a/backend/__tests__/integration/picpeakExport.test.js +++ b/backend/__tests__/integration/picpeakExport.test.js @@ -21,7 +21,7 @@ beforeAll(async () => { ({ db, cleanup, tmpDir } = await bootCrmDb()); process.env.STORAGE_PATH = tmpDir; // isolate file collection to the temp dir ({ createPicpeak } = require('../../src/services/picpeakExportService')); -}, 60000); +}, 120000); afterAll(async () => { await cleanup(); diff --git a/backend/__tests__/integration/picpeakRoundtrip.test.js b/backend/__tests__/integration/picpeakRoundtrip.test.js index 8e26de07..fcc6e7c6 100644 --- a/backend/__tests__/integration/picpeakRoundtrip.test.js +++ b/backend/__tests__/integration/picpeakRoundtrip.test.js @@ -28,7 +28,7 @@ beforeAll(async () => { ({ importFromPicpeak, validateManifest } = require('../../src/services/picpeakImportService')); const role = await db('roles').where({ name: 'super_admin' }).first(); superAdminRoleId = role.id; -}, 60000); +}, 120000); afterAll(async () => { await cleanup(); diff --git a/backend/__tests__/integration/resetAdminMfaCli.test.js b/backend/__tests__/integration/resetAdminMfaCli.test.js index 0b8414fb..f19fc528 100644 --- a/backend/__tests__/integration/resetAdminMfaCli.test.js +++ b/backend/__tests__/integration/resetAdminMfaCli.test.js @@ -20,7 +20,7 @@ let cleanup; beforeAll(async () => { ({ db, cleanup } = await bootCrmDb()); -}, 60000); +}, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/integration/setupService.test.js b/backend/__tests__/integration/setupService.test.js index 0f48f48d..7e4f234a 100644 --- a/backend/__tests__/integration/setupService.test.js +++ b/backend/__tests__/integration/setupService.test.js @@ -27,7 +27,7 @@ beforeAll(async () => { setupService = require('../../src/services/setupService'); ({ getAppSetting, upsertAppSetting } = require('../../src/utils/appSettings')); app = buildRouteApp('/api/setup', require('../../src/routes/setup')); -}, 60000); +}, 120000); afterAll(async () => { await cleanup(); diff --git a/backend/__tests__/routes/adminCrmAuth.test.js b/backend/__tests__/routes/adminCrmAuth.test.js index 3365994c..ef432827 100644 --- a/backend/__tests__/routes/adminCrmAuth.test.js +++ b/backend/__tests__/routes/adminCrmAuth.test.js @@ -83,7 +83,7 @@ describe('admin CRM routes — auth + permission gate', () => { // Invalid: signed with a different secret. adminAuth must reject. const jwt = require('jsonwebtoken'); invalidToken = jwt.sign({ id: adminId, type: 'admin' }, 'WRONG-SECRET', { issuer: 'picpeak-auth' }); - }, 60000); + }, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/routes/adminEventQr.test.js b/backend/__tests__/routes/adminEventQr.test.js index cfec5359..33b21cc5 100644 --- a/backend/__tests__/routes/adminEventQr.test.js +++ b/backend/__tests__/routes/adminEventQr.test.js @@ -105,7 +105,7 @@ describe('admin event QR endpoints', () => { expect(res.status).toBe(200); expect(res.headers['content-type']).toBe('application/pdf'); expect(res.body.slice(0, 4).toString()).toBe('%PDF'); - }, 30000); + }, 120000); it('409s when the event has no share link', async () => { // events.share_link is NOT NULL — an empty string is the closest real-world diff --git a/backend/__tests__/routes/adminMfa.test.js b/backend/__tests__/routes/adminMfa.test.js index 973c6456..0cfaabb3 100644 --- a/backend/__tests__/routes/adminMfa.test.js +++ b/backend/__tests__/routes/adminMfa.test.js @@ -95,7 +95,7 @@ beforeAll(async () => { ({ db, cleanup } = await bootCrmDb()); adminApp = buildRouteApp('/api/admin/auth', require('../../src/routes/adminAuth')); authApp = buildRouteApp('/api/auth', require('../../src/routes/auth')); -}, 60000); +}, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/routes/publicContracts.test.js b/backend/__tests__/routes/publicContracts.test.js index a1ed781c..c258f296 100644 --- a/backend/__tests__/routes/publicContracts.test.js +++ b/backend/__tests__/routes/publicContracts.test.js @@ -51,7 +51,7 @@ describe('publicContracts routes', () => { contractId = inserted[0]?.id ?? inserted[0]; app = buildRouteApp('/api/public/contracts', require('../../src/routes/publicContracts')); - }, 60000); + }, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/routes/publicPaymentCheck.test.js b/backend/__tests__/routes/publicPaymentCheck.test.js index ea5c0ee8..62a59023 100644 --- a/backend/__tests__/routes/publicPaymentCheck.test.js +++ b/backend/__tests__/routes/publicPaymentCheck.test.js @@ -33,7 +33,7 @@ describe('publicPaymentCheck routes', () => { ({ db, cleanup } = await bootCrmDb()); await seedMinimal(db); app = buildRouteApp('/api/public/payment-check', require('../../src/routes/publicPaymentCheck')); - }, 60000); + }, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/routes/publicQuotes.test.js b/backend/__tests__/routes/publicQuotes.test.js index f5234f71..0012bc60 100644 --- a/backend/__tests__/routes/publicQuotes.test.js +++ b/backend/__tests__/routes/publicQuotes.test.js @@ -60,7 +60,7 @@ describe('publicQuotes routes', () => { quoteId = inserted[0]?.id ?? inserted[0]; app = buildRouteApp('/api/public/quotes', require('../../src/routes/publicQuotes')); - }, 60000); + }, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/routes/slideshowAdmin.test.js b/backend/__tests__/routes/slideshowAdmin.test.js index ca277004..d8c9d876 100644 --- a/backend/__tests__/routes/slideshowAdmin.test.js +++ b/backend/__tests__/routes/slideshowAdmin.test.js @@ -75,7 +75,7 @@ describe('admin Live Slideshow endpoints', () => { app.use((err, req, res, next) => { res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code }); }); - }, 30000); + }, 120000); afterAll(async () => { await cleanup(); }); diff --git a/backend/__tests__/routes/slideshowPublic.test.js b/backend/__tests__/routes/slideshowPublic.test.js index 5a793922..af07d35b 100644 --- a/backend/__tests__/routes/slideshowPublic.test.js +++ b/backend/__tests__/routes/slideshowPublic.test.js @@ -67,11 +67,11 @@ async function insertEvent(db, over = {}) { describe('public Live Slideshow routes', () => { let db; let cleanup; let app; - // bootCrmDb runs the full migration set against a fresh SQLite file, which - // takes <2s locally but has been observed to exceed Jest's default 5s - // `beforeAll` timeout on slower GitHub Actions runners (~5.4s — runner-to- - // runner I/O variance). Raise the hook timeout so this doesn't intermittently - // block PRs on CI; doesn't affect happy-path local runs. + // bootCrmDb runs the full migration set against a fresh SQLite file. The + // chain keeps growing, and a 30s pin here blocked the 3.97.0-beta.0 + // release PR on a slow runner. Hook-argument timeouts OVERRIDE the 120s + // jest.config default (same trap as the jest.setTimeout pins raised in + // #860) — keep this at 120000, matching the config. beforeAll(async () => { ({ db, cleanup } = await bootCrmDb()); await seedMinimal(db); @@ -86,7 +86,7 @@ describe('public Live Slideshow routes', () => { app.use((err, req, res, next) => { res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code }); }); - }, 30000); + }, 120000); afterAll(async () => { await cleanup(); }); diff --git a/backend/__tests__/services/trackerFactory.test.js b/backend/__tests__/services/trackerFactory.test.js index 9bebee90..9b983350 100644 --- a/backend/__tests__/services/trackerFactory.test.js +++ b/backend/__tests__/services/trackerFactory.test.js @@ -27,7 +27,7 @@ let db; let cleanup; beforeAll(async () => { ({ db, cleanup } = await bootCrmDb()); -}, 30000); +}, 120000); afterAll(async () => { if (cleanup) await cleanup(); }); diff --git a/backend/__tests__/services/userManagementService.activateDelete.test.js b/backend/__tests__/services/userManagementService.activateDelete.test.js index 0c450afc..137b97d3 100644 --- a/backend/__tests__/services/userManagementService.activateDelete.test.js +++ b/backend/__tests__/services/userManagementService.activateDelete.test.js @@ -48,7 +48,7 @@ describe('userManagementService — activate + delete (#574 follow-up)', () => { is_active: 1, created_at: new Date(), }).returning('id'); targetId = targetInsert[0]?.id ?? targetInsert[0]; - }, 60000); + }, 120000); afterAll(async () => { if (cleanup) await cleanup(); diff --git a/backend/__tests__/utils/feedbackPerGuestLimit.test.js b/backend/__tests__/utils/feedbackPerGuestLimit.test.js index 40826e2d..dc2cfae0 100644 --- a/backend/__tests__/utils/feedbackPerGuestLimit.test.js +++ b/backend/__tests__/utils/feedbackPerGuestLimit.test.js @@ -115,7 +115,7 @@ beforeAll(async () => { }).returning('id'); photoIds.push(r[0]?.id ?? r[0]); } -}, 30000); +}, 120000); afterAll(async () => { if (cleanup) await cleanup(); }); diff --git a/backend/__tests__/utils/feedbackRatingRemoval.test.js b/backend/__tests__/utils/feedbackRatingRemoval.test.js index 56722570..0e0774ba 100644 --- a/backend/__tests__/utils/feedbackRatingRemoval.test.js +++ b/backend/__tests__/utils/feedbackRatingRemoval.test.js @@ -87,7 +87,7 @@ beforeAll(async () => { uploaded_at: new Date().toISOString(), }).returning('id'); photoId = r[0]?.id ?? r[0]; -}, 30000); +}, 120000); afterAll(async () => { if (cleanup) await cleanup(); });