fix(panel): 控制台、玩家页、权限页、文件页和仪表盘自动刷新状态,唤醒或停止后立即显示进行中
This commit is contained in:
24 files changed
+971
-116
No files matched your search
@@ -1,7 +1,7 @@
|
||||
// @vitest-environment jsdom
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { describe, it, expect, vi, afterEach } from "vitest";
|
||||
import { act, renderHook } from "@testing-library/react";
|
||||
import { useAsync, type AsyncOptions } from "./hooks";
|
||||
import { useAsync, usePolling, type AsyncOptions } from "./hooks";
|
||||
|
||||
// A request the test settles by hand, one per call, in call order.
|
||||
function requests() {
|
||||
@@ -100,3 +100,57 @@ describe("useAsync", () => {
|
||||
expect(h.result.current.data).toBe("server b");
|
||||
});
|
||||
});
|
||||
|
||||
describe("usePolling", () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
Object.defineProperty(document, "hidden", { configurable: true, value: false });
|
||||
});
|
||||
|
||||
function setHidden(hidden: boolean) {
|
||||
Object.defineProperty(document, "hidden", { configurable: true, value: hidden });
|
||||
document.dispatchEvent(new Event("visibilitychange"));
|
||||
}
|
||||
|
||||
it("reloads on every tick while the tab is in view, and at once when it comes back", () => {
|
||||
vi.useFakeTimers();
|
||||
const reload = vi.fn();
|
||||
renderHook(() => usePolling(reload, 1000));
|
||||
|
||||
vi.advanceTimersByTime(2500);
|
||||
expect(reload).toHaveBeenCalledTimes(2);
|
||||
|
||||
setHidden(true);
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(reload).toHaveBeenCalledTimes(2);
|
||||
|
||||
setHidden(false);
|
||||
expect(reload).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it("follows a new interval and stops when paused or unmounted", () => {
|
||||
vi.useFakeTimers();
|
||||
const reload = vi.fn();
|
||||
const hook = renderHook(({ ms }: { ms: number | null }) => usePolling(reload, ms), {
|
||||
initialProps: { ms: 1000 as number | null },
|
||||
});
|
||||
vi.advanceTimersByTime(1000);
|
||||
expect(reload).toHaveBeenCalledTimes(1);
|
||||
|
||||
hook.rerender({ ms: 5000 });
|
||||
vi.advanceTimersByTime(4000);
|
||||
expect(reload).toHaveBeenCalledTimes(1);
|
||||
vi.advanceTimersByTime(1000);
|
||||
expect(reload).toHaveBeenCalledTimes(2);
|
||||
|
||||
hook.rerender({ ms: null });
|
||||
vi.advanceTimersByTime(20000);
|
||||
setHidden(false);
|
||||
expect(reload).toHaveBeenCalledTimes(2);
|
||||
|
||||
hook.rerender({ ms: 1000 });
|
||||
hook.unmount();
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(reload).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
@@ -112,3 +112,26 @@ export function useUnsavedGuard(dirty: boolean): void {
|
||||
return () => window.removeEventListener("beforeunload", onBeforeUnload);
|
||||
}, [dirty]);
|
||||
}
|
||||
|
||||
/** How often a server page rereads its status: fast while it waits on the
|
||||
* server (coming up, going down, or needed up), slow while nothing is due. */
|
||||
export const STATUS_POLL_FAST_MS = 4_000;
|
||||
export const STATUS_POLL_SLOW_MS = 15_000;
|
||||
|
||||
/** usePolling re-runs `reload` every `ms` while the tab is visible, and at once
|
||||
* when the tab comes back into view, so a page watching a server follows it
|
||||
* without a manual refresh. `ms` null pauses it. */
|
||||
export function usePolling(reload: () => void, ms: number | null): void {
|
||||
useEffect(() => {
|
||||
if (ms === null) return;
|
||||
const tick = () => {
|
||||
if (!document.hidden) reload();
|
||||
};
|
||||
const id = window.setInterval(tick, ms);
|
||||
document.addEventListener("visibilitychange", tick);
|
||||
return () => {
|
||||
window.clearInterval(id);
|
||||
document.removeEventListener("visibilitychange", tick);
|
||||
};
|
||||
}, [reload, ms]);
|
||||
}
|
||||
Reference in new issue
Block a user