Files
carmanagement/apps/api/src/modules/reservations/reservation.presenter.boundary.test.ts
T
root 7ff2dbb139
Build & Deploy / Build & Push Docker Image (push) Successful in 2m55s
Test / Type Check (all packages) (push) Successful in 54s
Build & Deploy / Deploy to VPS (push) Successful in 4s
Test / API Unit Tests (push) Failing after 48s
Test / Homepage Unit Tests (push) Successful in 43s
Test / Storefront Unit Tests (push) Failing after 40s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Failing after 42s
Test / API Integration Tests (push) Successful in 1m0s
chore: wire Carplace into dev and production stacks
2026-07-02 18:15:42 -04:00

106 lines
3.4 KiB
TypeScript

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',
source: 'CARPLACE',
contractNumber: null,
invoiceNumber: null,
paymentStatus: 'UNPAID',
extras: { paymentMode: 'CARD' },
customer: {
id: 'customer_1',
driverLicense: null,
dateOfBirth: null,
address: {},
licenseImageUrl: '/storage/raw-license.jpg',
licenseValidationStatus: 'PENDING',
},
})
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',
source: 'CARPLACE',
contractNumber: null,
invoiceNumber: null,
paymentStatus: 'UNPAID',
extras: { paymentMode: 42 },
customer: {
id: 'customer_1',
driverLicense: null,
dateOfBirth: null,
address: {},
licenseImageUrl: null,
licenseValidationStatus: 'PENDING',
},
})
expect(result.paymentMode).toBeNull()
expect(result.customer?.licenseImageUrl).toBeNull()
})
})