Move tests to __tests__ folders, add unit tests for shared utils and services
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.
This commit is contained in:
152
packages/backend/__tests__/services/lookup.service.test.ts
Normal file
152
packages/backend/__tests__/services/lookup.service.test.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user