提交一次全量代码
This commit is contained in:
@@ -8,6 +8,7 @@ import ReservationOrderDetailView from '@/views/reservation/ReservationOrderDeta
|
||||
import ReservationOrderListView from '@/views/reservation/ReservationOrderListView.vue'
|
||||
import ReservationSourceMessageConversationView from '@/views/reservation/ReservationSourceMessageConversationView.vue'
|
||||
import ReservationTaskListView from '@/views/reservation/ReservationTaskListView.vue'
|
||||
import type { SourceMessageConversationResult } from '@/types/reservation'
|
||||
|
||||
vi.mock('@/services/reservationService', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/services/reservationService')>()
|
||||
@@ -148,8 +149,8 @@ function createOrderDetailResult() {
|
||||
}
|
||||
|
||||
function createSourceMessageConversationResult(
|
||||
overrides: Partial<ReturnType<typeof createSourceMessageConversationResultBase>> = {},
|
||||
) {
|
||||
overrides: Partial<SourceMessageConversationResult> = {},
|
||||
): SourceMessageConversationResult {
|
||||
const result = createSourceMessageConversationResultBase()
|
||||
return {
|
||||
...result,
|
||||
@@ -157,7 +158,7 @@ function createSourceMessageConversationResult(
|
||||
}
|
||||
}
|
||||
|
||||
function createSourceMessageConversationResultBase() {
|
||||
function createSourceMessageConversationResultBase(): SourceMessageConversationResult {
|
||||
return {
|
||||
conversation: {
|
||||
hotel_id: 'HOTEL-TEST',
|
||||
@@ -178,8 +179,10 @@ function createSourceMessageConversationResultBase() {
|
||||
received_at: '2026-07-08T02:00:00Z',
|
||||
source_sent_at: '2026-07-08T01:58:00Z',
|
||||
text_body: '完整邮件正文',
|
||||
html_body: '<strong>不应直接渲染</strong>',
|
||||
html_body: '<script>alert("raw")</script><strong onclick="alert(1)">原始邮件正文</strong>',
|
||||
html_body_sanitized: '<strong>清洗后邮件正文</strong>',
|
||||
html_sanitize_required: true,
|
||||
html_render_mode: 'SANITIZED_HTML',
|
||||
inline_images: [],
|
||||
attachments: [
|
||||
{
|
||||
@@ -289,7 +292,9 @@ describe('reservation P0 views', () => {
|
||||
expect(wrapper.text()).toContain('Booking Request')
|
||||
expect(wrapper.text()).toContain('guest@example.test')
|
||||
expect(wrapper.text()).toContain('2')
|
||||
expect(wrapper.text()).toContain('前序任务未完成')
|
||||
expect(wrapper.text()).toContain('查看邮件会话')
|
||||
expect(wrapper.text()).not.toContain('PREVIOUS_TASK_NOT_FINISHED')
|
||||
expect(wrapper.text()).not.toContain('来源邮件摘要字段待后端补充')
|
||||
})
|
||||
|
||||
@@ -346,8 +351,10 @@ describe('reservation P0 views', () => {
|
||||
|
||||
expect(wrapper.text()).toContain('GRP-001')
|
||||
expect(wrapper.text()).toContain('Booking Request')
|
||||
expect(wrapper.text()).toContain('新预订')
|
||||
expect(wrapper.text()).toContain('查看邮件会话')
|
||||
expect(wrapper.text()).not.toContain('接口待补')
|
||||
expect(wrapper.text()).not.toContain('NEW_BOOKING / NEW_BOOKING')
|
||||
})
|
||||
|
||||
it('filters and paginates task list with supported backend fields', async () => {
|
||||
@@ -355,17 +362,20 @@ describe('reservation P0 views', () => {
|
||||
.mockResolvedValueOnce(createTaskListResult('GRP-001', 'Booking Request', { page_num: 1, page_size: 20, total: 45 }))
|
||||
.mockResolvedValueOnce(createTaskListResult('GRP-001', 'Booking Request', { page_num: 1, page_size: 20, total: 45 }))
|
||||
.mockResolvedValueOnce(createTaskListResult('GRP-001', 'Booking Request', { page_num: 1, page_size: 20, total: 45 }))
|
||||
.mockResolvedValueOnce(createTaskListResult('GRP-001', 'Booking Request', { page_num: 1, page_size: 20, total: 45 }))
|
||||
.mockResolvedValueOnce(createTaskListResult('GRP-002', 'Booking Update', { page_num: 2, page_size: 20, total: 45 }))
|
||||
|
||||
const wrapper = await mountWithPlugins(ReservationTaskListView)
|
||||
await vi.dynamicImportSettled()
|
||||
|
||||
const selects = wrapper.findAll('select')
|
||||
expect(wrapper.text()).toContain('订单状态筛选待后端接入')
|
||||
expect(selects[2]!.attributes('disabled')).toBeDefined()
|
||||
expect(wrapper.text()).not.toContain('订单状态筛选待后端接入')
|
||||
expect(selects[2]!.attributes('disabled')).toBeUndefined()
|
||||
|
||||
await selects[1]!.setValue('READY')
|
||||
await vi.dynamicImportSettled()
|
||||
await selects[2]!.setValue('ENDED')
|
||||
await vi.dynamicImportSettled()
|
||||
await selects[3]!.setValue('true')
|
||||
await vi.dynamicImportSettled()
|
||||
|
||||
@@ -373,10 +383,10 @@ describe('reservation P0 views', () => {
|
||||
const filteredTaskRequest = taskListCalls[taskListCalls.length - 1]?.[0] ?? {}
|
||||
expect(filteredTaskRequest).toMatchObject({
|
||||
task_status: 'READY',
|
||||
order_status: 'ENDED',
|
||||
queue_participation: true,
|
||||
page_num: 1,
|
||||
})
|
||||
expect(filteredTaskRequest).not.toHaveProperty('order_status')
|
||||
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('下一页'))?.trigger('click')
|
||||
await vi.dynamicImportSettled()
|
||||
@@ -384,6 +394,7 @@ describe('reservation P0 views', () => {
|
||||
expect(service.fetchReservationTaskList).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
task_status: 'READY',
|
||||
order_status: 'ENDED',
|
||||
queue_participation: true,
|
||||
page_num: 2,
|
||||
page_size: 20,
|
||||
@@ -436,12 +447,34 @@ describe('reservation P0 views', () => {
|
||||
|
||||
expect(service.fetchSourceMessageConversation).toHaveBeenCalledWith('30001')
|
||||
expect(wrapper.text()).toContain('Booking Request')
|
||||
expect(wrapper.text()).toContain('不应直接渲染')
|
||||
expect(wrapper.text()).toContain('清洗后邮件正文')
|
||||
expect(wrapper.text()).toContain('rooming-list.xlsx')
|
||||
expect(wrapper.find('.message-body').html()).toContain('<strong>不应直接渲染</strong>')
|
||||
expect(wrapper.find('.message-body').html()).toContain('<strong>清洗后邮件正文</strong>')
|
||||
expect(wrapper.find('.message-body').html()).not.toContain('<script>')
|
||||
expect(wrapper.find('.message-body').html()).not.toContain('onclick')
|
||||
expect(wrapper.text()).not.toContain('原始邮件正文')
|
||||
expect(wrapper.text()).not.toContain('接口待接入')
|
||||
})
|
||||
|
||||
it('falls back to text when sanitized html is unavailable', async () => {
|
||||
const conversationResult = createSourceMessageConversationResult()
|
||||
conversationResult.messages[0]!.html_body = '<strong>原始 HTML 不上屏</strong>'
|
||||
conversationResult.messages[0]!.html_body_sanitized = null
|
||||
conversationResult.messages[0]!.html_render_mode = 'TEXT_ONLY'
|
||||
conversationResult.messages[0]!.text_body = '纯文本回退正文'
|
||||
vi.mocked(service.fetchSourceMessageConversation).mockResolvedValue(conversationResult)
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationSourceMessageConversationView,
|
||||
'/reservation/source-messages/30001/conversation',
|
||||
)
|
||||
await vi.dynamicImportSettled()
|
||||
|
||||
expect(wrapper.text()).toContain('纯文本回退正文')
|
||||
expect(wrapper.text()).not.toContain('原始 HTML 不上屏')
|
||||
expect(wrapper.find('.message-body--html').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('does not expose unsafe attachment URLs as links', async () => {
|
||||
const conversationResult = createSourceMessageConversationResult()
|
||||
conversationResult.messages[0]!.attachments = [
|
||||
|
||||
Reference in New Issue
Block a user