import { describe, it, expect, beforeEach, vi } from 'vitest'; import { createPinia, setActivePinia } from 'pinia'; vi.mock('../../resources/js/api/reminders', () => ({ listReminders: vi.fn(), createReminder: vi.fn(), updateReminder: vi.fn(), completeReminder: vi.fn(), deleteReminder: vi.fn(), })); vi.mock('../../resources/js/api/client', () => ({ apiClient: {}, ensureCsrfCookie: vi.fn(), extractValidationErrors: vi.fn(() => null), extractErrorMessage: vi.fn(() => 'Произошла ошибка.'), extractRateLimitRetry: vi.fn(() => null), })); import * as remindersApi from '../../resources/js/api/reminders'; import { useRemindersStore } from '../../resources/js/stores/reminders'; import type { ApiReminder } from '../../resources/js/api/reminders'; const mockReminder = (id: number, overrides: Partial = {}): ApiReminder => ({ id, deal_id: 100 + id, text: `Напоминание #${id}`, remind_at: new Date(2026, 4, 9, 14 + id, 0).toISOString(), completed_at: null, is_sent: false, sent_at: null, created_at: new Date(2026, 4, 9, 12, 0).toISOString(), created_by: 1, assignee_id: null, creator_name: 'Иван Петров', ...overrides, }); describe('useRemindersStore', () => { beforeEach(() => { setActivePinia(createPinia()); vi.clearAllMocks(); }); it('initial state', () => { const store = useRemindersStore(); expect(store.items).toEqual([]); expect(store.counts).toEqual({ active: 0, today: 0, upcoming: 0, overdue: 0 }); }); it('load() заполняет items + counts', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1), mockReminder(2)], counts: { active: 2, today: 1, upcoming: 1, overdue: 0 }, }); const store = useRemindersStore(); await store.load(); expect(store.items).toHaveLength(2); expect(store.counts.active).toBe(2); }); it('load() при reject ставит fetchError', async () => { vi.mocked(remindersApi.listReminders).mockRejectedValue(new Error('500')); const store = useRemindersStore(); await store.load(); expect(store.fetchError).toBe(true); }); it('refreshCounts() обновляет только counts', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1)], counts: { active: 5, today: 2, upcoming: 1, overdue: 2 }, }); const store = useRemindersStore(); store.items = [mockReminder(99)]; // pre-populate await store.refreshCounts(); expect(store.counts.active).toBe(5); expect(store.items).toHaveLength(1); // не тронуто }); it('create() добавляет в начало + increment active', async () => { const newR = mockReminder(99); vi.mocked(remindersApi.createReminder).mockResolvedValue(newR); const store = useRemindersStore(); store.counts.active = 3; await store.create({ deal_id: 100, remind_at: new Date().toISOString() }); expect(store.items[0]!.id).toBe(99); expect(store.counts.active).toBe(4); }); it('create() при reject возвращает null', async () => { vi.mocked(remindersApi.createReminder).mockRejectedValue(new Error('500')); const store = useRemindersStore(); const result = await store.create({ deal_id: 100, remind_at: new Date().toISOString() }); expect(result).toBeNull(); }); it('complete() optimistic + decrement active', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1)], counts: { active: 1, today: 1, upcoming: 0, overdue: 0 }, }); vi.mocked(remindersApi.completeReminder).mockResolvedValue( mockReminder(1, { completed_at: '2026-05-09T15:00:00Z' }), ); const store = useRemindersStore(); await store.load(); await store.complete(1); expect(store.counts.active).toBe(0); // currentFilter='active' → удалили из items. expect(store.items).toHaveLength(0); }); it('complete() при reject — revert', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1)], counts: { active: 1, today: 1, upcoming: 0, overdue: 0 }, }); vi.mocked(remindersApi.completeReminder).mockRejectedValue(new Error('500')); const store = useRemindersStore(); await store.load(); await store.complete(1); expect(store.counts.active).toBe(1); expect(store.items[0]!.completed_at).toBeNull(); }); it('remove() optimistic убирает + decrement', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1), mockReminder(2)], counts: { active: 2, today: 1, upcoming: 1, overdue: 0 }, }); vi.mocked(remindersApi.deleteReminder).mockResolvedValue(); const store = useRemindersStore(); await store.load(); await store.remove(1); expect(store.items).toHaveLength(1); expect(store.counts.active).toBe(1); }); it('remove() при reject — revert', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1), mockReminder(2)], counts: { active: 2, today: 1, upcoming: 1, overdue: 0 }, }); vi.mocked(remindersApi.deleteReminder).mockRejectedValue(new Error('500')); const store = useRemindersStore(); await store.load(); await store.remove(1); expect(store.items).toHaveLength(2); expect(store.counts.active).toBe(2); }); it('reset() очищает', async () => { vi.mocked(remindersApi.listReminders).mockResolvedValue({ items: [mockReminder(1)], counts: { active: 1, today: 1, upcoming: 0, overdue: 0 }, }); const store = useRemindersStore(); await store.load(); store.reset(); expect(store.items).toEqual([]); expect(store.counts).toEqual({ active: 0, today: 0, upcoming: 0, overdue: 0 }); }); });