import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' import {mount} from '@vue/test-utils' import type {DefineComponent} from 'vue' import DateWeek from './DateWeek.vue' type DateWeekProps = { modelValue?: string | null label?: string disabled?: boolean readonly?: boolean error?: string min?: string max?: string } const DateWeekForTest = DateWeek as DefineComponent const mountWeek = (props: DateWeekProps = {}) => mount(DateWeekForTest, {props, attachTo: document.body}) describe('MalioDateWeek', () => { beforeEach(() => { vi.useFakeTimers() vi.setSystemTime(new Date(2026, 4, 19)) // 19 mai 2026 }) afterEach(() => vi.useRealTimers()) it('renders the label and calendar icon', () => { const wrapper = mountWeek({label: 'Semaine'}) expect(wrapper.get('label').text()).toBe('Semaine') expect(wrapper.find('[data-test="calendar-icon"]').exists()).toBe(true) }) it('displays the formatted week when modelValue is set', () => { const wrapper = mountWeek({modelValue: '2026-W21'}) const input = wrapper.get('[data-test="date-input"]').element as HTMLInputElement expect(input.value).toBe('Semaine 21 (18/05 → 24/05/2026)') }) it('shows an empty field without a value', () => { const wrapper = mountWeek() const input = wrapper.get('[data-test="date-input"]').element as HTMLInputElement expect(input.value).toBe('') }) it('opens on the month of the selected week', async () => { const wrapper = mountWeek({modelValue: '2026-W01'}) // lundi 2025-12-29 await wrapper.get('[data-test="date-input"]').trigger('click') expect(wrapper.get('[data-test="header-toggle"]').text()).toContain('Décembre 2025') }) it('selects the week when a day is clicked', async () => { const wrapper = mountWeek() await wrapper.get('[data-test="date-input"]').trigger('click') await wrapper.get('[data-test="day"][data-iso="2026-05-20"]').trigger('click') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['2026-W21']) expect(wrapper.find('[data-test="popover"]').exists()).toBe(false) }) it('selects the week when the week number is clicked', async () => { const wrapper = mountWeek() await wrapper.get('[data-test="date-input"]').trigger('click') await wrapper.get('[data-test="week-number"][data-week-start="2026-05-18"]').trigger('click') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['2026-W21']) expect(wrapper.find('[data-test="popover"]').exists()).toBe(false) }) it('previews the whole week on day hover', async () => { const wrapper = mountWeek() await wrapper.get('[data-test="date-input"]').trigger('click') await wrapper.get('[data-test="day"][data-iso="2026-05-20"]').trigger('mouseenter') expect(wrapper.get('[data-test="day"][data-iso="2026-05-18"]').attributes('data-range-role')).toBe('start') expect(wrapper.get('[data-test="day"][data-iso="2026-05-24"]').attributes('data-range-role')).toBe('end') expect(wrapper.get('[data-test="day"][data-iso="2026-05-20"]').attributes('data-range-role')).toBe('in-range') }) it('previews the whole week on week-number hover', async () => { const wrapper = mountWeek() await wrapper.get('[data-test="date-input"]').trigger('click') await wrapper.get('[data-test="week-number"][data-week-start="2026-05-18"]').trigger('mouseenter') expect(wrapper.get('[data-test="day"][data-iso="2026-05-22"]').attributes('data-range-role')).toBe('in-range') }) it('marks the committed week number', async () => { const wrapper = mountWeek({modelValue: '2026-W21'}) await wrapper.get('[data-test="date-input"]').trigger('click') expect(wrapper.get('[data-test="week-number"][data-week-start="2026-05-18"]').attributes('data-marked')).toBe('true') expect(wrapper.get('[data-test="day"][data-iso="2026-05-18"]').attributes('data-range-role')).toBe('start') }) it('emits null on clear', async () => { const wrapper = mountWeek({modelValue: '2026-W21'}) await wrapper.get('[data-test="clear"]').trigger('click') expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual([null]) }) it('disables a week fully outside min/max', async () => { const wrapper = mountWeek({min: '2026-05-18', max: '2026-05-31'}) await wrapper.get('[data-test="date-input"]').trigger('click') const earlyWeek = wrapper.get('[data-test="week-number"][data-week-start="2026-05-11"]') expect((earlyWeek.element as HTMLButtonElement).disabled).toBe(true) const selectableWeek = wrapper.get('[data-test="week-number"][data-week-start="2026-05-18"]') expect((selectableWeek.element as HTMLButtonElement).disabled).toBe(false) }) it('does not open when disabled', async () => { const wrapper = mountWeek({disabled: true}) await wrapper.get('[data-test="date-input"]').trigger('click') expect(wrapper.find('[data-test="popover"]').exists()).toBe(false) }) it('does not open when readonly', async () => { const wrapper = mountWeek({readonly: true, modelValue: '2026-W21'}) await wrapper.get('[data-test="date-input"]').trigger('click') expect(wrapper.find('[data-test="popover"]').exists()).toBe(false) }) it('sets aria-invalid on error', () => { const wrapper = mountWeek({error: 'Semaine requise'}) expect(wrapper.get('[data-test="date-input"]').attributes('aria-invalid')).toBe('true') expect(wrapper.text()).toContain('Semaine requise') }) })