2026-10-09 11:01:41 +08:00
|
|
|
|
import { mount } from '@vue/test-utils'
|
|
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
|
|
import AppointmentCalendarPanel from './AppointmentCalendarPanel.vue'
|
|
|
|
|
|
|
|
|
|
|
|
describe('appointment calendar interactions', () => {
|
|
|
|
|
|
const render = () => mount(AppointmentCalendarPanel, {
|
|
|
|
|
|
props: { initialDate: '2026-09-24', canCreate: true, events: [
|
|
|
|
|
|
{ key: 'a', type: 'delivery', date: '2026-09-24', time: '09:00-11:00', title: 'ONT8 预约送货', fields: [], canEdit: true, canDelete: true },
|
|
|
|
|
|
] },
|
|
|
|
|
|
global: { stubs: { ElButton: { template: '<button><slot /></button>' } }, directives: { loading: {} } },
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('selects an already loaded date without requesting data again', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.get('[aria-label="2026-09-25,0 项安排"]').trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('range')).toBeUndefined()
|
|
|
|
|
|
expect(wrapper.get('[aria-label="当天安排"]').text()).toContain('当天暂无到港或送仓预约')
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-10-10 12:40:52 +08:00
|
|
|
|
it('shows an overnight slot on both days without fetching again and excludes midnight ends', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.setProps({ events: [
|
|
|
|
|
|
{ key: 'overnight', type: 'delivery', date: '2026-09-23', endAt: '2026-09-24T01:00:00', time: '23:00–01:00', title: '跨日送仓', fields: [] },
|
|
|
|
|
|
{ key: 'midnight', type: 'delivery', date: '2026-09-23', endAt: '2026-09-24T00:00:00', time: '23:00–00:00', title: '午夜结束', fields: [] },
|
|
|
|
|
|
] })
|
|
|
|
|
|
expect(wrapper.find('[aria-label="2026-09-23,2 项安排"]').exists()).toBe(true)
|
|
|
|
|
|
expect(wrapper.find('[aria-label="2026-09-24,1 项安排"]').exists()).toBe(true)
|
|
|
|
|
|
expect(wrapper.get('[aria-label="当天安排"]').text()).toContain('跨日送仓')
|
|
|
|
|
|
expect(wrapper.get('[aria-label="当天安排"]').text()).not.toContain('午夜结束')
|
|
|
|
|
|
expect(wrapper.emitted('range')).toBeUndefined()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-10-09 11:01:41 +08:00
|
|
|
|
it('requests exactly one range for a view switch and navigates seven days', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.get('[aria-label="预约视图"]').findAll('button')[1]!.trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('range')).toEqual([[{ from: '2026-09-21', to: '2026-09-28' }]])
|
|
|
|
|
|
await wrapper.get('[aria-label="下一周"]').trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('range')?.at(-1)).toEqual([{ from: '2026-09-28', to: '2026-10-05' }])
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-10-09 12:03:25 +08:00
|
|
|
|
it('keeps busy days to three previews in both views and exposes the full count', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.setProps({ events: Array.from({ length: 233 }, (_, index) => ({
|
|
|
|
|
|
key: `arrival-${index}`, type: 'arrival' as const, date: '2026-09-24', time: '09:00',
|
|
|
|
|
|
title: `船舶 ${index}`, fields: [],
|
|
|
|
|
|
})) })
|
|
|
|
|
|
for (const view of ['month', 'week']) {
|
|
|
|
|
|
if (view === 'week') await wrapper.get('[aria-label="预约视图"]').findAll('button')[1]!.trigger('click')
|
|
|
|
|
|
const day = wrapper.get('[aria-label="2026-09-24,233 项安排"]')
|
|
|
|
|
|
expect(day.findAll('.event-chip')).toHaveLength(3)
|
|
|
|
|
|
expect(day.attributes('title')).toContain('共 233 条安排')
|
|
|
|
|
|
expect(day.get('.event-more').text()).toBe('还有 230 条')
|
|
|
|
|
|
expect(wrapper.findAll('.detail-event')).toHaveLength(233)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-10-09 11:01:41 +08:00
|
|
|
|
it('uses the selected day for creation and emits edit/delete only from detail actions', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.findAll('button').find(button => button.text() === '+ 新增预约')!.trigger('click')
|
|
|
|
|
|
expect(wrapper.emitted('create')).toEqual([['2026-09-24']])
|
|
|
|
|
|
await wrapper.findAll('button').find(button => button.text() === '编辑')!.trigger('click')
|
2026-10-10 10:44:07 +08:00
|
|
|
|
await wrapper.findAll('button').find(button => button.text() === '取消预约')!.trigger('click')
|
2026-10-09 11:01:41 +08:00
|
|
|
|
expect(wrapper.emitted('edit')?.[0]?.[0]).toMatchObject({ key: 'a' })
|
|
|
|
|
|
expect(wrapper.emitted('delete')?.[0]?.[0]).toMatchObject({ key: 'a' })
|
|
|
|
|
|
})
|
2026-10-09 22:05:51 +08:00
|
|
|
|
|
|
|
|
|
|
it('renders many inbound codes outside the two-column fields with only three previews', async () => {
|
|
|
|
|
|
const wrapper = render()
|
|
|
|
|
|
await wrapper.setProps({ events: [{
|
|
|
|
|
|
key: 'many', type: 'delivery', date: '2026-09-24', time: '09:00', title: 'ONT8 预约送仓',
|
|
|
|
|
|
fields: [{ label: '货物信息', value: '20 票 / 12 个客户' }],
|
|
|
|
|
|
inboundCodes: Array.from({ length: 20 }, (_, index) => `WT-INBOUND-${index}`), canEdit: true,
|
|
|
|
|
|
}] })
|
|
|
|
|
|
const card = wrapper.get('.detail-event')
|
|
|
|
|
|
expect(card.get('dl').text()).not.toContain('WT-INBOUND')
|
|
|
|
|
|
expect(card.findAll('.inbound-codes li')).toHaveLength(3)
|
|
|
|
|
|
expect(card.get('.inbound-codes').text()).toContain('20 个')
|
|
|
|
|
|
expect(card.get('footer').text()).toContain('编辑')
|
|
|
|
|
|
})
|
2026-10-09 11:01:41 +08:00
|
|
|
|
})
|