import { describe, it, expect, beforeEach, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createPinia, setActivePinia } from 'pinia' import { useUi } from '@/stores/useUi' import { useTareasStore } from '@/stores/useTareas' import TareasIndex from '../TareasIndex.vue' import TablaTareas from '@/components/tareas/tablaTareas.vue' import CardTarea from '@/components/tareas/cardTarea.vue' // Mock child components vi.mock('@/components/tareas/tablaTareas.vue', () => ({ default: { name: 'TablaTareas', props: ['tareas'], // Match actual props emits: ['edit'], template: '
', }, })) vi.mock('@/components/tareas/cardTarea.vue', () => ({ default: { name: 'CardTarea', props: ['tarea'], // Match actual props emits: ['edit'], template: '', }, })) // Mock stores const mockSetDefaultViewTareas = vi.fn(); const mockFetchTareas = vi.fn(); vi.mock('@/stores/useUi', () => ({ useUi: vi.fn(() => ({ defaultViewTareas: 'table', // Default mock value setDefaultViewTareas: mockSetDefaultViewTareas, })), })) vi.mock('@/stores/useTareas', () => ({ useTareasStore: vi.fn(() => ({ tareas: [], fetchTareas: mockFetchTareas, })), })) describe('TareasIndex.vue', () => { let uiStoreMock let tareasStoreMock beforeEach(() => { setActivePinia(createPinia()) mockFetchTareas.mockClear().mockResolvedValue([]) mockSetDefaultViewTareas.mockClear() uiStoreMock = useUi() tareasStoreMock = useTareasStore() }) const mountComponent = () => { return mount(TareasIndex, { global: {}, }) } it('fetches tareas on mount', async () => { mountComponent() await mockFetchTareas(); // Ensure the promise from fetch resolves expect(mockFetchTareas).toHaveBeenCalledTimes(1) }) describe('View Rendering based on useUi store', () => { it('renders TablaTareas when defaultViewTareas is "table"', async () => { uiStoreMock.defaultViewTareas = 'table' tareasStoreMock.tareas = [{ id: 1, titulo: 'Test Task', completada: false }] const wrapper = mountComponent() await mockFetchTareas(); await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() expect(wrapper.findComponent({ name: 'TablaTareas' }).exists()).toBe(true) const expected = [...tareasStoreMock.tareas].sort((a, b) => b.id - a.id) expect(wrapper.findComponent({ name: 'TablaTareas' }).props('tareas')).toEqual(expected) expect(wrapper.findComponent({ name: 'CardTarea' }).exists()).toBe(false) }) it('renders CardTarea when defaultViewTareas is "card"', async () => { uiStoreMock.defaultViewTareas = 'card' tareasStoreMock.tareas = [{ id: 1, T1: 'T1' }, { id: 2, T2: 'T2' }] const wrapper = mountComponent() await mockFetchTareas(); await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() const cardWrappers = wrapper.findAllComponents({ name: 'CardTarea' }) const expected = [...tareasStoreMock.tareas].sort((a, b) => b.id - a.id) expect(cardWrappers.length).toBe(expected.length) expect(cardWrappers[0].props('tarea')).toEqual(expected[0]) expect(wrapper.findComponent({ name: 'TablaTareas' }).exists()).toBe(false) }) it('renders no data message for table view when no tareas exist', async () => { uiStoreMock.defaultViewTareas = 'table'; tareasStoreMock.tareas = []; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); expect(wrapper.findComponent({ name: 'TablaTareas' }).exists()).toBe(true); expect(wrapper.text()).toContain('No hay tareas para mostrar'); }); it('renders no data message for card view when no tareas exist', async () => { uiStoreMock.defaultViewTareas = 'card'; tareasStoreMock.tareas = []; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); expect(wrapper.findAllComponents({ name: 'CardTarea' }).length).toBe(0); expect(wrapper.text()).toContain('No hay tareas para mostrar'); }); }) describe('Local View Toggle Buttons', () => { it('renders toggle buttons and reflects initial view from store (table)', async () => { uiStoreMock.defaultViewTareas = 'table'; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); const tableViewButton = wrapper.find('button[aria-label="Table View"]'); const cardViewButton = wrapper.find('button[aria-label="Card View"]'); expect(tableViewButton.exists()).toBe(true); expect(cardViewButton.exists()).toBe(true); expect(tableViewButton.classes()).toContain('bg-[var(--accent-color-tareas)]'); expect(cardViewButton.classes()).toContain('bg-gray-200'); }); it('renders toggle buttons and reflects initial view from store (card)', async () => { uiStoreMock.defaultViewTareas = 'card'; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); const tableViewButton = wrapper.find('button[aria-label="Table View"]'); const cardViewButton = wrapper.find('button[aria-label="Card View"]'); expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-tareas)]'); expect(tableViewButton.classes()).toContain('bg-gray-200'); }); it('switches to card view on button click and updates button styles, does not call global store action', async () => { uiStoreMock.defaultViewTareas = 'table'; tareasStoreMock.tareas = [{ id: 1, titulo: 'Test' }]; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); const cardViewButton = wrapper.find('button[aria-label="Card View"]'); const tableViewButton = wrapper.find('button[aria-label="Table View"]'); await cardViewButton.trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.findComponent({ name: 'CardTarea' }).exists()).toBe(true); expect(wrapper.findComponent({ name: 'TablaTareas' }).exists()).toBe(false); expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-tareas)]'); expect(tableViewButton.classes()).toContain('bg-gray-200'); expect(mockSetDefaultViewTareas).not.toHaveBeenCalled(); }); it('switches back to table view on button click and updates button styles, does not call global store action', async () => { uiStoreMock.defaultViewTareas = 'card'; // Start with card view tareasStoreMock.tareas = [{ id: 1, titulo: 'Test' }]; const wrapper = mountComponent(); await mockFetchTareas(); await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick(); const cardViewButton = wrapper.find('button[aria-label="Card View"]'); const tableViewButton = wrapper.find('button[aria-label="Table View"]'); expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-tareas)]'); await tableViewButton.trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.findComponent({ name: 'TablaTareas' }).exists()).toBe(true); expect(wrapper.findComponent({ name: 'CardTarea' }).exists()).toBe(false); expect(tableViewButton.classes()).toContain('bg-[var(--accent-color-tareas)]'); expect(cardViewButton.classes()).toContain('bg-gray-200'); expect(mockSetDefaultViewTareas).not.toHaveBeenCalled(); }); }); })