mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
8 changed files with 211 additions and 9 deletions
@ -0,0 +1,140 @@ |
|||
import { SchedulerRegistry } from '@nestjs/schedule'; |
|||
|
|||
import { CronService } from './cron.service'; |
|||
|
|||
describe('CronService', () => { |
|||
let configurationService: { get: jest.Mock }; |
|||
let cronService: CronService; |
|||
let dataGatheringService: { |
|||
gatherHourlyMarketData: jest.Mock; |
|||
gatherRecentMarketData: jest.Mock; |
|||
}; |
|||
let propertyService: { getByKey: jest.Mock }; |
|||
let schedulerRegistry: SchedulerRegistry; |
|||
|
|||
const createCronService = (intervalInMinutes: number) => { |
|||
configurationService.get.mockReturnValue(intervalInMinutes); |
|||
|
|||
return new CronService( |
|||
configurationService as never, |
|||
dataGatheringService as never, |
|||
propertyService as never, |
|||
schedulerRegistry, |
|||
{} as never, |
|||
{} as never, |
|||
{} as never |
|||
); |
|||
}; |
|||
|
|||
beforeEach(() => { |
|||
jest.useFakeTimers(); |
|||
|
|||
configurationService = { get: jest.fn() }; |
|||
dataGatheringService = { |
|||
gatherHourlyMarketData: jest.fn().mockResolvedValue(undefined), |
|||
gatherRecentMarketData: jest.fn().mockResolvedValue(undefined) |
|||
}; |
|||
propertyService = { getByKey: jest.fn().mockResolvedValue(undefined) }; |
|||
schedulerRegistry = new SchedulerRegistry(); |
|||
}); |
|||
|
|||
afterEach(() => { |
|||
cronService?.onModuleDestroy(); |
|||
|
|||
jest.useRealTimers(); |
|||
}); |
|||
|
|||
it('gathers the market data every hour by default', async () => { |
|||
cronService = createCronService(60); |
|||
cronService.onModuleInit(); |
|||
|
|||
await jest.advanceTimersByTimeAsync(59 * 60 * 1000); |
|||
expect(dataGatheringService.gatherHourlyMarketData).not.toHaveBeenCalled(); |
|||
|
|||
await jest.advanceTimersByTimeAsync(60 * 1000); |
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
1 |
|||
); |
|||
expect(dataGatheringService.gatherRecentMarketData).toHaveBeenCalledTimes( |
|||
1 |
|||
); |
|||
}); |
|||
|
|||
it('gathers the market data in the configured interval', async () => { |
|||
cronService = createCronService(5); |
|||
cronService.onModuleInit(); |
|||
|
|||
await jest.advanceTimersByTimeAsync(15 * 60 * 1000); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
3 |
|||
); |
|||
}); |
|||
|
|||
it('does not gather more often than once per minute', async () => { |
|||
cronService = createCronService(0); |
|||
cronService.onModuleInit(); |
|||
|
|||
await jest.advanceTimersByTimeAsync(60 * 1000); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
1 |
|||
); |
|||
}); |
|||
|
|||
it('does not gather the market data if the data gathering is disabled', async () => { |
|||
propertyService.getByKey.mockResolvedValue(false); |
|||
|
|||
cronService = createCronService(60); |
|||
await cronService.runHourlyMarketDataGathering(); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).not.toHaveBeenCalled(); |
|||
}); |
|||
|
|||
it('skips a run while the previous run is still in progress', async () => { |
|||
let finish: () => void = () => undefined; |
|||
|
|||
dataGatheringService.gatherHourlyMarketData.mockReturnValue( |
|||
new Promise<void>((resolve) => { |
|||
finish = resolve; |
|||
}) |
|||
); |
|||
|
|||
cronService = createCronService(60); |
|||
|
|||
const firstRun = cronService.runHourlyMarketDataGathering(); |
|||
|
|||
// Let the first run reach the pending data gathering
|
|||
await jest.advanceTimersByTimeAsync(0); |
|||
|
|||
await cronService.runHourlyMarketDataGathering(); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
1 |
|||
); |
|||
|
|||
finish(); |
|||
await firstRun; |
|||
|
|||
await cronService.runHourlyMarketDataGathering(); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
2 |
|||
); |
|||
}); |
|||
|
|||
it('keeps running after a failed run', async () => { |
|||
dataGatheringService.gatherHourlyMarketData.mockRejectedValueOnce( |
|||
new Error('Provider unavailable') |
|||
); |
|||
|
|||
cronService = createCronService(60); |
|||
|
|||
await cronService.runHourlyMarketDataGathering(); |
|||
await cronService.runHourlyMarketDataGathering(); |
|||
|
|||
expect(dataGatheringService.gatherHourlyMarketData).toHaveBeenCalledTimes( |
|||
2 |
|||
); |
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue