fix(tests): raise jest timeouts to the 120s convention (stable) (#902)
Stable backport combining #860 (never reached stable) and #900: - jest.config.js gains testTimeout: 120000 — stable still ran on Jest's 5s default for anything unpinned, while its migration chain (134 core migrations via backports) is nearly as long as beta's. - All 19 suite-level jest.setTimeout(30000/60000) pins raised to 120s; local pins override the config default (#860's rationale). - All 15 hook-ARGUMENT timeout pins on migration-booting beforeAll hooks raised to 120s (#900's rationale — the 3.97.0-beta.0 release PR failed on exactly this class on the beta side). Untouched: the three suites whose pinned hooks don't run migrations (webhookDelivery, imageProcessor.storage, storageBackend) and publicQuotes' 30s pin on the rate-limit lockout test. No test logic changed. Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
a7885846ac
commit
962f1d9586
@@ -40,7 +40,7 @@ jest.mock('../../src/middleware/permissions', () => ({
|
|||||||
requirePermission: () => (_req, _res, next) => next(),
|
requirePermission: () => (_req, _res, next) => next(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('GET /api/admin/system-health/backup-coverage', () => {
|
describe('GET /api/admin/system-health/backup-coverage', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jest.mock('../../src/middleware/permissions', () => ({
|
|||||||
requirePermission: () => (_req, _res, next) => next(),
|
requirePermission: () => (_req, _res, next) => next(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('GET /api/admin/system-health/backup-integrity', () => {
|
describe('GET /api/admin/system-health/backup-integrity', () => {
|
||||||
let cleanup;
|
let cleanup;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const path = require('path');
|
|||||||
|
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('backupService — configurable walker (backup_paths)', () => {
|
describe('backupService — configurable walker (backup_paths)', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jest.mock('../../src/services/databaseBackup', () => ({
|
|||||||
DatabaseBackupService: class {},
|
DatabaseBackupService: class {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('backupService — inline DB dump + fail-loud guard', () => {
|
describe('backupService — inline DB dump + fail-loud guard', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const path = require('path');
|
|||||||
|
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('backupService — per-Stage-B-path statistics', () => {
|
describe('backupService — per-Stage-B-path statistics', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const path = require('path');
|
|||||||
|
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('backupService — config + file collection + manifest (smoke)', () => {
|
describe('backupService — config + file collection + manifest (smoke)', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('booking cutover — draft invoices on hold', () => {
|
describe('booking cutover — draft invoices on hold', () => {
|
||||||
let db; let cleanup; let adminId; let customerId; let quoteService;
|
let db; let cleanup; let adminId; let customerId; let quoteService;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
|||||||
// Service-level CRM calls cold-require heavy modules (pdfService,
|
// Service-level CRM calls cold-require heavy modules (pdfService,
|
||||||
// nodemailer, etc.) on first use; the global 5 s per-test budget is
|
// nodemailer, etc.) on first use; the global 5 s per-test budget is
|
||||||
// too tight for that. Bump it for this file only.
|
// too tight for that. Bump it for this file only.
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('discount line items (negative unit_price_minor)', () => {
|
describe('discount line items (negative unit_price_minor)', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
||||||
|
|
||||||
// bootCrmDb runs the full core-migration set in beforeAll.
|
// bootCrmDb runs the full core-migration set in beforeAll.
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('event type slug rename cascade', () => {
|
describe('event type slug rename cascade', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const request = require('supertest');
|
|||||||
|
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db; let cleanup; let service; let app;
|
let db; let cleanup; let service; let app;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db; let cleanup; let service; let adminId;
|
let db; let cleanup; let service; let adminId;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
|||||||
|
|
||||||
// Service-level CRM calls cold-require heavy modules (pdfService, nodemailer)
|
// Service-level CRM calls cold-require heavy modules (pdfService, nodemailer)
|
||||||
// on first use; bump the budget for this file.
|
// on first use; bump the budget for this file.
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('incoming-invoice categorise / re-bill chain', () => {
|
describe('incoming-invoice categorise / re-bill chain', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ jest.mock('../../src/services/restoreService', () => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('installFromBackupBoot', () => {
|
describe('installFromBackupBoot', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const { bootCrmDb, seedMinimal } = require('./helpers/crmDb');
|
|||||||
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
||||||
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
||||||
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let cleanup;
|
let cleanup;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ beforeAll(async () => {
|
|||||||
({ db, cleanup, tmpDir } = await bootCrmDb());
|
({ db, cleanup, tmpDir } = await bootCrmDb());
|
||||||
process.env.STORAGE_PATH = tmpDir; // isolate file collection to the temp dir
|
process.env.STORAGE_PATH = tmpDir; // isolate file collection to the temp dir
|
||||||
({ createPicpeak } = require('../../src/services/picpeakExportService'));
|
({ createPicpeak } = require('../../src/services/picpeakExportService'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanup();
|
await cleanup();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ beforeAll(async () => {
|
|||||||
({ importFromPicpeak, validateManifest } = require('../../src/services/picpeakImportService'));
|
({ importFromPicpeak, validateManifest } = require('../../src/services/picpeakImportService'));
|
||||||
const role = await db('roles').where({ name: 'super_admin' }).first();
|
const role = await db('roles').where({ name: 'super_admin' }).first();
|
||||||
superAdminRoleId = role.id;
|
superAdminRoleId = role.id;
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanup();
|
await cleanup();
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ const { execFileSync } = require('child_process');
|
|||||||
|
|
||||||
const { bootCrmDb } = require('./helpers/crmDb');
|
const { bootCrmDb } = require('./helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let cleanup;
|
let cleanup;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
({ db, cleanup } = await bootCrmDb());
|
({ db, cleanup } = await bootCrmDb());
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ beforeAll(async () => {
|
|||||||
setupService = require('../../src/services/setupService');
|
setupService = require('../../src/services/setupService');
|
||||||
({ getAppSetting, upsertAppSetting } = require('../../src/utils/appSettings'));
|
({ getAppSetting, upsertAppSetting } = require('../../src/utils/appSettings'));
|
||||||
app = buildRouteApp('/api/setup', require('../../src/routes/setup'));
|
app = buildRouteApp('/api/setup', require('../../src/routes/setup'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanup();
|
await cleanup();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const { bootCrmDb } = require('./helpers/crmDb');
|
|||||||
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
||||||
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
||||||
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let cleanup;
|
let cleanup;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const {
|
|||||||
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
// bootCrmDb runs the full core-migration set in beforeAll; under full-suite
|
||||||
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
// parallel load on a small CI runner that can exceed the 5s default. Match the
|
||||||
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
// other migration-heavy CRM suites (discountLineItems, incomingInvoiceRebill).
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let cleanup;
|
let cleanup;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ describe('admin CRM routes — auth + permission gate', () => {
|
|||||||
// Invalid: signed with a different secret. adminAuth must reject.
|
// Invalid: signed with a different secret. adminAuth must reject.
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
invalidToken = jwt.sign({ id: adminId, type: 'admin' }, 'WRONG-SECRET', { issuer: 'picpeak-auth' });
|
invalidToken = jwt.sign({ id: adminId, type: 'admin' }, 'WRONG-SECRET', { issuer: 'picpeak-auth' });
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const {
|
|||||||
bootCrmDb, mintAdminToken, buildRouteApp,
|
bootCrmDb, mintAdminToken, buildRouteApp,
|
||||||
} = require('../integration/helpers/crmDb');
|
} = require('../integration/helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
let cleanup;
|
let cleanup;
|
||||||
@@ -95,7 +95,7 @@ beforeAll(async () => {
|
|||||||
({ db, cleanup } = await bootCrmDb());
|
({ db, cleanup } = await bootCrmDb());
|
||||||
adminApp = buildRouteApp('/api/admin/auth', require('../../src/routes/adminAuth'));
|
adminApp = buildRouteApp('/api/admin/auth', require('../../src/routes/adminAuth'));
|
||||||
authApp = buildRouteApp('/api/auth', require('../../src/routes/auth'));
|
authApp = buildRouteApp('/api/auth', require('../../src/routes/auth'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ describe('publicContracts routes', () => {
|
|||||||
contractId = inserted[0]?.id ?? inserted[0];
|
contractId = inserted[0]?.id ?? inserted[0];
|
||||||
|
|
||||||
app = buildRouteApp('/api/public/contracts', require('../../src/routes/publicContracts'));
|
app = buildRouteApp('/api/public/contracts', require('../../src/routes/publicContracts'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ describe('publicPaymentCheck routes', () => {
|
|||||||
({ db, cleanup } = await bootCrmDb());
|
({ db, cleanup } = await bootCrmDb());
|
||||||
await seedMinimal(db);
|
await seedMinimal(db);
|
||||||
app = buildRouteApp('/api/public/payment-check', require('../../src/routes/publicPaymentCheck'));
|
app = buildRouteApp('/api/public/payment-check', require('../../src/routes/publicPaymentCheck'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ describe('publicQuotes routes', () => {
|
|||||||
quoteId = inserted[0]?.id ?? inserted[0];
|
quoteId = inserted[0]?.id ?? inserted[0];
|
||||||
|
|
||||||
app = buildRouteApp('/api/public/quotes', require('../../src/routes/publicQuotes'));
|
app = buildRouteApp('/api/public/quotes', require('../../src/routes/publicQuotes'));
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ describe('admin Live Slideshow endpoints', () => {
|
|||||||
app.use((err, req, res, next) => {
|
app.use((err, req, res, next) => {
|
||||||
res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code });
|
res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code });
|
||||||
});
|
});
|
||||||
}, 30000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => { await cleanup(); });
|
afterAll(async () => { await cleanup(); });
|
||||||
|
|
||||||
|
|||||||
@@ -67,11 +67,10 @@ async function insertEvent(db, over = {}) {
|
|||||||
describe('public Live Slideshow routes', () => {
|
describe('public Live Slideshow routes', () => {
|
||||||
let db; let cleanup; let app;
|
let db; let cleanup; let app;
|
||||||
|
|
||||||
// bootCrmDb runs the full migration set against a fresh SQLite file, which
|
// bootCrmDb runs the full migration set against a fresh SQLite file and the
|
||||||
// takes <2s locally but has been observed to exceed Jest's default 5s
|
// chain keeps growing via backports. Hook-argument timeouts OVERRIDE the
|
||||||
// `beforeAll` timeout on slower GitHub Actions runners (~5.4s — runner-to-
|
// 120s jest.config default (same trap as the jest.setTimeout pins) — keep
|
||||||
// runner I/O variance). Raise the hook timeout so this doesn't intermittently
|
// this at 120000, matching the config.
|
||||||
// block PRs on CI; doesn't affect happy-path local runs.
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
({ db, cleanup } = await bootCrmDb());
|
({ db, cleanup } = await bootCrmDb());
|
||||||
await seedMinimal(db);
|
await seedMinimal(db);
|
||||||
@@ -86,7 +85,7 @@ describe('public Live Slideshow routes', () => {
|
|||||||
app.use((err, req, res, next) => {
|
app.use((err, req, res, next) => {
|
||||||
res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code });
|
res.status(err.statusCode || err.status || 500).json({ error: err.message, code: err.code });
|
||||||
});
|
});
|
||||||
}, 30000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => { await cleanup(); });
|
afterAll(async () => { await cleanup(); });
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const crypto = require('crypto');
|
|||||||
|
|
||||||
const { bootCrmDb, seedMinimal } = require('../integration/helpers/crmDb');
|
const { bootCrmDb, seedMinimal } = require('../integration/helpers/crmDb');
|
||||||
|
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
describe('backupIntegrityService.verifyDocumentArtefacts', () => {
|
describe('backupIntegrityService.verifyDocumentArtefacts', () => {
|
||||||
let db;
|
let db;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ let db; let cleanup;
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
({ db, cleanup } = await bootCrmDb());
|
({ db, cleanup } = await bootCrmDb());
|
||||||
}, 30000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => { if (cleanup) await cleanup(); });
|
afterAll(async () => { if (cleanup) await cleanup(); });
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ describe('userManagementService — activate + delete (#574 follow-up)', () => {
|
|||||||
is_active: 1, created_at: new Date(),
|
is_active: 1, created_at: new Date(),
|
||||||
}).returning('id');
|
}).returning('id');
|
||||||
targetId = targetInsert[0]?.id ?? targetInsert[0];
|
targetId = targetInsert[0]?.id ?? targetInsert[0];
|
||||||
}, 60000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (cleanup) await cleanup();
|
if (cleanup) await cleanup();
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ beforeAll(async () => {
|
|||||||
}).returning('id');
|
}).returning('id');
|
||||||
photoIds.push(r[0]?.id ?? r[0]);
|
photoIds.push(r[0]?.id ?? r[0]);
|
||||||
}
|
}
|
||||||
}, 30000);
|
}, 120000);
|
||||||
|
|
||||||
afterAll(async () => { if (cleanup) await cleanup(); });
|
afterAll(async () => { if (cleanup) await cleanup(); });
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
|
// bootCrmDb() runs EVERY core migration in beforeAll and the chain keeps
|
||||||
|
// growing (134 migrations and counting via backports). 120s matches the
|
||||||
|
// beta-branch convention from #860.
|
||||||
|
testTimeout: 120000,
|
||||||
coverageDirectory: 'coverage',
|
coverageDirectory: 'coverage',
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'src/**/*.js',
|
'src/**/*.js',
|
||||||
|
|||||||
Reference in New Issue
Block a user