200 lines
7.0 KiB
TypeScript
200 lines
7.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import type { ReservationV4TaskCardFieldResult } from '@/types/reservation'
|
|
import {
|
|
buildReservationV4ConfirmedPayload,
|
|
buildReservationV4InitialFieldValues,
|
|
buildReservationV4ReviewOverrides,
|
|
isReservationV4ConfirmWritableField,
|
|
isReservationV4ReviewWritableField,
|
|
reservationV4LookupKindForOptionsSource,
|
|
stringifyReservationV4SafeDisplayValue,
|
|
validateReservationV4Fields,
|
|
} from '@/utils/reservationV4FieldRules'
|
|
|
|
function createV4Field(
|
|
field_pointer: string,
|
|
overrides: Partial<ReservationV4TaskCardFieldResult> = {},
|
|
): ReservationV4TaskCardFieldResult {
|
|
return {
|
|
field_path: field_pointer.replace(/^\//, '').replace(/\//g, '.'),
|
|
field_pointer,
|
|
display_name: overrides.display_name ?? field_pointer,
|
|
value: overrides.value ?? '',
|
|
editable: overrides.editable ?? true,
|
|
required: overrides.required ?? false,
|
|
control_type: overrides.control_type ?? 'TEXT',
|
|
edit_scope: overrides.edit_scope ?? 'NORMAL_TASK',
|
|
write_target: overrides.write_target ?? 'CONFIRMED_PAYLOAD_JSON',
|
|
options_source: overrides.options_source ?? null,
|
|
raw_readonly: overrides.raw_readonly ?? false,
|
|
validation_errors: overrides.validation_errors ?? [],
|
|
control_hint: overrides.control_hint ?? null,
|
|
}
|
|
}
|
|
|
|
describe('reservationV4FieldRules', () => {
|
|
it('builds initial values from backend fields using field pointers', () => {
|
|
const fields = [
|
|
createV4Field('/basic_information/account_code', { value: 'HANATOUR' }),
|
|
createV4Field('/business_fields/after/room_items/0/room_type_code', { value: 'TWN' }),
|
|
]
|
|
|
|
expect(buildReservationV4InitialFieldValues(fields)).toEqual({
|
|
'/basic_information/account_code': 'HANATOUR',
|
|
'/business_fields/after/room_items/0/room_type_code': 'TWN',
|
|
})
|
|
})
|
|
|
|
it('submits only editable confirm fields and keeps nested pointer structure', () => {
|
|
const fields = [
|
|
createV4Field('/basic_information/account_code', { value: 'OLD' }),
|
|
createV4Field('/basic_information/read_only_label', {
|
|
value: 'VISIBLE_ONLY',
|
|
editable: true,
|
|
raw_readonly: true,
|
|
}),
|
|
createV4Field('/business_fields/after/room_items/0/room_type_code', {
|
|
value: 'KING',
|
|
edit_scope: 'MANUAL_REVIEW_ONLY',
|
|
write_target: 'REVIEW_RESOLUTION_FIELD_OVERRIDES',
|
|
}),
|
|
]
|
|
|
|
const payload = buildReservationV4ConfirmedPayload(fields, {
|
|
'/basic_information/account_code': 'HANATOUR',
|
|
'/basic_information/read_only_label': 'SHOULD_NOT_SEND',
|
|
'/business_fields/after/room_items/0/room_type_code': 'TWN',
|
|
})
|
|
|
|
expect(payload).toEqual({
|
|
basic_information: {
|
|
account_code: 'HANATOUR',
|
|
},
|
|
})
|
|
})
|
|
|
|
it('uses field_pointer for review resolution overrides', () => {
|
|
const fields = [
|
|
createV4Field('/business_fields/after/room_items/0/room_type_code', {
|
|
value: '',
|
|
edit_scope: 'MANUAL_REVIEW_ONLY',
|
|
write_target: 'REVIEW_RESOLUTION_FIELD_OVERRIDES',
|
|
}),
|
|
createV4Field('/business_fields/after/room_items/0/room_type_raw', {
|
|
value: 'TWN',
|
|
editable: false,
|
|
write_target: 'NONE',
|
|
}),
|
|
]
|
|
|
|
expect(buildReservationV4ReviewOverrides(fields, {
|
|
'/business_fields/after/room_items/0/room_type_code': 'TWN',
|
|
'/business_fields/after/room_items/0/room_type_raw': 'Twin',
|
|
})).toEqual([
|
|
{
|
|
field_pointer: '/business_fields/after/room_items/0/room_type_code',
|
|
value: 'TWN',
|
|
},
|
|
])
|
|
})
|
|
|
|
it('does not submit fields with missing V4 write metadata', () => {
|
|
const confirmField = createV4Field('/business_fields/after/room_items/0/rate_code')
|
|
confirmField.edit_scope = null
|
|
confirmField.write_target = null
|
|
const reviewField = createV4Field('/business_fields/after/room_items/0/room_type_code', {
|
|
edit_scope: 'MANUAL_REVIEW_ONLY',
|
|
})
|
|
reviewField.write_target = null
|
|
|
|
expect(isReservationV4ConfirmWritableField(confirmField)).toBe(false)
|
|
expect(isReservationV4ReviewWritableField(reviewField)).toBe(false)
|
|
expect(buildReservationV4ConfirmedPayload([confirmField], {
|
|
'/business_fields/after/room_items/0/rate_code': 'BAR',
|
|
})).toEqual({})
|
|
expect(buildReservationV4ReviewOverrides([reviewField], {
|
|
'/business_fields/after/room_items/0/room_type_code': 'TWN',
|
|
})).toEqual([])
|
|
})
|
|
|
|
it('allows review overrides only for basic information and business fields', () => {
|
|
const fields = [
|
|
createV4Field('/source_message/subject', {
|
|
edit_scope: 'MANUAL_REVIEW_ONLY',
|
|
write_target: 'REVIEW_RESOLUTION_FIELD_OVERRIDES',
|
|
}),
|
|
createV4Field('/business_fields/after/room_items/0/room_type_code', {
|
|
edit_scope: 'MANUAL_REVIEW_ONLY',
|
|
write_target: 'REVIEW_RESOLUTION_FIELD_OVERRIDES',
|
|
}),
|
|
]
|
|
|
|
expect(buildReservationV4ReviewOverrides(fields, {
|
|
'/source_message/subject': 'SHOULD_NOT_SEND',
|
|
'/business_fields/after/room_items/0/room_type_code': 'TWN',
|
|
})).toEqual([
|
|
{
|
|
field_pointer: '/business_fields/after/room_items/0/room_type_code',
|
|
value: 'TWN',
|
|
},
|
|
])
|
|
})
|
|
|
|
it('redacts nested raw body, evidence and URL values from safe display text', () => {
|
|
const text = stringifyReservationV4SafeDisplayValue({
|
|
business_fields: {
|
|
group_code: 'GRP-001',
|
|
raw_evidence: 'raw email body',
|
|
nested: {
|
|
room_type_code: 'TWN',
|
|
oss_url: 'https://oss.example/private-file.pdf',
|
|
},
|
|
safe_url_value: 'https://oss.example/also-hidden.pdf',
|
|
},
|
|
}, 'empty', 'hidden')
|
|
|
|
expect(text).toContain('GRP-001')
|
|
expect(text).toContain('TWN')
|
|
expect(text).not.toContain('raw email body')
|
|
expect(text).not.toContain('https://oss.example')
|
|
expect(text).not.toContain('oss_url')
|
|
})
|
|
|
|
it('redacts direct URL-like display values', () => {
|
|
expect(stringifyReservationV4SafeDisplayValue(
|
|
'https://oss.example/private-file.pdf',
|
|
'empty',
|
|
'hidden',
|
|
)).toBe('hidden')
|
|
})
|
|
|
|
it('validates only editable visible fields', () => {
|
|
const fields = [
|
|
createV4Field('/basic_information/account_code', {
|
|
display_name: 'Account',
|
|
required: true,
|
|
}),
|
|
createV4Field('/business_fields/after/room_items/0/room_type_code', {
|
|
display_name: 'Room type',
|
|
required: true,
|
|
editable: false,
|
|
}),
|
|
]
|
|
|
|
expect(validateReservationV4Fields(fields, {
|
|
'/basic_information/account_code': '',
|
|
'/business_fields/after/room_items/0/room_type_code': '',
|
|
})).toEqual({
|
|
'/basic_information/account_code': 'Account is required',
|
|
})
|
|
})
|
|
|
|
it('maps V4 options_source to lookup kinds without returning fixed catalog options', () => {
|
|
expect(reservationV4LookupKindForOptionsSource('reservation_v4_account_catalog')).toBe('ACCOUNT')
|
|
expect(reservationV4LookupKindForOptionsSource('RESERVATION_V4_ROOM_TYPE_CATALOG')).toBe('ROOM_TYPE')
|
|
expect(reservationV4LookupKindForOptionsSource('reservation_v4_rate_code_catalog')).toBe('RATE_CODE')
|
|
expect(reservationV4LookupKindForOptionsSource('static_enum')).toBeNull()
|
|
})
|
|
})
|