Restructure tests into __tests__/ directories at package root so they can be excluded from production builds. Add unit tests for dates, currency, lookup service, payment method default logic, and tax exemption state transitions.
153 lines
5.1 KiB
TypeScript
153 lines
5.1 KiB
TypeScript
import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'bun:test'
|
|
import type { FastifyInstance } from 'fastify'
|
|
import { createTestApp, cleanDb, seedTestCompany, TEST_COMPANY_ID } from '../../src/test/helpers.js'
|
|
import { UnitStatusService, ItemConditionService } from '../../src/services/lookup.service.js'
|
|
|
|
describe('UnitStatusService', () => {
|
|
let app: FastifyInstance
|
|
|
|
beforeAll(async () => {
|
|
app = await createTestApp()
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
await cleanDb(app)
|
|
await seedTestCompany(app)
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await app.close()
|
|
})
|
|
|
|
describe('seedForCompany', () => {
|
|
it('seeds system statuses on first call', async () => {
|
|
const statuses = await UnitStatusService.list(app.db, TEST_COMPANY_ID)
|
|
expect(statuses.length).toBeGreaterThanOrEqual(8)
|
|
expect(statuses.every((s) => s.isSystem)).toBe(true)
|
|
})
|
|
|
|
it('is idempotent — second seed does not duplicate', async () => {
|
|
await UnitStatusService.seedForCompany(app.db, TEST_COMPANY_ID)
|
|
const statuses = await UnitStatusService.list(app.db, TEST_COMPANY_ID)
|
|
const slugs = statuses.map((s) => s.slug)
|
|
const uniqueSlugs = new Set(slugs)
|
|
expect(slugs.length).toBe(uniqueSlugs.size)
|
|
})
|
|
})
|
|
|
|
describe('getBySlug', () => {
|
|
it('returns a system status by slug', async () => {
|
|
const status = await UnitStatusService.getBySlug(app.db, TEST_COMPANY_ID, 'available')
|
|
expect(status).not.toBeNull()
|
|
expect(status!.slug).toBe('available')
|
|
expect(status!.isSystem).toBe(true)
|
|
})
|
|
|
|
it('returns null for nonexistent slug', async () => {
|
|
const status = await UnitStatusService.getBySlug(app.db, TEST_COMPANY_ID, 'nonexistent')
|
|
expect(status).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('validateSlug', () => {
|
|
it('returns true for valid active slug', async () => {
|
|
expect(await UnitStatusService.validateSlug(app.db, TEST_COMPANY_ID, 'sold')).toBe(true)
|
|
})
|
|
|
|
it('returns false for nonexistent slug', async () => {
|
|
expect(await UnitStatusService.validateSlug(app.db, TEST_COMPANY_ID, 'bogus')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('create', () => {
|
|
it('creates a custom (non-system) status', async () => {
|
|
const custom = await UnitStatusService.create(app.db, TEST_COMPANY_ID, {
|
|
name: 'In Transit',
|
|
slug: 'in_transit',
|
|
description: 'Being shipped between locations',
|
|
sortOrder: 99,
|
|
})
|
|
expect(custom.slug).toBe('in_transit')
|
|
expect(custom.isSystem).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('delete', () => {
|
|
it('throws when deleting a system status', async () => {
|
|
const system = await UnitStatusService.getBySlug(app.db, TEST_COMPANY_ID, 'available')
|
|
expect(system).not.toBeNull()
|
|
expect(() => UnitStatusService.delete(app.db, TEST_COMPANY_ID, system!.id)).toThrow('system')
|
|
})
|
|
|
|
it('deletes a custom status', async () => {
|
|
const custom = await UnitStatusService.create(app.db, TEST_COMPANY_ID, {
|
|
name: 'Temp',
|
|
slug: 'temp',
|
|
sortOrder: 0,
|
|
})
|
|
const deleted = await UnitStatusService.delete(app.db, TEST_COMPANY_ID, custom.id)
|
|
expect(deleted).not.toBeNull()
|
|
expect(deleted!.slug).toBe('temp')
|
|
})
|
|
|
|
it('returns null for nonexistent id', async () => {
|
|
const result = await UnitStatusService.delete(app.db, TEST_COMPANY_ID, '00000000-0000-0000-0000-000000000000')
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('update', () => {
|
|
it('throws when deactivating a system status', async () => {
|
|
const system = await UnitStatusService.getBySlug(app.db, TEST_COMPANY_ID, 'sold')
|
|
expect(() => UnitStatusService.update(app.db, TEST_COMPANY_ID, system!.id, { isActive: false })).toThrow('system')
|
|
})
|
|
|
|
it('allows renaming a custom status', async () => {
|
|
const custom = await UnitStatusService.create(app.db, TEST_COMPANY_ID, {
|
|
name: 'Old Name',
|
|
slug: 'custom_rename',
|
|
sortOrder: 0,
|
|
})
|
|
const updated = await UnitStatusService.update(app.db, TEST_COMPANY_ID, custom.id, { name: 'New Name' })
|
|
expect(updated!.name).toBe('New Name')
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('ItemConditionService', () => {
|
|
let app: FastifyInstance
|
|
|
|
beforeAll(async () => {
|
|
app = await createTestApp()
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
await cleanDb(app)
|
|
await seedTestCompany(app)
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await app.close()
|
|
})
|
|
|
|
it('seeds system conditions', async () => {
|
|
const conditions = await ItemConditionService.list(app.db, TEST_COMPANY_ID)
|
|
const slugs = conditions.map((c) => c.slug)
|
|
expect(slugs).toContain('new')
|
|
expect(slugs).toContain('excellent')
|
|
expect(slugs).toContain('good')
|
|
expect(slugs).toContain('fair')
|
|
expect(slugs).toContain('poor')
|
|
})
|
|
|
|
it('creates a custom condition', async () => {
|
|
const custom = await ItemConditionService.create(app.db, TEST_COMPANY_ID, {
|
|
name: 'Refurbished',
|
|
slug: 'refurbished',
|
|
sortOrder: 10,
|
|
})
|
|
expect(custom.isSystem).toBe(false)
|
|
expect(await ItemConditionService.validateSlug(app.db, TEST_COMPANY_ID, 'refurbished')).toBe(true)
|
|
})
|
|
})
|