fix architecture and write new tests
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
vi.mock('../../lib/storage', () => ({
|
||||
getProtectedCustomerLicenseImageUrl: vi.fn((customerId: string) => `/api/v1/customers/${customerId}/license-image`),
|
||||
}))
|
||||
|
||||
import {
|
||||
buildReservationWorkflow,
|
||||
normalizeOptionalString,
|
||||
parseReservationExtras,
|
||||
serializeReservationForDashboard,
|
||||
} from './reservation.presenter'
|
||||
|
||||
describe('reservation.presenter boundary behavior', () => {
|
||||
it('treats missing, array and primitive extras as empty objects', () => {
|
||||
expect(parseReservationExtras(null)).toEqual({})
|
||||
expect(parseReservationExtras(['paymentMode'])).toEqual({})
|
||||
expect(parseReservationExtras('cash')).toEqual({})
|
||||
expect(parseReservationExtras({ paymentMode: 'CASH' })).toEqual({ paymentMode: 'CASH' })
|
||||
})
|
||||
|
||||
it('normalizes optional strings without preserving whitespace-only values', () => {
|
||||
expect(normalizeOptionalString(' hello ')).toBe('hello')
|
||||
expect(normalizeOptionalString(' ')).toBeNull()
|
||||
expect(normalizeOptionalString(null)).toBeNull()
|
||||
expect(normalizeOptionalString(undefined)).toBeNull()
|
||||
})
|
||||
|
||||
it('locks core edits after contract generation even when reservation is still confirmed', () => {
|
||||
expect(buildReservationWorkflow({
|
||||
status: 'CONFIRMED',
|
||||
contractNumber: 'CTR-1',
|
||||
invoiceNumber: null,
|
||||
extras: {},
|
||||
})).toMatchObject({
|
||||
contractGenerated: true,
|
||||
closed: false,
|
||||
coreEditable: false,
|
||||
checkInInspectionEditable: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('marks closed reservations as immutable and exposes close metadata from extras only when strings', () => {
|
||||
expect(buildReservationWorkflow({
|
||||
status: 'COMPLETED',
|
||||
contractNumber: null,
|
||||
invoiceNumber: null,
|
||||
extras: { reservationClosedAt: '2026-06-01T12:00:00.000Z', reservationClosedBy: 123 },
|
||||
})).toMatchObject({
|
||||
closed: true,
|
||||
closedAt: '2026-06-01T12:00:00.000Z',
|
||||
closedBy: null,
|
||||
coreEditable: false,
|
||||
returnEditable: false,
|
||||
checkOutInspectionEditable: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('serializes dashboard reservations with protected license URLs and payment mode extraction', () => {
|
||||
const result = serializeReservationForDashboard({
|
||||
id: 'reservation_1',
|
||||
status: 'DRAFT',
|
||||
contractNumber: null,
|
||||
invoiceNumber: null,
|
||||
extras: { paymentMode: 'CARD' },
|
||||
customer: { id: 'customer_1', licenseImageUrl: '/storage/raw-license.jpg' },
|
||||
})
|
||||
|
||||
expect(result.paymentMode).toBe('CARD')
|
||||
expect(result.customer?.licenseImageUrl).toBe('/api/v1/customers/customer_1/license-image')
|
||||
expect(result.workflow.coreEditable).toBe(true)
|
||||
})
|
||||
|
||||
it('does not invent protected license URLs when customer has no stored license image', () => {
|
||||
const result = serializeReservationForDashboard({
|
||||
id: 'reservation_1',
|
||||
status: 'DRAFT',
|
||||
contractNumber: null,
|
||||
invoiceNumber: null,
|
||||
extras: { paymentMode: 42 },
|
||||
customer: { id: 'customer_1', licenseImageUrl: null },
|
||||
})
|
||||
|
||||
expect(result.paymentMode).toBeNull()
|
||||
expect(result.customer?.licenseImageUrl).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user