import { describe, expect, it } from 'vitest' import { buckets, expired, inventoryExpired, parseDashboardDrilldown, previousDate } from './dashboardNavigation' import type { QueryContext } from './types' const context: QueryContext = { salesRunId: '11', inventoryRunId: '12', salesScopeHash: 'sales', inventoryScopeHash: 'stock', queryAsOf: '2026-10-13T00:00:00Z', queryExpiresAt: '2026-10-13T00:30:00Z', businessTimezone: 'Asia/Shanghai', anchorDate: '2026-10-13', rangeStartDate: '2026-09-29', rangeEndDateExclusive: '2026-10-14', inventoryDrilldownExpiresAt: '2026-10-13T00:10:00Z' } const base = { from: 'overview', warehouseCode: 'WH-A', context: JSON.stringify(context), overviewReturn: JSON.stringify({ rangePreset: 'LAST_15_DAYS', scroll: 650 }) } describe('dashboard exact drilldown contract', () => { it.each(buckets)('maps $code to exact server bucket rather than an attention approximation', ({ code }) => { const parsed = parseDashboardDrilldown({ ...base, coverageBucket: code, bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1' }, 'inventory')! expect(parsed.inventory).toMatchObject({ coverageBucket: code, bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1', drilldownFrom: 'DASHBOARD', attention: 'ALL' }) expect(parsed.context).toEqual(context) expect(parsed).toMatchObject({ rangePreset: 'CUSTOM', startDate: '2026-09-29', endDate: '2026-10-13' }) expect(parsed.returnTo).toEqual({ rangePreset: 'LAST_15_DAYS', scroll: 650 }) }) it('preserves exact owner/SKU, maps hot enum and the independent finite candidate selector', () => { expect(parseDashboardDrilldown({ ...base, analysis: 'HOT', rangePreset: 'CUSTOM', startDate: '2026-09-13', endDate: '2026-10-12', customerCode: 'OWNER-B', sku: 'SKU-X' }, 'sales')).toMatchObject({ customerCode: 'OWNER-B', analysis: 'hot' }) expect(parseDashboardDrilldown({ ...base, coverageSelection: 'FINITE_POSITIVE', sortBy: 'COVERAGE_DAYS_DESC' }, 'inventory')?.inventory).toMatchObject({ coverageSelection: 'FINITE_POSITIVE', sortBy: 'COVERAGE_DAYS_DESC' }) expect(parseDashboardDrilldown({ ...base, analysis: 'SKU', rangePreset: 'CUSTOM', startDate: '2026-10-12', endDate: '2026-10-12' }, 'sales')).toMatchObject({ analysis: 'summary', startDate: '2026-10-12', endDate: '2026-10-12' }) }) it.each([ { coverageBucket: 'BAD', bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1' }, { coverageBucket: 'DAYS_GT_90', bucketRuleVersion: 'BAD' }, { bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1' }, { coverageBucket: 'DAYS_GT_90', bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1', attention: 'NO_OUTBOUND_IN_WINDOW' }, { coverageSelection: 'FINITE_POSITIVE', attention: 'NO_OUTBOUND_IN_WINDOW' }, { coverageSelection: 'FINITE_POSITIVE', coverageBucket: 'UNKNOWN', bucketRuleVersion: 'COVERAGE_DISTRIBUTION_V1' }, { context: '{}' }, { context: JSON.stringify({ ...context, rangeStartDate: undefined }) }, { context: JSON.stringify({ ...context, rangeEndDateExclusive: '2026-09-01' }) }, { warehouseCode: '' }, { drilldownFrom: 'OTHER' }, ])('rejects malformed/conflicting parameters without widening to the whole warehouse: %j', invalid => { expect(() => parseDashboardDrilldown(Object.fromEntries(Object.entries({ ...base, ...invalid }).filter(([, value]) => value !== undefined)) as Record, 'inventory')).toThrow() }) it('rejects invalid date/analysis/source and keeps warehouse selection mandatory', () => { expect(parseDashboardDrilldown({ ...base, analysis: 'HOT', rangePreset: 'CUSTOM', startDate: '2026-09-01', endDate: '2026-10-13' }, 'sales')).toMatchObject({ analysis: 'hot', rangePreset: 'CUSTOM', startDate: '2026-09-01', endDate: '2026-10-13' }) expect(() => parseDashboardDrilldown({ ...base, analysis: 'HOT', windowDays: '30' }, 'sales')).toThrow() expect(() => parseDashboardDrilldown({ ...base, analysis: 'HOT', rangePreset: 'CUSTOM', startDate: '2026-10-13', endDate: '2026-10-12' }, 'sales')).toThrow() expect(() => parseDashboardDrilldown({ ...base, analysis: 'ALL' }, 'sales')).toThrow() expect(() => parseDashboardDrilldown({ ...base, analysis: 'SKU', rangePreset: 'CUSTOM', startDate: '2026-02-30', endDate: '2026-02-30' }, 'sales')).toThrow() expect(() => parseDashboardDrilldown({ ...base, from: 'https://example.com' }, 'sales')).toThrow() expect(() => parseDashboardDrilldown({ coverageBucket: 'UNKNOWN' }, 'inventory')).toThrow() }) it('expires inventory earlier without expiring sales and subtracts date boundaries without local timezone drift', () => { const now = Date.parse('2026-10-13T00:15:00Z') expect(inventoryExpired(context, now)).toBe(true) expect(expired(context, now)).toBe(false) expect(previousDate('2026-03-01')).toBe('2026-02-28') }) })