11import { describe , it , expect , vi , beforeEach , type Mock } from 'vitest'
22import { mount } from '@vue/test-utils'
33import SyncStatusButton from './SyncStatusButton.vue'
4- import { useIsFetching , useQueryClient } from '@tanstack/vue-query'
4+ import { useIsFetching , useQueryClient , onlineManager } from '@tanstack/vue-query'
55import { useEnhancedToast } from '@/shared/composables/useEnhancedToast'
66
77// Mock TanStack Query
88vi . mock ( '@tanstack/vue-query' , ( ) => ( {
99 useIsFetching : vi . fn ( ) ,
1010 useQueryClient : vi . fn ( ) ,
11+ onlineManager : {
12+ isOnline : vi . fn ( ) ,
13+ } ,
1114} ) )
1215
1316// Mock Enhanced Toast
@@ -33,6 +36,7 @@ describe('SyncStatusButton', () => {
3336 }
3437 ; ( useQueryClient as Mock ) . mockReturnValue ( mockQueryClient )
3538 ; ( useIsFetching as Mock ) . mockReturnValue ( { value : 0 } )
39+ ; ( onlineManager . isOnline as Mock ) . mockReturnValue ( true )
3640
3741 mockShowSuccess = vi . fn ( )
3842 mockShowError = vi . fn ( )
@@ -45,7 +49,7 @@ describe('SyncStatusButton', () => {
4549 vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } )
4650 } )
4751
48- it ( 'should call invalidateQueries and show success toast on click' , async ( ) => {
52+ it ( 'should call invalidateQueries and show success toast on click when online ' , async ( ) => {
4953 vi . useFakeTimers ( )
5054 const wrapper = mount ( SyncStatusButton , {
5155 global : {
@@ -72,15 +76,44 @@ describe('SyncStatusButton', () => {
7276 await vi . advanceTimersByTimeAsync ( 600 )
7377
7478 expect ( mockShowSuccess ) . toHaveBeenCalledWith (
75- 'Data synchronized' ,
76- 'All active data views have been updated.'
79+ 'Data is updated successfully!'
7780 )
7881 vi . useRealTimers ( )
7982 } )
8083
81- it ( 'should show error toast and mark error as silent on failure ' , async ( ) => {
84+ it ( 'should show "Sync Paused" error when offline after click ' , async ( ) => {
8285 vi . useFakeTimers ( )
83- const error = new Error ( 'Sync failed' )
86+ ; ( onlineManager . isOnline as Mock ) . mockReturnValue ( false )
87+
88+ const wrapper = mount ( SyncStatusButton , {
89+ global : {
90+ stubs : {
91+ TooltipProvider : { template : '<div><slot /></div>' } ,
92+ Tooltip : { template : '<div><slot /></div>' } ,
93+ TooltipTrigger : { template : '<div><slot /></div>' } ,
94+ TooltipContent : { template : '<div><slot /></div>' } ,
95+ Button : {
96+ template : '<button @click="$emit(\'click\')"><slot /></button>' ,
97+ props : [ 'disabled' ] ,
98+ } ,
99+ } ,
100+ } ,
101+ } )
102+
103+ const button = wrapper . find ( 'button' )
104+ await button . trigger ( 'click' )
105+
106+ await vi . advanceTimersByTimeAsync ( 600 )
107+
108+ expect ( mockShowError ) . toHaveBeenCalled ( )
109+ const errorPassed = mockShowError . mock . calls [ 0 ] [ 0 ]
110+ expect ( errorPassed . message ) . toContain ( 'currently offline' )
111+ vi . useRealTimers ( )
112+ } )
113+
114+ it ( 'should NOT call showError on query failure (relying on global handler)' , async ( ) => {
115+ vi . useFakeTimers ( )
116+ const error = new Error ( 'Network error' )
84117 mockQueryClient . invalidateQueries . mockRejectedValue ( error )
85118
86119 const wrapper = mount ( SyncStatusButton , {
@@ -103,8 +136,7 @@ describe('SyncStatusButton', () => {
103136
104137 await vi . advanceTimersByTimeAsync ( 600 )
105138
106- expect ( mockShowError ) . toHaveBeenCalledWith ( error , 'Sync Failed' )
107- expect ( ( error as Error & { silent ?: boolean } ) . silent ) . toBe ( true )
139+ expect ( mockShowError ) . not . toHaveBeenCalled ( )
108140 vi . useRealTimers ( )
109141 } )
110142} )
0 commit comments