spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import { describe, expect, it } from 'vitest';2import { humanDuration, isStale, scheduleIntervalMs } from './schedule.js';34const H = 3600_000;5const D = 24 * H;67describe('scheduleIntervalMs', () => {8 it('classifies the manifest schedules', () => {9 expect(scheduleIntervalMs('0 2 * * *')).toBe(D); // civic daily10 expect(scheduleIntervalMs('30 2 * * *')).toBe(D); // clinicaltrials daily11 expect(scheduleIntervalMs('0 5 * * 2')).toBe(7 * D); // clinvar / hgnc weekly12 expect(scheduleIntervalMs('0 3 1 * *')).toBe(31 * D); // ncit-evs monthly13 expect(scheduleIntervalMs('0 7 1 7 *')).toBe(31 * D); // cdc-uscs yearly → treated as monthly floor14 expect(scheduleIntervalMs('15 * * * *')).toBe(H); // health probe hourly15 expect(scheduleIntervalMs('*/10 * * * *')).toBe(10 * 60_000);16 expect(scheduleIntervalMs('0 */6 * * *')).toBe(6 * H);17 expect(scheduleIntervalMs('0 2,14 * * *')).toBe(12 * H);18 expect(scheduleIntervalMs('0 4 * * 1,4')).toBe(3.5 * D);19 });20 it('returns null for malformed / missing expressions', () => {21 expect(scheduleIntervalMs(undefined)).toBeNull();22 expect(scheduleIntervalMs('')).toBeNull();23 expect(scheduleIntervalMs('0 6 15 1,7 * *')).toBeNull(); // 6 fields24 });25});2627describe('isStale', () => {28 const now = Date.parse('2026-09-08T12:00:00Z');29 it('flags no success within 2× the interval', () => {30 expect(isStale(new Date(now - 1.5 * D), '0 2 * * *', now).stale).toBe(false);31 expect(isStale(new Date(now - 2.5 * D), '0 2 * * *', now).stale).toBe(true);32 expect(isStale(new Date(now - 10 * D), '0 5 * * 2', now).stale).toBe(false);33 expect(isStale(new Date(now - 15 * D), '0 5 * * 2', now).stale).toBe(true);34 });35 it('never-succeeded scheduled connectors are stale; unscheduled ones never are', () => {36 expect(isStale(null, '0 2 * * *', now)).toMatchObject({ stale: true, ageMs: null, limitMs: 2 * D });37 expect(isStale(null, undefined, now).stale).toBe(false);38 expect(isStale(new Date(now - 100 * D), null, now).stale).toBe(false);39 });40});4142describe('humanDuration', () => {43 it('formats', () => {44 expect(humanDuration(30_000)).toBe('30 s');45 expect(humanDuration(5 * 60_000)).toBe('5 min');46 expect(humanDuration(3 * H + 5 * 60_000)).toBe('3 h 5 min');47 expect(humanDuration(3 * D + 2 * H)).toBe('3 d 2 h');48 expect(humanDuration(null)).toBe('-');49 });50});51