/* @vitest-environment jsdom */ import { act, renderHook } from '@testing-library/react'; import { afterEach, expect, test, vi } from 'vitest'; import { subscribeHostAppLifecycle } from '../services/host-bridge/hostBridge'; import { useHostLifecycleActive } from './useHostLifecycleActive'; vi.mock('../services/host-bridge/hostBridge', () => ({ subscribeHostAppLifecycle: vi.fn(() => () => undefined), })); const subscribeHostAppLifecycleMock = vi.mocked(subscribeHostAppLifecycle); afterEach(() => { vi.clearAllMocks(); }); test('host lifecycle active defaults to active when host lifecycle is unavailable', () => { const { result } = renderHook(() => useHostLifecycleActive()); expect(result.current).toBe(true); expect(subscribeHostAppLifecycleMock).toHaveBeenCalledTimes(1); }); test('host lifecycle active follows native app lifecycle events', () => { const unsubscribe = vi.fn(); let lifecycleListener: | Parameters[0] | null = null; subscribeHostAppLifecycleMock.mockImplementation((listener) => { lifecycleListener = listener; return unsubscribe; }); const { result, unmount } = renderHook(() => useHostLifecycleActive()); expect(result.current).toBe(true); act(() => { lifecycleListener?.({ state: 'inactive', focused: false, nativeState: 'blur', }); }); expect(result.current).toBe(false); act(() => { lifecycleListener?.({ state: 'active', focused: false, nativeState: 'active', }); }); expect(result.current).toBe(false); act(() => { lifecycleListener?.({ state: 'active', focused: true, nativeState: 'active', }); }); expect(result.current).toBe(true); unmount(); expect(unsubscribe).toHaveBeenCalledTimes(1); }); test('host lifecycle active treats background as inactive even when focused is true', () => { let lifecycleListener: | Parameters[0] | null = null; subscribeHostAppLifecycleMock.mockImplementation((listener) => { lifecycleListener = listener; return () => undefined; }); const { result } = renderHook(() => useHostLifecycleActive()); act(() => { lifecycleListener?.({ state: 'background', focused: false, nativeState: 'hidden', }); }); expect(result.current).toBe(false); act(() => { lifecycleListener?.({ state: 'background', focused: true, nativeState: 'minimized', }); }); expect(result.current).toBe(false); act(() => { lifecycleListener?.({ state: 'active', focused: true, nativeState: 'focused', }); }); expect(result.current).toBe(true); });