import { mount } from '@vue/test-utils' import { describe, expect, it } from 'vitest' import ScheduleCalendar from '../../components/ScheduleCalendar.vue' describe('ScheduleCalendar', () => { it('renders week events with layout styles from the schedule model', () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), dayStartHour: 6, dayEndHour: 10, slotDuration: 30, showNowIndicator: false, events: [ { id: 'run-1', title: 'LCMS run', start: '2024-05-15T07:00:00', end: '2024-05-15T08:30:00', }, ], }, }) const event = wrapper.find('.mint-schedule__event') expect(event.exists()).toBe(true) expect(event.find('.mint-schedule__event-title').text()).toBe('LCMS run') expect(event.attributes('style')).toContain('top: 80px') expect(event.attributes('style')).toContain('height: 120px') }) it('should write the status after the time when an event is pending', () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), dayStartHour: 6, dayEndHour: 10, showNowIndicator: false, events: [ { id: 'm-1', title: 'MS maintenance', start: '2024-05-15T07:00:00', end: '2024-05-15T08:00:00', status: 'pending' }, ], }, }) expect(wrapper.find('.mint-schedule__event-time').text()).toMatch(/ · Pending$/) }) it('should leave the time unlabeled when an event is confirmed', () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), dayStartHour: 6, dayEndHour: 10, showNowIndicator: false, events: [ { id: 'r-1', title: 'HPLC run', start: '2024-05-15T07:00:00', end: '2024-05-15T08:00:00', status: 'confirmed' }, ], }, }) expect(wrapper.find('.mint-schedule__event-time').text()).not.toContain('·') }) it('renders the month grid from the extracted calendar layout', () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), view: 'month', }, }) expect(wrapper.findAll('.mint-schedule__month-weekday')).toHaveLength(7) expect(wrapper.findAll('.mint-schedule__month-cell')).toHaveLength(42) expect(wrapper.find('.mint-schedule__title').text()).toBe('May 2024') }) it('reschedules an event with Alt and the arrow keys', async () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), dayStartHour: 6, dayEndHour: 10, slotDuration: 30, showNowIndicator: false, events: [ { id: 'run-1', title: 'LCMS run', start: '2024-05-15T07:00:00', end: '2024-05-15T08:00:00', }, ], }, }) const event = wrapper.get('.mint-schedule__event') expect(event.attributes('tabindex')).toBe('0') expect(event.attributes('aria-label')).toContain('Press Alt with the up or down arrow keys') await event.trigger('keydown', { key: 'ArrowDown', altKey: true }) const update = wrapper.emitted('event-update')?.[0]?.[0] as { newStart: Date newEnd: Date } expect(update.newStart.getHours()).toBe(7) expect(update.newStart.getMinutes()).toBe(30) expect(update.newEnd.getHours()).toBe(8) expect(update.newEnd.getMinutes()).toBe(30) await wrapper.vm.$nextTick() expect(wrapper.get('[role="status"]').attributes('aria-live')).toBe('polite') }) it('does not reschedule from the keyboard while readonly', async () => { const wrapper = mount(ScheduleCalendar, { props: { modelValue: new Date('2024-05-15T12:00:00'), dayStartHour: 6, dayEndHour: 10, slotDuration: 30, showNowIndicator: false, readonly: true, events: [ { id: 'run-1', title: 'LCMS run', start: '2024-05-15T07:00:00', end: '2024-05-15T08:00:00', }, ], }, }) await wrapper.get('.mint-schedule__event').trigger('keydown', { key: 'ArrowDown', altKey: true }) expect(wrapper.emitted('event-update')).toBeUndefined() }) })