fix: replace ESM-only uuid package with built-in crypto.randomUUID
All checks were successful
CI/CD Pipeline - Apartment API / Scan Dependencies (pull_request) Successful in 13s
CI/CD Pipeline - Apartment API / Lint & Test (pull_request) Successful in 41s
CI/CD Pipeline - Apartment API / Send Webhook Notification (pull_request) Successful in 2s
CI/CD Pipeline - Apartment API / Build & Push Image (pull_request) Has been skipped
CI/CD Pipeline - Apartment API / Deploy to Production (pull_request) Has been skipped

The uuid v13 package is ESM-only, which causes Jest to fail when
loading routes/admin.js -> jobs/scraperJob.js -> uuid without mocks.
This broke all admin dashboard tests (phase1-4) with silent 404s.

Switched to Node.js built-in crypto.randomUUID() and updated all
test mocks from uuid to crypto accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-06 22:05:31 -07:00
parent c30b02681e
commit 7e796295cb
2 changed files with 97 additions and 69 deletions

View File

@ -18,9 +18,10 @@ jest.mock('../../services/scraperLogger', () => ({
})) }))
})); }));
// Mock uuid // Mock crypto.randomUUID
jest.mock('uuid', () => ({ jest.mock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid-1234') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid-1234')
})); }));
// Mock scraperService // Mock scraperService
@ -256,8 +257,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -293,8 +295,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -325,8 +328,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -369,8 +373,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -410,8 +415,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -446,8 +452,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -481,8 +488,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { initializeScheduler: freshInit } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit } = require('../../jobs/scraperJob');
@ -518,8 +526,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const freshCron = require('node-cron'); const freshCron = require('node-cron');
@ -564,8 +573,9 @@ describe('scraperJob - scheduler', () => {
info: jest.fn(), warn: jest.fn(), error: jest.fn() info: jest.fn(), warn: jest.fn(), error: jest.fn()
})) }))
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'scheduled-job-id') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'scheduled-job-id')
})); }));
const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob');
@ -609,8 +619,9 @@ describe('scraperJob - scheduler', () => {
info: jest.fn(), warn: jest.fn(), error: jest.fn() info: jest.fn(), warn: jest.fn(), error: jest.fn()
})) }))
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'job-release-test') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'job-release-test')
})); }));
const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob');
@ -649,8 +660,9 @@ describe('scraperJob - scheduler', () => {
info: jest.fn(), warn: jest.fn(), error: jest.fn() info: jest.fn(), warn: jest.fn(), error: jest.fn()
})) }))
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'job-error-test') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'job-error-test')
})); }));
const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, isScraperRunning: freshIsRunning } = require('../../jobs/scraperJob');
@ -688,8 +700,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperLogger', () => ({ jest.doMock('../../services/scraperLogger', () => ({
createLogger: jest.fn(() => freshLogger) createLogger: jest.fn(() => freshLogger)
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'job-skip-test') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'job-skip-test')
})); }));
const { initializeScheduler: freshInit, acquireLock: freshAcquire } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, acquireLock: freshAcquire } = require('../../jobs/scraperJob');
@ -731,8 +744,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { initializeScheduler: freshInit, stopScheduler: freshStop } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, stopScheduler: freshStop } = require('../../jobs/scraperJob');
@ -770,8 +784,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { initializeScheduler: freshInit, gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob');
@ -802,8 +817,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { const {
@ -855,8 +871,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperLogger', () => ({ jest.doMock('../../services/scraperLogger', () => ({
createLogger: jest.fn(() => freshLogger) createLogger: jest.fn(() => freshLogger)
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'running-job-id') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'running-job-id')
})); }));
const { const {
@ -925,8 +942,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperLogger', () => ({ jest.doMock('../../services/scraperLogger', () => ({
createLogger: jest.fn(() => freshLogger) createLogger: jest.fn(() => freshLogger)
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'timeout-job-id') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'timeout-job-id')
})); }));
const { const {
@ -975,8 +993,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob'); const { gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob');
@ -1015,8 +1034,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob'); const { gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob');
@ -1047,8 +1067,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { const {
@ -1089,8 +1110,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { registerSignalHandlers: freshRegister } = require('../../jobs/scraperJob'); const { registerSignalHandlers: freshRegister } = require('../../jobs/scraperJob');
@ -1118,8 +1140,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { registerSignalHandlers: freshRegister } = require('../../jobs/scraperJob'); const { registerSignalHandlers: freshRegister } = require('../../jobs/scraperJob');
@ -1166,8 +1189,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { isShuttingDown: freshIsShuttingDown } = require('../../jobs/scraperJob'); const { isShuttingDown: freshIsShuttingDown } = require('../../jobs/scraperJob');
@ -1195,8 +1219,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { isShuttingDown: freshIsShuttingDown, gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob'); const { isShuttingDown: freshIsShuttingDown, gracefulShutdown: freshShutdown } = require('../../jobs/scraperJob');
@ -1228,8 +1253,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { gracefulShutdown } = require('../../jobs/scraperJob'); const { gracefulShutdown } = require('../../jobs/scraperJob');
@ -1256,8 +1282,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { isShuttingDown } = require('../../jobs/scraperJob'); const { isShuttingDown } = require('../../jobs/scraperJob');
@ -1284,8 +1311,9 @@ describe('scraperJob - scheduler', () => {
jest.doMock('../../services/scraperService', () => ({ jest.doMock('../../services/scraperService', () => ({
runScrape: jest.fn() runScrape: jest.fn()
})); }));
jest.doMock('uuid', () => ({ jest.doMock('crypto', () => ({
v4: jest.fn(() => 'mock-uuid') ...jest.requireActual('crypto'),
randomUUID: jest.fn(() => 'mock-uuid')
})); }));
const { registerSignalHandlers } = require('../../jobs/scraperJob'); const { registerSignalHandlers } = require('../../jobs/scraperJob');
@ -1307,7 +1335,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { getScheduleExpression: freshGetExpr } = require('../../jobs/scraperJob'); const { getScheduleExpression: freshGetExpr } = require('../../jobs/scraperJob');
@ -1327,7 +1355,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { getScheduleExpression: freshGetExpr } = require('../../jobs/scraperJob'); const { getScheduleExpression: freshGetExpr } = require('../../jobs/scraperJob');
@ -1349,7 +1377,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1369,7 +1397,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1393,7 +1421,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1421,7 +1449,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1451,7 +1479,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1476,7 +1504,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: utcInit, getNextScheduledRun: utcGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: utcInit, getNextScheduledRun: utcGetNext } = require('../../jobs/scraperJob');
@ -1507,7 +1535,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');
@ -1539,7 +1567,7 @@ describe('scraperJob - scheduler', () => {
createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() })) createLogger: jest.fn(() => ({ info: jest.fn(), warn: jest.fn(), error: jest.fn() }))
})); }));
jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() })); jest.doMock('../../services/scraperService', () => ({ runScrape: jest.fn() }));
jest.doMock('uuid', () => ({ v4: jest.fn(() => 'mock-uuid') })); jest.doMock('crypto', () => ({ ...jest.requireActual('crypto'), randomUUID: jest.fn(() => 'mock-uuid') }));
const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob'); const { initializeScheduler: freshInit, getNextScheduledRun: freshGetNext } = require('../../jobs/scraperJob');

View File

@ -1,8 +1,8 @@
const cron = require('node-cron'); const cron = require('node-cron');
const crypto = require('crypto');
const config = require('../config/scraper'); const config = require('../config/scraper');
const { runScrape } = require('../services/scraperService'); const { runScrape } = require('../services/scraperService');
const { createLogger } = require('../services/scraperLogger'); const { createLogger } = require('../services/scraperLogger');
const { v4: uuidv4 } = require('uuid');
// In-process mutex state // In-process mutex state
let isRunning = false; let isRunning = false;
@ -140,7 +140,7 @@ function initializeScheduler(db) {
// Create the scheduled job // Create the scheduled job
scheduledJob = cron.schedule(config.SCRAPER_SCHEDULE, async () => { scheduledJob = cron.schedule(config.SCRAPER_SCHEDULE, async () => {
const jobId = uuidv4(); const jobId = crypto.randomUUID();
const jobLogger = createLogger(jobId); const jobLogger = createLogger(jobId);
jobLogger.info('Scheduled scrape triggered'); jobLogger.info('Scheduled scrape triggered');