Files
lunarfront-app/packages/backend/__tests__/services/tax.test.ts
ryan 8256380cd1
All checks were successful
CI / ci (pull_request) Successful in 20s
CI / e2e (pull_request) Successful in 50s
feat: add cash rounding, POS test suite, and fix test harness port cleanup
- Add Swedish rounding (nearest nickel) for cash payments at locations with cash_rounding enabled
- Add rounding_adjustment column to transactions, cash_rounding to locations
- Add POS schema to database plugin for relational query support
- Complete/void routes now return full transaction with line items via getById
- Test harness killPort falls back to fuser when lsof unavailable (fixes stale process bug)
- Add 35-test POS API suite covering discounts, drawer, transactions, tax, rounding, e2e flow
- Add unit tests for tax service and POS Zod schemas

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 18:23:05 +00:00

120 lines
3.2 KiB
TypeScript

import { describe, it, expect } from 'bun:test'
import { TaxService } from '../../src/services/tax.service.js'
describe('TaxService.calculateTax', () => {
it('calculates tax on a simple amount', () => {
// 8.25% on $100
expect(TaxService.calculateTax(100, 0.0825)).toBe(8.25)
})
it('rounds to 2 decimal places', () => {
// 8.25% on $10.01 = 0.825825 → 0.83
expect(TaxService.calculateTax(10.01, 0.0825)).toBe(0.83)
})
it('returns 0 for zero rate', () => {
expect(TaxService.calculateTax(100, 0)).toBe(0)
})
it('returns 0 for zero amount', () => {
expect(TaxService.calculateTax(0, 0.0825)).toBe(0)
})
it('handles small amounts', () => {
// 8.25% on $0.99 = 0.081675 → 0.08
expect(TaxService.calculateTax(0.99, 0.0825)).toBe(0.08)
})
it('handles large amounts', () => {
// 8.25% on $9999.99 = 824.999175 → 825.00
expect(TaxService.calculateTax(9999.99, 0.0825)).toBe(825)
})
it('handles 5% service tax rate', () => {
// 5% on $60 = 3.00
expect(TaxService.calculateTax(60, 0.05)).toBe(3)
})
it('handles fractional cent rounding down', () => {
// 7% on $1.01 = 0.0707 → 0.07
expect(TaxService.calculateTax(1.01, 0.07)).toBe(0.07)
})
it('handles fractional cent rounding up', () => {
// 7% on $1.05 = 0.0735 → 0.07
expect(TaxService.calculateTax(1.05, 0.07)).toBe(0.07)
})
})
describe('TaxService.roundToNickel', () => {
it('rounds .01 down to .00', () => {
expect(TaxService.roundToNickel(10.01)).toBe(10.00)
})
it('rounds .02 down to .00', () => {
expect(TaxService.roundToNickel(10.02)).toBe(10.00)
})
it('rounds .03 up to .05', () => {
expect(TaxService.roundToNickel(10.03)).toBe(10.05)
})
it('rounds .04 up to .05', () => {
expect(TaxService.roundToNickel(10.04)).toBe(10.05)
})
it('keeps .05 as is', () => {
expect(TaxService.roundToNickel(10.05)).toBe(10.05)
})
it('rounds .06 down to .05', () => {
expect(TaxService.roundToNickel(10.06)).toBe(10.05)
})
it('rounds .07 down to .05', () => {
expect(TaxService.roundToNickel(10.07)).toBe(10.05)
})
it('rounds .08 up to .10', () => {
expect(TaxService.roundToNickel(10.08)).toBe(10.10)
})
it('rounds .09 up to .10', () => {
expect(TaxService.roundToNickel(10.09)).toBe(10.10)
})
it('keeps .00 as is', () => {
expect(TaxService.roundToNickel(10.00)).toBe(10.00)
})
it('keeps .10 as is', () => {
expect(TaxService.roundToNickel(10.10)).toBe(10.10)
})
it('handles zero', () => {
expect(TaxService.roundToNickel(0)).toBe(0)
})
})
describe('TaxService.repairItemTypeToTaxCategory', () => {
it('maps labor to service', () => {
expect(TaxService.repairItemTypeToTaxCategory('labor')).toBe('service')
})
it('maps part to goods', () => {
expect(TaxService.repairItemTypeToTaxCategory('part')).toBe('goods')
})
it('maps flat_rate to goods', () => {
expect(TaxService.repairItemTypeToTaxCategory('flat_rate')).toBe('goods')
})
it('maps misc to goods', () => {
expect(TaxService.repairItemTypeToTaxCategory('misc')).toBe('goods')
})
it('maps unknown type to goods (default)', () => {
expect(TaxService.repairItemTypeToTaxCategory('something_else')).toBe('goods')
})
})