优化V4预订事项用户化展示

This commit is contained in:
andy committed 2026-07-21 21:33:51 +07:00
1 parent c521eb6dc0
commit fb980c6814
10 files changed
+163 -55

No files matched your search

+14 -1
View File
@@ -14,11 +14,24 @@ describe('reservation i18n locales', () => {
it('includes Thai labels for the P0 reservation navigation', () => {
expect(thTH.nav.orders).toBe('รายการออเดอร์')
expect(thTH.nav.taskQueue).toBe('คิวงาน')
expect(thTH.nav.taskQueue).toBe('รายการจองที่ต้องจัดการ')
expect(thTH.nav.debugEml).toBe('Debug EML')
expect(thTH.taskList.viewConversation).toBe('ดูเธรดอีเมล')
})
it('uses user-facing reservation navigation labels instead of legacy task wording', () => {
expect(zhCN.nav.taskQueue).toBe('预订事项')
expect(zhCN.nav.taskDetail).toBe('订单事项办理')
expect(zhCN.nav.orderDetail).toBe('订单总览')
expect(enUS.nav.taskQueue).toBe('Reservation items')
expect(enUS.nav.taskDetail).toBe('Reservation item handling')
expect(enUS.nav.orderDetail).toBe('Order overview')
expect(thTH.nav.taskDetail).toBe('จัดการรายการจอง')
expect(zhCN.nav.taskQueue).not.toBe('任务队列')
expect(zhCN.nav.taskDetail).not.toBe('任务详情')
})
it('covers Debug EML backend error codes in all locales', () => {
const expectedErrorCodes = [
'REQUEST_FIELD_REQUIRED',
@@ -199,6 +199,8 @@ describe('ReservationAppShell', () => {
expect(wrapper.find('a[href="/reservation/orders"]').exists()).toBe(true)
expect(wrapper.find('a[href="/reservation/tasks"]').exists()).toBe(true)
expect(wrapper.text()).toContain('预订事项')
expect(wrapper.text()).not.toContain('任务队列')
expect(wrapper.find('a[href="/debug/eml-superagent"]').exists()).toBe(false)
})
+68 -3
View File
@@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import { createMemoryHistory, createRouter } from 'vue-router'
import taskCardSectionSource from '@/components/reservation/ReservationV4TaskCardSection.vue?raw'
import zhCN from '@/i18n/locales/zh-CN'
import { useAuthStore } from '@/stores/authStore'
import type {
@@ -811,6 +812,25 @@ describe('reservation V4 pages', () => {
})
})
it('shows a user-facing empty state when Room Information display data is unavailable', async () => {
const detail = createOrderTaskDetail({
businessDisplayPayload: {},
})
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
const wrapper = await mountWithPlugins(
ReservationV4OrderTaskDetailView,
'/reservation/order-tasks/9001',
)
await flushPromises()
const roomCard = wrapper.find('[data-testid="room-information-card"]')
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.noDisplayModel)
expect(roomCard.text()).not.toContain('Room Information')
expect(roomCard.text()).not.toContain('display model')
expect(roomCard.text()).not.toContain('展示模型')
})
it('keeps backend errors for hidden Room Information fields visible as action messages', async () => {
const detail = createOrderTaskDetail({
businessEventType: 'NEW_BOOKING',
@@ -870,6 +890,8 @@ describe('reservation V4 pages', () => {
await flushPromises()
const roomCard = wrapper.find('[data-testid="room-information-card"]')
expect(roomCard.text()).toContain('新预订')
expect(roomCard.text()).not.toContain('NEW_BOOKING')
expect(roomCard.find('select[name="/room_information/final_values/group_booking_status"]').exists()).toBe(false)
expect(roomCard.text()).toContain('TEN-Tentative')
})
@@ -955,6 +977,8 @@ describe('reservation V4 pages', () => {
await flushPromises()
const roomCard = wrapper.find('[data-testid="room-information-card"]')
expect(roomCard.text()).toContain('修改预订')
expect(roomCard.text()).not.toContain('UPDATE_BOOKING')
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.changeSummary)
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.currentValues)
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.proposedValues)
@@ -1018,6 +1042,8 @@ describe('reservation V4 pages', () => {
await flushPromises()
const roomCard = wrapper.find('[data-testid="room-information-card"]')
expect(roomCard.text()).toContain('取消预订')
expect(roomCard.text()).not.toContain('CANCEL_BOOKING')
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.currentValues)
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.finalValues)
expect(roomCard.text()).toContain('GRP-V4-RI-CANCEL-001')
@@ -1073,7 +1099,7 @@ describe('reservation V4 pages', () => {
})
})
it('shows non-blocking lookup empty, stale and warning states', async () => {
it('shows lookup empty state without catalog technical warnings', async () => {
const detail = createOrderTaskDetail()
vi.mocked(service.fetchReservationV4AccountLookups).mockResolvedValue({
hotel_id: 'HOTEL-TEST',
@@ -1098,8 +1124,8 @@ describe('reservation V4 pages', () => {
await flushPromises()
expect(wrapper.text()).toContain(zhCN.taskV4.lookup.empty)
expect(wrapper.text()).toContain(zhCN.taskV4.lookup.stale)
expect(wrapper.text()).toContain('PMS sync is stale')
expect(wrapper.text()).not.toContain(zhCN.taskV4.lookup.stale)
expect(wrapper.text()).not.toContain('PMS sync is stale')
expect(wrapper.text()).not.toContain('PMS_SYNC')
expect(wrapper.text()).not.toContain('stale-v1')
})
@@ -1226,6 +1252,45 @@ describe('reservation V4 pages', () => {
})
})
it('hides catalog technical warnings from ordinary V4 business cards', async () => {
const detail = createOrderTaskDetail()
vi.mocked(service.fetchReservationV4AccountLookups).mockResolvedValue({
hotel_id: 'HOTEL-TEST',
catalog_type: 'ACCOUNT',
catalog_source: 'PMS_SYNC',
catalog_version: 'seed-v1',
stale: true,
items: [],
page: {
page_num: 1,
page_size: 100,
total: 0,
},
warnings: ['固定种子初始化,后续接入真实 PMS。'],
})
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
const wrapper = await mountWithPlugins(
ReservationV4OrderTaskDetailView,
'/reservation/order-tasks/9001',
)
await flushPromises()
expect(wrapper.text()).toContain(zhCN.taskV4.lookup.empty)
expect(wrapper.text()).not.toContain('固定种子初始化')
expect(wrapper.text()).not.toContain('真实 PMS')
expect(wrapper.text()).not.toContain('PMS_SYNC')
expect(wrapper.text()).not.toContain('seed-v1')
expect(wrapper.text()).not.toContain(zhCN.taskV4.lookup.stale)
})
it('keeps the per-card primary action right aligned on narrow screens', () => {
expect(taskCardSectionSource).toContain('@media (max-width: 980px)')
expect(taskCardSectionSource).toContain('.task-card-section__status-actions')
expect(taskCardSectionSource).toContain('align-self: stretch')
expect(taskCardSectionSource).toContain('justify-content: flex-end')
})
it('requires confirmed order id before resolving an unresolved V4 review card', async () => {
const detail = createOrderTaskDetail({
businessCardStatus: 'REVIEW_REQUIRED',