fix(workspace): hide ephemeral quick runtimes
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
import { act, renderHook, waitFor } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { RuntimeSnapshot, Workspace, WorkspaceSummary } from "./types";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
invoke: vi.fn(),
|
||||
listeners: {} as Record<string, (message: { payload: any }) => void>,
|
||||
listen: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@tauri-apps/api/core", () => ({ invoke: mocks.invoke }));
|
||||
vi.mock("@tauri-apps/api/event", () => ({ listen: mocks.listen }));
|
||||
vi.mock("@tauri-apps/api/window", () => ({
|
||||
getCurrentWindow: () => ({}),
|
||||
}));
|
||||
vi.mock("./persistence", () => ({
|
||||
legacyPreferences: () => ({}),
|
||||
loadPresentation: async () => ({
|
||||
version: 1,
|
||||
directoryOrder: [],
|
||||
runtimeOrderByDirectory: {},
|
||||
drafts: {},
|
||||
scroll: {},
|
||||
lastSeen: {},
|
||||
}),
|
||||
presentationState: vi.fn(),
|
||||
removeLegacyPreferences: vi.fn(),
|
||||
savePresentation: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
import { useWorkspace } from "./useWorkspace";
|
||||
|
||||
const normalRuntime = {
|
||||
runtimeId: "normal",
|
||||
worktreePath: "/repo",
|
||||
state: "idle",
|
||||
label: "Normal",
|
||||
attention: false,
|
||||
queueCount: 0,
|
||||
lastActivity: "now",
|
||||
openedAt: "now",
|
||||
};
|
||||
const quickRuntime = { ...normalRuntime, runtimeId: "quick", label: "Quick" };
|
||||
|
||||
function workspace(runtimes: (typeof normalRuntime)[]): Workspace {
|
||||
return {
|
||||
bridgeInstanceId: "bridge",
|
||||
latestSeq: 1,
|
||||
directories: [
|
||||
{
|
||||
worktreePath: "/repo",
|
||||
isHome: true,
|
||||
openCount: runtimes.length,
|
||||
workingCount: 0,
|
||||
attentionCount: 0,
|
||||
recoveringCount: 0,
|
||||
errorCount: 0,
|
||||
runtimes,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const summary: WorkspaceSummary = {
|
||||
bridgeInstanceId: "bridge",
|
||||
latestSeq: 1,
|
||||
openCount: 1,
|
||||
workingCount: 0,
|
||||
attentionCount: 0,
|
||||
recoveringCount: 0,
|
||||
errorCount: 0,
|
||||
directoryCount: 1,
|
||||
resourceWarning: false,
|
||||
};
|
||||
|
||||
function snapshot(runtime: typeof normalRuntime): RuntimeSnapshot {
|
||||
return {
|
||||
bridgeInstanceId: "bridge",
|
||||
latestSeq: 1,
|
||||
runtime,
|
||||
extensions: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe("useWorkspace Quick runtime isolation", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
for (const key of Object.keys(mocks.listeners)) delete mocks.listeners[key];
|
||||
mocks.listen.mockImplementation((event, listener) => {
|
||||
mocks.listeners[event] = listener;
|
||||
return Promise.resolve(() => delete mocks.listeners[event]);
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores unknown Quick events and exposes promoted runtime once", async () => {
|
||||
let promoted = false;
|
||||
mocks.invoke.mockImplementation(
|
||||
(command: string, payload?: { runtimeId?: string }) => {
|
||||
if (command === "get_workspace")
|
||||
return Promise.resolve(
|
||||
workspace(promoted ? [normalRuntime, quickRuntime] : [normalRuntime]),
|
||||
);
|
||||
if (command === "get_workspace_summary") return Promise.resolve(summary);
|
||||
if (command === "get_session_runtime_snapshot")
|
||||
return Promise.resolve(
|
||||
snapshot(payload?.runtimeId === "quick" ? quickRuntime : normalRuntime),
|
||||
);
|
||||
if (command === "get_pending_promoted_runtime")
|
||||
return Promise.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(() => useWorkspace());
|
||||
|
||||
await waitFor(() =>
|
||||
expect(result.current.state.runtimesById.normal).toBeDefined(),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(mocks.listeners["workspace-bridge"]).toBeDefined(),
|
||||
);
|
||||
const workspaceCalls = () =>
|
||||
mocks.invoke.mock.calls.filter(([command]) => command === "get_workspace");
|
||||
|
||||
await act(async () => {
|
||||
mocks.listeners["workspace-bridge"]({
|
||||
payload: {
|
||||
kind: "event",
|
||||
event: {
|
||||
bridgeInstanceId: "bridge",
|
||||
seq: 2,
|
||||
type: "runtime_event",
|
||||
data: {
|
||||
runtimeId: "quick",
|
||||
runtime: quickRuntime,
|
||||
eventType: "transcript",
|
||||
eventData: { event: { type: "message_end" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(result.current.state.runtimesById.quick).toBeUndefined();
|
||||
expect(workspaceCalls()).toHaveLength(1);
|
||||
|
||||
promoted = true;
|
||||
await act(async () => {
|
||||
mocks.listeners["workspace-promoted-runtime"]({
|
||||
payload: { runtimeId: "quick" },
|
||||
});
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(result.current.state.runtimesById.quick).toBeDefined(),
|
||||
);
|
||||
expect(result.current.state.runtimeOrderByDirectory["/repo"]).toEqual([
|
||||
"normal",
|
||||
"quick",
|
||||
]);
|
||||
expect(result.current.state.selectedRuntimeId).toBe("quick");
|
||||
expect(workspaceCalls()).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user