diff --git a/frontend/src/App.vue b/frontend/src/App.vue index d3b6227..fd1e714 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -12,6 +12,7 @@ const auth = useAuthStore() const { showError } = useEnhancedToast() const globalErrorHandler = (error: unknown) => { + if (error && typeof error === 'object' && 'silent' in error && error.silent) return showError(error) } diff --git a/frontend/src/shared/components/layout/SyncStatusButton.spec.ts b/frontend/src/shared/components/layout/SyncStatusButton.spec.ts new file mode 100644 index 0000000..dbf40e0 --- /dev/null +++ b/frontend/src/shared/components/layout/SyncStatusButton.spec.ts @@ -0,0 +1,110 @@ +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest' +import { mount } from '@vue/test-utils' +import SyncStatusButton from './SyncStatusButton.vue' +import { useIsFetching, useQueryClient } from '@tanstack/vue-query' +import { useEnhancedToast } from '@/shared/composables/useEnhancedToast' + +// Mock TanStack Query +vi.mock('@tanstack/vue-query', () => ({ + useIsFetching: vi.fn(), + useQueryClient: vi.fn(), +})) + +// Mock Enhanced Toast +vi.mock('@/shared/composables/useEnhancedToast', () => ({ + useEnhancedToast: vi.fn(), +})) + +// Mock Iconify +vi.mock('@iconify/vue', () => ({ + Icon: { template: 'icon' }, +})) + +describe('SyncStatusButton', () => { + let mockQueryClient: { invalidateQueries: Mock } + let mockShowSuccess: Mock + let mockShowError: Mock + + beforeEach(() => { + vi.clearAllMocks() + + mockQueryClient = { + invalidateQueries: vi.fn().mockResolvedValue(undefined), + } + ;(useQueryClient as Mock).mockReturnValue(mockQueryClient) + ;(useIsFetching as Mock).mockReturnValue({ value: 0 }) + + mockShowSuccess = vi.fn() + mockShowError = vi.fn() + ;(useEnhancedToast as Mock).mockReturnValue({ + showSuccess: mockShowSuccess, + showError: mockShowError, + }) + + // Silence console during tests if needed + vi.spyOn(console, 'error').mockImplementation(() => {}) + }) + + it('should call invalidateQueries and show success toast on click', async () => { + vi.useFakeTimers() + const wrapper = mount(SyncStatusButton, { + global: { + stubs: { + TooltipProvider: { template: '
{{ isFetching > 0 ? 'Syncing data...' : 'Refresh all data' }}
+{{ isRefreshing ? 'Syncing data...' : 'Refresh all data' }}