// Unit tests for routine components. import { describe, it, expect, beforeEach, vi } from 'vitest' import { mount } from '@vue/test-utils' import RoutineEditView from '@/components/routine/RoutineEditView.vue' import RoutineConfirmDialog from '@/components/child/RoutineConfirmDialog.vue' import ModalDialog from '@/components/shared/ModalDialog.vue' // Mock fetch globally global.fetch = vi.fn() describe('RoutineEditView.vue', () => { beforeEach(() => { vi.clearAllMocks() ;(global.fetch as ReturnType).mockClear() }) it('renders create form heading when no id prop provided', async () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) expect(wrapper.text()).toContain('Create Routine') }) it('renders name and points inputs', () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) // EntityEditForm renders inputs with id matching field.name expect(wrapper.find('input[id="name"]').exists()).toBe(true) expect(wrapper.find('input[id="points"]').exists()).toBe(true) }) it('shows Routine Tasks section', () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) expect(wrapper.text()).toContain('Routine Tasks') }) it('shows empty state message when no tasks added', () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) expect(wrapper.text()).toContain('Add at least one task') }) it('shows Add Task button by default', () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) expect(wrapper.text()).toContain('Add Task') }) it('opens item form when Add Task button clicked', async () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) const addBtn = wrapper.find('.add-task-trigger') expect(addBtn.exists()).toBe(true) await addBtn.trigger('click') // Item form should appear with a task name input expect(wrapper.find('input[id="item-name"]').exists()).toBe(true) }) it('allows typing a task name in the add form', async () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) await wrapper.find('.add-task-trigger').trigger('click') const itemInput = wrapper.find('input[id="item-name"]') await itemInput.setValue('Make Bed') expect((itemInput.element as HTMLInputElement).value).toBe('Make Bed') }) it('adds item to list when Add button clicked with valid name', async () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) await wrapper.find('.add-task-trigger').trigger('click') await wrapper.find('input[id="item-name"]').setValue('Make Bed') await wrapper.find('.item-form-actions .btn-primary').trigger('click') await wrapper.vm.$nextTick() // The item name should now appear in the list expect(wrapper.text()).toContain('Make Bed') }) it('renders Cancel and Create buttons', () => { const wrapper = mount(RoutineEditView, { props: { id: undefined }, }) const text = wrapper.text() expect(text).toContain('Cancel') expect(text).toContain('Create') }) it('renders edit heading when id prop provided', async () => { ;(global.fetch as ReturnType) .mockResolvedValueOnce({ ok: true, json: async () => ({ id: 'r1', name: 'Morning Routine', points: 50, image_id: null, image_url: null, }), }) .mockResolvedValueOnce({ ok: true, json: async () => ({ items: [] }), }) const wrapper = mount(RoutineEditView, { props: { id: 'r1' }, }) await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() expect(wrapper.text()).toContain('Edit Routine') }) }) describe('RoutineConfirmDialog.vue', () => { const routine = { id: 'r1', name: 'Morning Routine', points: 20, custom_value: null, image_id: null, image_url: null, pending_status: null, pending_confirmation_id: null, schedule: null, items: [], } it('displays routine name', () => { const wrapper = mount(RoutineConfirmDialog, { props: { routine, childName: 'Timmy' }, global: { components: { ModalDialog } }, }) expect(wrapper.text()).toContain('Morning Routine') }) it('displays child name', () => { const wrapper = mount(RoutineConfirmDialog, { props: { routine, childName: 'Timmy' }, global: { components: { ModalDialog } }, }) expect(wrapper.text()).toContain('Timmy') }) it('emits confirm event when Yes button clicked', async () => { const wrapper = mount(RoutineConfirmDialog, { props: { routine, childName: 'Timmy' }, global: { components: { ModalDialog } }, }) const buttons = wrapper.findAll('button') const confirmBtn = buttons.find((b) => b.text().toLowerCase().includes('yes')) if (confirmBtn) { await confirmBtn.trigger('click') expect(wrapper.emitted('confirm')).toBeTruthy() } }) it('emits cancel event when Cancel button clicked', async () => { const wrapper = mount(RoutineConfirmDialog, { props: { routine, childName: 'Timmy' }, global: { components: { ModalDialog } }, }) const buttons = wrapper.findAll('button') const cancelBtn = buttons.find((b) => b.text().toLowerCase().includes('cancel')) if (cancelBtn) { await cancelBtn.trigger('click') expect(wrapper.emitted('cancel')).toBeTruthy() } }) })