import { describe, expect, it } from 'vitest'; import type { WorksTokenPointBalance } from '@/lib/works-square'; import { formatWorksTokenPointValue, isWorksTokenPointBalanceExhausted, } from '@/lib/works-square-token-points'; function pointBalance( overrides: Partial = {}, ): WorksTokenPointBalance { return { plan_code: 'mastery', plan_name: '精通', cycle_start: '2026-09-01T00:00:00Z', cycle_end: '2026-09-08T00:00:00Z', next_refresh_at: '2026-09-08T00:00:00Z', weekly_allowance: '500.00', weekly_used: '100.00', weekly_reserved: '25.00', weekly_remaining: '375.00', permanent_total: '50.00', permanent_used: '0.00', permanent_reserved: '0.00', permanent_remaining: '50.00', total_remaining: '425.00', entitlement_source: 'self', family_shared: false, can_manage_membership: true, upgrade_action: 'self_service', shared_available: null, ...overrides, }; } describe('Works Square V2 token points', () => { it('formats exact server point strings without losing integer precision', () => { expect(formatWorksTokenPointValue('1000.00')).toBe('1,000'); expect(formatWorksTokenPointValue('123456789012345678.50')).toBe('123,456,789,012,345,678.5'); expect(formatWorksTokenPointValue(null)).toBeNull(); expect(formatWorksTokenPointValue('-1.00')).toBeNull(); }); it('treats an exact zero total balance as exhausted for the owner', () => { expect(isWorksTokenPointBalanceExhausted(pointBalance({ total_remaining: '0.00' }))).toBe(true); expect(isWorksTokenPointBalanceExhausted(pointBalance())).toBe(false); expect(isWorksTokenPointBalanceExhausted(pointBalance({ total_remaining: null }))).toBe(false); }); it('uses the server-provided coarse availability for every non-manager', () => { const nonManager = pointBalance({ plan_code: null, plan_name: null, can_manage_membership: false, family_shared: false, upgrade_action: 'contact_family_owner', shared_available: false, total_remaining: null, }); expect(isWorksTokenPointBalanceExhausted(nonManager)).toBe(true); expect(isWorksTokenPointBalanceExhausted({ ...nonManager, shared_available: true })).toBe(false); expect(isWorksTokenPointBalanceExhausted({ ...nonManager, family_shared: true })).toBe(true); }); });