/* @vitest-environment jsdom */ import { act, renderHook, waitFor } from '@testing-library/react'; import { type ReactNode, StrictMode } from 'react'; import { beforeEach, expect, test, vi } from 'vitest'; const profileClientMocks = vi.hoisted(() => ({ getPlatformProfileRechargeCenter: vi.fn(), })); vi.mock('../services/platform-entry/platformProfileClient', () => ({ getPlatformProfileRechargeCenter: profileClientMocks.getPlatformProfileRechargeCenter, })); import { usePlatformWalletLifecycle, usePlatformWalletStore, } from './usePlatformWalletStore'; beforeEach(() => { vi.clearAllMocks(); usePlatformWalletStore.getState().resetWalletBalance(); profileClientMocks.getPlatformProfileRechargeCenter.mockResolvedValue({ walletBalance: 42, mudPointBalance: { totalPoints: 42, permanentPoints: 42, limitedPoints: 0, limitedExpiresAt: null, dailyFreePoints: 0, dailyFreeResetPoints: 20, dailyFreeResetsAt: '2026-08-08T00:00:00+08:00', }, }); }); test('the single lifecycle survives StrictMode replay and resets on root unmount', async () => { const addWindowListener = vi.spyOn(window, 'addEventListener'); const removeWindowListener = vi.spyOn(window, 'removeEventListener'); const { unmount } = renderHook( () => usePlatformWalletLifecycle('user-1', true), { wrapper: ({ children }: { children: ReactNode }) => ( {children} ), }, ); await waitFor(() => { expect(usePlatformWalletStore.getState()).toMatchObject({ ownerUserId: 'user-1', mudPointBalance: expect.objectContaining({ totalPoints: 42 }), legacyWalletBalance: 42, mudPointBalanceStatus: 'ready', }); }); const requestsBeforeFocus = profileClientMocks.getPlatformProfileRechargeCenter.mock.calls.length; await act(async () => { window.dispatchEvent(new Event('focus')); }); await waitFor(() => { expect( profileClientMocks.getPlatformProfileRechargeCenter.mock.calls.length, ).toBeGreaterThan(requestsBeforeFocus); }); unmount(); expect(usePlatformWalletStore.getState()).toMatchObject({ ownerUserId: null, mudPointBalance: null, legacyWalletBalance: null, mudPointBalanceStatus: 'idle', }); expect( addWindowListener.mock.calls.filter(([eventName]) => eventName === 'focus'), ).toHaveLength( removeWindowListener.mock.calls.filter( ([eventName]) => eventName === 'focus', ).length, ); });