Files
admin-web/src/modules/appointment-calendar/WorkCalendarPanel.test.ts
T

81 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { mount } from '@vue/test-utils'
import { afterEach, expect, it, vi } from 'vitest'
import WorkCalendarPanel from './WorkCalendarPanel.vue'
import { workCalendar } from './work.test-support'
import { workTypes } from './workApi'
function render() { return mount(WorkCalendarPanel, { props: { anchor: '2026-10-15', mode: 'month', flow: '', types: [...workTypes], calendar: workCalendar, loading: false, failed: false, reference: false, arrivals: [], referenceReady: false } }) }
afterEach(() => vi.useRealTimers())
it('keeps a busy day at five type summaries and consumes authoritative transport counts unchanged', async () => {
const wrapper = render()
const counts = { PICKUP: 300, WAREHOUSE_RECEIPT: 300, DELIVERY: 2, TRANSPORT: 1, EMPTY_RETURN: 300 }
await wrapper.setProps({ calendar: { ...workCalendar, days: [{ ...workCalendar.days[0]!, total: 903, typeCounts: counts }] } })
const day = wrapper.get('[data-date="2026-10-15"]')
expect(day.findAll('.type-counts button')).toHaveLength(5)
expect(day.get('[data-type="TRANSPORT"]').text()).toContain('1')
expect(day.get('[data-type="DELIVERY"]').text()).toContain('2')
await day.get('[data-type="TRANSPORT"]').trigger('click')
expect(wrapper.emitted('day')).toEqual([['2026-10-15', 'TRANSPORT']]); wrapper.unmount()
})
it('offers all four flows directly and emits the original filter values with an exclusive selection', async () => {
const wrapper = render()
const buttons = wrapper.findAll('.flow-controls button')
expect(buttons.map(button => button.text())).toEqual(['全部流程', '海外仓中转', '整柜直送', '路线待确认'])
expect(wrapper.find('select').exists()).toBe(false)
for (const [index, flow] of (['', 'TRANSFER', 'DIRECT', 'UNKNOWN'] as const).entries()) {
await buttons[index]!.trigger('click')
expect(wrapper.emitted('flow')?.at(-1)).toEqual([flow])
await wrapper.setProps({ flow })
expect(wrapper.findAll('.flow-controls button[aria-pressed=true]')).toHaveLength(1)
expect(buttons[index]!.attributes('aria-pressed')).toBe('true')
}
wrapper.unmount()
})
it('distinguishes today from the selected day and type without changing the selected scope', async () => {
vi.useFakeTimers(); vi.setSystemTime(new Date('2026-10-15T12:00:00'))
const wrapper = render()
await wrapper.setProps({ selectedDate: '2026-10-16' })
expect(wrapper.get('[data-date="2026-10-15"] .day-heading').attributes('aria-current')).toBe('date')
expect(wrapper.get('[data-date="2026-10-15"] .day-heading').attributes('aria-pressed')).toBe('false')
expect(wrapper.get('[data-date="2026-10-16"]').classes()).toContain('is-selected')
await wrapper.setProps({ selectedDate: '2026-10-15', selectedType: 'DELIVERY' })
expect(wrapper.get('[data-date="2026-10-15"] [data-type="DELIVERY"]').attributes('aria-pressed')).toBe('true')
expect(wrapper.get('[data-date="2026-10-15"] [data-type="PICKUP"]').attributes('aria-pressed')).toBe('false')
wrapper.unmount()
})
it('shows the actual cross-month interval and hides empty-day zeros while keeping dates clickable', async () => {
const wrapper = render()
expect(wrapper.get('.calendar-counts').text()).toContain('2026-09-28 ~ 2026-11-08')
const empty = wrapper.get('[data-date="2026-10-01"] .day-heading')
expect(empty.text()).toBe('1')
expect(empty.attributes('disabled')).toBeUndefined()
await empty.trigger('click'); expect(wrapper.emitted('day')).toEqual([['2026-10-01']])
expect(wrapper.get('footer').text()).toContain('未定日期请从上方待办查看')
await wrapper.setProps({ mode: 'week' })
expect(wrapper.findAll('.work-day')).toHaveLength(7)
expect(wrapper.get('.view-switch button:last-child').attributes('aria-pressed')).toBe('true')
wrapper.unmount()
})
it('renders server type counts instead of individual event cards and opens exact date/type details', async () => {
const wrapper = render()
expect(wrapper.findAll('.work-day')).toHaveLength(35)
const day = wrapper.get('[data-date="2026-10-15"]')
expect(day.get('.day-heading').text()).toContain('2 项')
await day.get('[data-type="DELIVERY"]').trigger('click')
expect(wrapper.emitted('day')).toEqual([['2026-10-15', 'DELIVERY']]); wrapper.unmount()
})
it('does not conflate arrivals, no-booking requirements or completed work with confirmed work', async () => {
const wrapper = render()
await wrapper.setProps({ reference: true, referenceReady: true, arrivals: [{ containerBookingId: '1', cabinetNo: 'D-1', arrivalAt: '2026-10-15T10:00:00', arrivalType: 'ESTIMATED' }] })
expect(wrapper.get('[data-date="2026-10-15"] .day-heading').text()).toContain('2 项')
expect(wrapper.get('.calendar-counts').text()).toContain('已完成 1')
expect(wrapper.get('.calendar-counts').text()).toContain('已落实 0')
await wrapper.get('.arrival-reference').trigger('click'); expect(wrapper.emitted('arrivals')).toEqual([['2026-10-15']]); wrapper.unmount()
})
it('shows explicit all-off and failure states without manufacturing zero aggregates', async () => {
const wrapper = render(); await wrapper.setProps({ types: [], calendar: null })
expect(wrapper.text()).toContain('全局待办仍可查看'); expect(wrapper.findAll('.type-counts button')).toHaveLength(0)
await wrapper.setProps({ types: [...workTypes], failed: true })
expect(wrapper.get('.calendar-counts').text()).toBe('工作统计加载失败')
expect(wrapper.get('[data-date="2026-10-15"] .day-heading').text()).not.toContain('0 项'); wrapper.unmount()
})