huskies: merge 948

This commit is contained in:
dave
2026-05-13 04:43:48 +00:00
parent 2f50e2198b
commit f2943c7e69
16 changed files with 995 additions and 205 deletions
+17 -14
View File
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { api, ChatWebSocket, resolveWsHost } from "./client";
import { installRpcMock } from "./__test_utils__/mockRpcWebSocket";
const mockFetch = vi.fn();
@@ -24,20 +25,19 @@ function errorResponse(status: number, text: string) {
describe("api client", () => {
describe("getCurrentProject", () => {
it("sends GET to /project", async () => {
mockFetch.mockResolvedValueOnce(okResponse("/home/user/project"));
it("dispatches project.current RPC and returns the path", async () => {
const rpc = installRpcMock();
rpc.respond("project.current", "/home/user/project");
const result = await api.getCurrentProject();
expect(mockFetch).toHaveBeenCalledWith(
"/api/project",
expect.objectContaining({}),
);
expect(rpc.calls).toEqual([{ method: "project.current", params: {} }]);
expect(result).toBe("/home/user/project");
});
it("returns null when no project open", async () => {
mockFetch.mockResolvedValueOnce(okResponse(null));
const rpc = installRpcMock();
rpc.respond("project.current", null);
const result = await api.getCurrentProject();
expect(result).toBeNull();
@@ -74,25 +74,28 @@ describe("api client", () => {
});
describe("getKnownProjects", () => {
it("returns array of project paths", async () => {
mockFetch.mockResolvedValueOnce(okResponse(["/a", "/b"]));
it("dispatches project.known RPC and returns the path list", async () => {
const rpc = installRpcMock();
rpc.respond("project.known", ["/a", "/b"]);
const result = await api.getKnownProjects();
expect(rpc.calls).toEqual([{ method: "project.known", params: {} }]);
expect(result).toEqual(["/a", "/b"]);
});
});
describe("error handling", () => {
it("throws on non-ok response with body text", async () => {
mockFetch.mockResolvedValueOnce(errorResponse(404, "Not found"));
it("surfaces RPC errors visibly", async () => {
const rpc = installRpcMock();
rpc.respondError("project.current", "store offline", "INTERNAL");
await expect(api.getCurrentProject()).rejects.toThrow("Not found");
await expect(api.getCurrentProject()).rejects.toThrow("store offline");
});
it("throws with status code when no body", async () => {
it("throws on non-ok HTTP response for legacy POST endpoints", async () => {
mockFetch.mockResolvedValueOnce(errorResponse(500, ""));
await expect(api.getCurrentProject()).rejects.toThrow(
await expect(api.openProject("/some/path")).rejects.toThrow(
"Request failed (500)",
);
});