Files
multica/packages/views/common/use-app-foreground.test.ts
Bohan Jiang ace0f16cad fix(chat): badge unread chat replies that arrive while backgrounded (MUL-4485) (#5356)
Gate the Chat unread badge and chat auto mark-read on a shared useAppForeground() signal (document visible AND window focused). A reply arriving while the app is backgrounded now stays unread and badges, and clears when the user returns. Adds foreground-gating regression tests for the sidebar count and useChatController.
2026-07-14 01:41:04 +08:00

71 lines
2.1 KiB
TypeScript

import { act, renderHook } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { useAppForeground } from "./use-app-foreground";
/** Drive jsdom's visibility + focus, then fire the event the hook listens on. */
function setEnv(visible: boolean, focused: boolean) {
Object.defineProperty(document, "visibilityState", {
configurable: true,
get: () => (visible ? "visible" : "hidden"),
});
vi.spyOn(document, "hasFocus").mockReturnValue(focused);
}
afterEach(() => {
vi.restoreAllMocks();
Object.defineProperty(document, "visibilityState", {
configurable: true,
get: () => "visible",
});
});
describe("useAppForeground", () => {
it("is true when the document is visible and focused", () => {
setEnv(true, true);
const { result } = renderHook(() => useAppForeground());
expect(result.current).toBe(true);
});
it("is false when the window loses focus (another app / window on top)", () => {
setEnv(true, false);
const { result } = renderHook(() => useAppForeground());
expect(result.current).toBe(false);
});
it("is false when the tab is hidden even if it still reports focus", () => {
setEnv(false, true);
const { result } = renderHook(() => useAppForeground());
expect(result.current).toBe(false);
});
it("reacts to blur and focus events", () => {
setEnv(true, true);
const { result } = renderHook(() => useAppForeground());
expect(result.current).toBe(true);
act(() => {
setEnv(true, false);
window.dispatchEvent(new Event("blur"));
});
expect(result.current).toBe(false);
act(() => {
setEnv(true, true);
window.dispatchEvent(new Event("focus"));
});
expect(result.current).toBe(true);
});
it("reacts to visibilitychange events", () => {
setEnv(true, true);
const { result } = renderHook(() => useAppForeground());
expect(result.current).toBe(true);
act(() => {
setEnv(false, true);
document.dispatchEvent(new Event("visibilitychange"));
});
expect(result.current).toBe(false);
});
});