接入前端真实接口并标记邮件HTML清洗

This commit is contained in:
andy
2026-07-08 23:37:03 +08:00
parent c83935a26c
commit a0cb3a05d7
25 changed files with 2581 additions and 157 deletions

View File

@@ -1,7 +1,6 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import {
EndpointPendingError,
fetchReservationOrderDetail,
fetchReservationOrders,
fetchReservationTaskDetail,
@@ -69,13 +68,54 @@ describe('reservationService real API mode', () => {
})
expect(fetchMock).toHaveBeenCalledWith(
'/api/reservation/tasks?task_status=PENDING_CONFIRM&page_num=1&page_size=20',
'/api/reservation/tasks?hotel_id=HOTEL-TEST&task_status=PENDING_CONFIRM&page_num=1&page_size=20',
expect.objectContaining({ method: 'GET' }),
)
expect(result.items).toHaveLength(1)
expect(result.items[0]?.source_subject).toBe('Booking Request')
})
it('fetches the order list from the backend by default', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
mockJsonResponse({
items: [
{
order_id: '20001',
hotel_id: 'HOTEL-TEST',
order_status: 'ACTIVE',
display_order_key: 'GRP-001',
temporary_order_no: null,
confirmation_number: null,
group_code: 'GRP-001',
display_name: 'GRP-001',
open_task_count: 2,
next_processable_task_id: '10002',
created_at: '2026-07-08T03:00:00Z',
updated_at: '2026-07-08T03:10:00Z',
},
],
page: {
page_num: 1,
page_size: 20,
total: 1,
},
}),
)
const result = await fetchReservationOrders({
keyword: 'GRP-001',
page_num: 1,
page_size: 20,
})
expect(fetchMock).toHaveBeenCalledWith(
'/api/reservation/orders?hotel_id=HOTEL-TEST&keyword=GRP-001&page_num=1&page_size=20',
expect.objectContaining({ method: 'GET' }),
)
expect(result.items[0]?.display_order_key).toBe('GRP-001')
expect(result.items[0]?.next_processable_task_id).toBe('10002')
})
it('fetches order detail from the backend by default', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
mockJsonResponse({
@@ -100,7 +140,7 @@ describe('reservationService real API mode', () => {
const result = await fetchReservationOrderDetail('20001')
expect(fetchMock).toHaveBeenCalledWith(
'/api/reservation/orders/20001?include_tasks=true&include_source_summary=true',
'/api/reservation/orders/20001?hotel_id=HOTEL-TEST&include_tasks=true&include_source_summary=true',
expect.objectContaining({ method: 'GET' }),
)
expect(result.order.display_name).toBe('GRP-001')
@@ -141,11 +181,61 @@ describe('reservationService real API mode', () => {
expect(result.task_id).toBe('10001')
})
it('marks order list as pending instead of returning fixture data', async () => {
await expect(fetchReservationOrders()).rejects.toBeInstanceOf(EndpointPendingError)
})
it('fetches source message conversation from the backend by default', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
mockJsonResponse({
conversation: {
hotel_id: 'HOTEL-TEST',
channel: 'EMAIL',
external_conversation_id: 'thread-30001',
subject: 'Booking Request',
message_count: 2,
first_received_at: '2026-07-08T02:00:00Z',
last_received_at: '2026-07-08T03:00:00Z',
},
messages: [
{
id: '30001',
external_message_id: 'msg-30001',
external_conversation_id: 'thread-30001',
sender_summary: 'guest@example.test',
subject: 'Booking Request',
received_at: '2026-07-08T02:00:00Z',
source_sent_at: '2026-07-08T01:58:00Z',
text_body: '完整邮件正文',
html_body: '<p>完整邮件正文</p>',
html_sanitize_required: true,
inline_images: [],
attachments: [],
related_orders: [
{
order_id: '20001',
display_order_key: 'GRP-001',
order_status: 'ACTIVE',
},
],
related_tasks: [
{
task_id: '10001',
order_id: '20001',
task_type: 'NEW_BOOKING',
task_subtype: 'NEW_BOOKING',
task_status: 'PENDING_CONFIRM',
card_name: 'New Booking',
},
],
},
],
}),
)
it('marks source message conversation as pending instead of returning fixture data', async () => {
await expect(fetchSourceMessageConversation('30001')).rejects.toBeInstanceOf(EndpointPendingError)
const result = await fetchSourceMessageConversation('30001')
expect(fetchMock).toHaveBeenCalledWith(
'/api/source-messages/30001/conversation',
expect.objectContaining({ method: 'GET' }),
)
expect(result.conversation.external_conversation_id).toBe('thread-30001')
expect(result.messages[0]?.text_body).toBe('完整邮件正文')
})
})