Terminal file viewer/editor + per-window app-command lockdown (#60)
Build App / compute-version (push) Successful in 7s
Secret Scan / scan (push) Successful in 8s
Build App / build-macos (push) Successful in 2m53s
Build App / build-linux (push) Successful in 5m12s
Build App / build-windows (push) Successful in 5m15s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 1m5s
Build App / compute-version (push) Successful in 7s
Secret Scan / scan (push) Successful in 8s
Build App / build-macos (push) Successful in 2m53s
Build App / build-linux (push) Successful in 5m12s
Build App / build-windows (push) Successful in 5m15s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 1m5s
Clicking a file path in Claude's terminal output now opens the file in its own window with a CodeMirror 6 editor. The editor highlights the target line, live-reloads while the file changes, and saves explicitly with hash-based conflict detection. The viewer commands are gated by window label. Every app command is now ACL-gated per window through a Tauri AppManifest. build.rs checks the handler list against the capability files and fails the build on any mismatch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #60.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { renderHook } from "@testing-library/react";
|
||||
import { useViewerPolling } from "./useViewerPolling";
|
||||
|
||||
describe("useViewerPolling", () => {
|
||||
beforeEach(() => vi.useFakeTimers());
|
||||
afterEach(() => vi.useRealTimers());
|
||||
|
||||
const setVisibility = (state: DocumentVisibilityState) => {
|
||||
Object.defineProperty(document, "visibilityState", { value: state, configurable: true });
|
||||
document.dispatchEvent(new Event("visibilitychange"));
|
||||
};
|
||||
|
||||
it("ticks on the interval only while visible, and once immediately on becoming visible", async () => {
|
||||
setVisibility("visible");
|
||||
const tick = vi.fn(async () => {});
|
||||
renderHook(() => useViewerPolling(2000, tick, true));
|
||||
expect(tick).toHaveBeenCalledTimes(1); // initial
|
||||
await vi.advanceTimersByTimeAsync(4000);
|
||||
expect(tick).toHaveBeenCalledTimes(3);
|
||||
setVisibility("hidden");
|
||||
await vi.advanceTimersByTimeAsync(6000);
|
||||
expect(tick).toHaveBeenCalledTimes(3);
|
||||
setVisibility("visible");
|
||||
expect(tick).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
it("does not overlap ticks and stops when disabled", async () => {
|
||||
setVisibility("visible");
|
||||
let resolve: () => void = () => {};
|
||||
const tick = vi.fn(() => new Promise<void>((r) => { resolve = r; }));
|
||||
const { rerender } = renderHook(({ on }) => useViewerPolling(1000, tick, on), { initialProps: { on: true } });
|
||||
await vi.advanceTimersByTimeAsync(3000);
|
||||
expect(tick).toHaveBeenCalledTimes(1);
|
||||
resolve();
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(tick).toHaveBeenCalledTimes(2);
|
||||
rerender({ on: false });
|
||||
resolve();
|
||||
await vi.advanceTimersByTimeAsync(5000);
|
||||
expect(tick).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user