import { describe, it, expect, beforeAll, afterAll } from 'vitest' import * as db from '../src/database.js' import { registerSubscription } from '../src/actions.js' import { getCronExpression } from '../src/alert.js' import { getJobCronSource, removeJob } from '../src/worker/email.js' import { registerSubscription as regSub } from '../src/worker/index.js' const pubkey = 'schedule-test-' + Date.now() const email = 'schedule-test-' + Date.now() + '@example.com' let sub: any = null describe('Schedule fields', () => { beforeAll(async () => { await db.migrate() }) it('inserts subscription with custom hour/minute/timezone', async () => { const s = await db.insertSubscription(pubkey, email, 'daily', 7, 30, undefined, 'America/New_York') expect(s).toBeTruthy() expect(s!.hour).toBe(7) expect(s!.minute).toBe(30) expect(s!.timezone).toBe('America/New_York') expect(s!.day_of_week).toBeNull() sub = s }) it('inserts subscription with custom weekly dayOfWeek', async () => { const pk2 = 'schedule-test-weekly-' + Date.now() const em2 = pk2 + '@example.com' const s = await db.insertSubscription(pk2, em2, 'weekly', 9, 0, 6, 'UTC') expect(s).toBeTruthy() expect(s!.hour).toBe(9) expect(s!.minute).toBe(0) expect(s!.day_of_week).toBe(6) expect(s!.timezone).toBe('UTC') }) it('inserts subscription with defaults when schedule omitted', async () => { const pk3 = 'schedule-test-defaults-' + Date.now() const em3 = pk3 + '@example.com' const s = await db.insertSubscription(pk3, em3, 'daily') expect(s).toBeTruthy() expect(s!.hour).toBe(17) expect(s!.minute).toBe(0) expect(s!.timezone).toBe('UTC') expect(s!.day_of_week).toBeNull() }) it('getCronExpression returns daily with custom hour/minute', () => { expect(getCronExpression('daily', 7, 30)).toBe('0 30 7 * * *') }) it('getCronExpression returns weekly with custom dayOfWeek', () => { expect(getCronExpression('weekly', 9, 0, 6)).toBe('0 0 9 * * 6') }) it('getCronExpression defaults to Monday for weekly', () => { expect(getCronExpression('weekly', 17, 0)).toBe('0 0 17 * * 1') }) it('confirms and registers job with custom schedule', async () => { // Confirm the daily subscription created above const confirmed = await db.confirmSubscription(sub.key) expect(confirmed).toBeTruthy() sub = confirmed!.sub regSub(sub) const dailySource = getJobCronSource(sub.id) // Expect 0 30 7 * * * (from custom hour=7, minute=30) expect(dailySource).toBe('0 30 7 * * *') }) it('updateSubscription preserves schedule fields through frequency change', async () => { const updated = await db.updateSubscription(sub, email, 'weekly', undefined, undefined, 2, undefined) expect(updated).toBeTruthy() expect(updated!.frequency).toBe('weekly') // hour/minute should keep the previously set values (7/30) since we passed undefined expect(updated!.hour).toBe(7) expect(updated!.minute).toBe(30) expect(updated!.day_of_week).toBe(2) expect(updated!.timezone).toBe('America/New_York') }) it('registerSubscription preserves schedule fields', async () => { await registerSubscription({ pubkey, email, frequency: 'daily', hour: 10, minute: 15, timezone: 'Europe/London' }) const reloaded = await db.getSubscriptionByPubkey(pubkey) expect(reloaded).toBeTruthy() expect(reloaded!.hour).toBe(10) expect(reloaded!.minute).toBe(15) expect(reloaded!.timezone).toBe('Europe/London') }) }) afterAll(async () => { const updated = await db.getSubscriptionByPubkey(pubkey) if (updated) removeJob(updated) })