Files
Genarrative/src/hooks/useHostLifecycleActive.test.tsx
T
kdletters a471e69455 补齐桌面壳后台生命周期
桌面壳生命周期按可见性、最小化和焦点统一归一

托盘隐藏前注入 background 并在恢复窗口时回放当前状态

H5 lifecycle 测试覆盖 background 暂停语义

宿主壳文档和原生壳门禁同步桌面 background 约定
2026-06-19 04:25:42 +08:00

108 lines
2.7 KiB
TypeScript

/* @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<typeof subscribeHostAppLifecycle>[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<typeof subscribeHostAppLifecycle>[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);
});