From 386d629cde03247c8d6a08d7b97f4af19412daaf Mon Sep 17 00:00:00 2001 From: Xavier Abad Date: Wed, 11 Feb 2026 11:07:01 +0100 Subject: [PATCH 1/2] fix: empty state after clearing trash --- src/services/sockets/socket.service.test.ts | 4 +++- src/services/sockets/socket.service.ts | 19 ++++++++++--------- .../DriveExplorer/DriveExplorer.tsx | 9 ++++++++- src/views/Drive/hooks/usePaginationState.ts | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/services/sockets/socket.service.test.ts b/src/services/sockets/socket.service.test.ts index d1e75e2f17..2c398fe67a 100644 --- a/src/services/sockets/socket.service.test.ts +++ b/src/services/sockets/socket.service.test.ts @@ -95,11 +95,13 @@ describe('RealtimeService', () => { test.each([ { isProduction: true, reconnection: true, withCredentials: true, logs: false }, - { isProduction: false, reconnection: true, withCredentials: false, logs: true }, + { isProduction: false, reconnection: false, withCredentials: false, logs: true }, ])( 'When running in isProduction=$isProduction environment, then it adjusts reconnection=$reconnection, withCredentials=$withCredentials and logging=$logs', ({ isProduction, reconnection, withCredentials, logs }) => { vi.spyOn(envService, 'isProduction').mockReturnValue(isProduction); + (RealtimeService as unknown as { instance: RealtimeService | undefined }).instance = undefined; + service = RealtimeService.getInstance(); service.init(); diff --git a/src/services/sockets/socket.service.ts b/src/services/sockets/socket.service.ts index 8f590fee8a..a15800a8eb 100644 --- a/src/services/sockets/socket.service.ts +++ b/src/services/sockets/socket.service.ts @@ -8,6 +8,7 @@ export default class RealtimeService { private socket?: Socket; private static instance: RealtimeService; private readonly eventHandlers: Set<(data: EventData) => void> = new Set(); + private readonly isProduction = envService.isProduction(); static getInstance(): RealtimeService { if (!this.instance) { @@ -18,7 +19,7 @@ export default class RealtimeService { } init(onConnected?: () => void): void { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME]: CONNECTING...'); } @@ -26,12 +27,12 @@ export default class RealtimeService { auth: { token: getToken(), }, - reconnection: true, - withCredentials: envService.isProduction(), + reconnection: this.isProduction, + withCredentials: this.isProduction, }); this.socket.on('connect', () => { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME]: CONNECTED WITH ID', this.socket?.id); } onConnected?.(); @@ -50,13 +51,13 @@ export default class RealtimeService { }); this.socket.on('disconnect', (reason) => { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME] DISCONNECTED:', reason); } }); this.socket.on('connect_error', (error) => { - if (!envService.isProduction()) console.error('[REALTIME] CONNECTION ERROR:', error); + if (!this.isProduction) console.error('[REALTIME] CONNECTION ERROR:', error); }); } @@ -68,14 +69,14 @@ export default class RealtimeService { } onEvent(cb: (data: any) => void): () => void { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME] Registering event handler. Total handlers:', this.eventHandlers.size + 1); } this.eventHandlers.add(cb); return () => { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME] Removing event handler. Remaining handlers:', this.eventHandlers.size - 1); } this.eventHandlers.delete(cb); @@ -83,7 +84,7 @@ export default class RealtimeService { } removeAllListeners() { - if (!envService.isProduction()) { + if (!this.isProduction) { console.log('[REALTIME] Clearing all event handlers'); } this.eventHandlers.clear(); diff --git a/src/views/Drive/components/DriveExplorer/DriveExplorer.tsx b/src/views/Drive/components/DriveExplorer/DriveExplorer.tsx index d93a3c9264..26590fe2cc 100644 --- a/src/views/Drive/components/DriveExplorer/DriveExplorer.tsx +++ b/src/views/Drive/components/DriveExplorer/DriveExplorer.tsx @@ -416,6 +416,13 @@ const DriveExplorer = (props: DriveExplorerProps): JSX.Element => { } }; + const onTrashCleared = useCallback(() => { + dispatch(storageActions.resetTrash()); + paginationState.setHasMoreItems(false); + setHasMoreTrashFolders(false); + onItemsDeleted?.(); + }, [onItemsDeleted]); + const onCloseEditItemDialog = (newItem) => { if (newItem && editNameItem) { if (isFileViewerOpen) { @@ -530,7 +537,7 @@ const DriveExplorer = (props: DriveExplorerProps): JSX.Element => { }} isTrash={isTrash} /> - + diff --git a/src/views/Drive/hooks/usePaginationState.ts b/src/views/Drive/hooks/usePaginationState.ts index 121444ee9c..3d205ba424 100644 --- a/src/views/Drive/hooks/usePaginationState.ts +++ b/src/views/Drive/hooks/usePaginationState.ts @@ -19,7 +19,7 @@ export const usePaginationState = ({ isTrash, hasMoreFiles, hasMoreFolders }: Us }, [hasMoreFiles, isTrash]); useEffect(() => { - if (hasMoreFiles && hasMoreFolders) { + if (!isTrash && hasMoreFiles && hasMoreFolders) { setHasMoreItems(true); } }, [hasMoreFiles, hasMoreFolders]); From e74b9df2192c50b5bd0049ad0423f5cf2a162e17 Mon Sep 17 00:00:00 2001 From: Xavier Abad Date: Wed, 11 Feb 2026 14:11:50 +0100 Subject: [PATCH 2/2] tests: socket service --- src/services/sockets/socket.service.test.ts | 58 +++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/services/sockets/socket.service.test.ts b/src/services/sockets/socket.service.test.ts index 2c398fe67a..4e979eb24f 100644 --- a/src/services/sockets/socket.service.test.ts +++ b/src/services/sockets/socket.service.test.ts @@ -120,6 +120,64 @@ describe('RealtimeService', () => { ); }); + describe('Logging behavior', () => { + const resetServiceWithProduction = (isProduction: boolean) => { + vi.spyOn(envService, 'isProduction').mockReturnValue(isProduction); + (RealtimeService as unknown as { instance: RealtimeService | undefined }).instance = undefined; + return RealtimeService.getInstance(); + }; + + test('When not in production, then it logs on connect event', () => { + service = resetServiceWithProduction(false); + service.init(); + const connectHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'connect')?.[1]; + connectHandler?.(); + expect(consoleLogSpy).toHaveBeenCalledWith('[REALTIME]: CONNECTED WITH ID', mockSocket.id); + }); + + test('When in production, then it does not log on connect event', () => { + service = resetServiceWithProduction(true); + service.init(); + const connectHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'connect')?.[1]; + connectHandler?.(); + expect(consoleLogSpy).not.toHaveBeenCalledWith('[REALTIME]: CONNECTED WITH ID', mockSocket.id); + }); + + test('When not in production, then it logs on disconnect event', () => { + service = resetServiceWithProduction(false); + service.init(); + const disconnectHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'disconnect')?.[1]; + disconnectHandler?.('transport close'); + expect(consoleLogSpy).toHaveBeenCalledWith('[REALTIME] DISCONNECTED:', 'transport close'); + }); + + test('When in production, then it does not log on disconnect event', () => { + service = resetServiceWithProduction(true); + service.init(); + const disconnectHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'disconnect')?.[1]; + disconnectHandler?.('transport close'); + expect(consoleLogSpy).not.toHaveBeenCalledWith('[REALTIME] DISCONNECTED:', 'transport close'); + }); + + test('When not in production, then it logs errors on connect_error event', () => { + service = resetServiceWithProduction(false); + service.init(); + const connectErrorHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'connect_error')?.[1]; + const error = new Error('connection refused'); + connectErrorHandler?.(error); + expect(consoleErrorSpy).toHaveBeenCalledWith('[REALTIME] CONNECTION ERROR:', error); + }); + + test('When in production, then it does not log errors on connect_error event', () => { + service = resetServiceWithProduction(true); + service.init(); + const connectErrorHandler = mockSocket.on.mock.calls.find((call) => call[0] === 'connect_error')?.[1]; + const error = new Error('connection refused'); + connectErrorHandler?.(error); + expect(consoleErrorSpy).not.toHaveBeenCalledWith('[REALTIME] CONNECTION ERROR:', error); + }); + }); + describe('Retrieving connection identifier', () => { test('When getting the client Id after initialization, then it provides a unique identifier', () => { service.init();