import { describe, expect, it } from 'vitest'; import { formatWecomReportMarkdown, wecomReportCutoff, wecomReportDueAt, wecomReportPeriod, wecomReportShouldFire, } from './wecom-report'; const emptyStats = { usersTotal: 10, usersIncrement: 2, partnersTotal: 3, partnersIncrement: 1, storesTotal: 4, storesIncrement: 0, ordersTotal: 20, ordersIncrement: 5, orderAmountTotal: 1000, orderAmountIncrement: 80.5, redeemsTotal: 8, redeemsIncrement: 3, redeemAmountTotal: 200, redeemAmountIncrement: 40, }; describe('wecomReportPeriod', () => { it('daily is the Shanghai calendar day', () => { const p = wecomReportPeriod('daily', new Date('2026-09-02T20:00:00+08:00')); expect(p.periodKey).toBe('2026-09-02'); expect(p.incrementLabel).toBe('当日新增'); expect(p.start.toISOString()).toBe(new Date('2026-09-02T00:00:00+08:00').toISOString()); }); it('weekly is the previous natural week', () => { const p = wecomReportPeriod('weekly', new Date('2026-09-02T09:00:00+08:00')); expect(p.periodKey).toBe('2026-08-24'); expect(p.rangeLabel).toBe('2026-08-24 ~ 2026-08-30'); expect(p.incrementLabel).toBe('本期新增'); }); it('monthly is the previous natural month', () => { const p = wecomReportPeriod('monthly', new Date('2026-09-01T09:00:00+08:00')); expect(p.periodKey).toBe('2026-08'); expect(p.title).toBe('月报(2026年8月)'); }); }); describe('wecomReportCutoff', () => { it('caps an in-progress daily period at now', () => { const now = new Date('2026-09-02T20:00:00+08:00'); const p = wecomReportPeriod('daily', now); expect(wecomReportCutoff(p, now).getTime()).toBe(now.getTime()); }); it('uses period end for a completed week', () => { const now = new Date('2026-09-02T09:00:00+08:00'); const p = wecomReportPeriod('weekly', now); expect(wecomReportCutoff(p, now).getTime()).toBe(p.endExclusive.getTime()); }); }); describe('wecomReportShouldFire', () => { const base = { enabled: true, sendHour: 20, sendMinute: 0, sendWeekday: 1, sendMonthDay: 1, lastSentPeriod: null as string | null, }; it('does not fire before due time', () => { expect( wecomReportShouldFire('daily', base, new Date('2026-09-02T19:59:00+08:00')), ).toBe(false); }); it('fires after due time if this period not sent', () => { expect( wecomReportShouldFire('daily', base, new Date('2026-09-02T20:00:00+08:00')), ).toBe(true); }); it('does not fire twice for the same period', () => { expect( wecomReportShouldFire( 'daily', { ...base, lastSentPeriod: '2026-09-02' }, new Date('2026-09-02T21:00:00+08:00'), ), ).toBe(false); }); it('weekly fires Monday 09:00 for last week', () => { expect( wecomReportShouldFire( 'weekly', { ...base, sendHour: 9, sendMinute: 0, sendWeekday: 1 }, new Date('2026-09-07T09:00:00+08:00'), ), ).toBe(true); }); }); describe('wecomReportDueAt', () => { it('monthly clamps to last day of month', () => { const due = wecomReportDueAt( 'monthly', { enabled: true, sendHour: 9, sendMinute: 0, sendWeekday: 1, sendMonthDay: 31, lastSentPeriod: null, }, new Date('2026-09-10T00:00:00+08:00'), ); expect(due.toISOString()).toBe(new Date('2026-09-30T09:00:00+08:00').toISOString()); }); }); describe('formatWecomReportMarkdown', () => { it('renders stock plus increment lines', () => { const p = wecomReportPeriod('daily', new Date('2026-09-02T20:00:00+08:00')); const md = formatWecomReportMarkdown(p, emptyStats); expect(md).toContain('**杜康好客 · 日报(2026-09-02)**'); expect(md).toContain('用户数量:10(当日新增 2)'); expect(md).toContain('订单金额:1000.00(当日新增 80.50)'); expect(md).toContain('核销单数量:8(当日新增 3)'); }); });