feat(workbench): integrate operational workflows and map state

This commit is contained in:
2026-09-24 04:34:46 +08:00
parent 1752b9ef84
commit 436d5500f1
76 changed files with 5081 additions and 1937 deletions
@@ -36,6 +36,37 @@ describe("workbench project client", () => {
await expect(findOwnedWorkbenchProject()).rejects.toThrow("授权项目");
});
it("does not share a caller-bound abort signal with other project consumers", async () => {
const projectPage = JSON.stringify({
items: [{ project_id: "supply", gs_workspace: "tjwater_next", status: "active" }],
total: 1,
limit: 1000,
offset: 0
});
const fetchMock = vi.fn((_input: RequestInfo | URL, init?: RequestInit) => {
if (!init?.signal) {
return Promise.resolve(new Response(projectPage, { status: 200 }));
}
return new Promise<Response>((_resolve, reject) => {
init.signal?.addEventListener("abort", () => {
reject(new DOMException("Aborted", "AbortError"));
}, { once: true });
});
});
vi.stubGlobal("fetch", fetchMock);
const getAccessToken = async () => null;
const controller = new AbortController();
const cancelled = findOwnedWorkbenchProject(getAccessToken, controller.signal);
await vi.waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1));
const active = findOwnedWorkbenchProject(getAccessToken);
controller.abort();
await expect(cancelled).rejects.toMatchObject({ name: "AbortError" });
await expect(active).resolves.toMatchObject({ project: { project_id: "supply" } });
expect(fetchMock).toHaveBeenCalledTimes(2);
});
it("loads the authoritative project extent and access identity independently", async () => {
const fetchMock = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
const path = new URL(String(input)).pathname;