Archived
80 lines
3.2 KiB
TypeScript
80 lines
3.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { Workspace } from "@jmfederico/pi-web/plugin-api";
|
|
import { ACTIONS_CONFIG_PATH } from "./config";
|
|
import { loadWorkspaceActionsConfig, parseWorkspaceFileResponse, workspaceFileUrl, type FetchLike } from "./workspaceActionsClient";
|
|
|
|
const workspace: Workspace = {
|
|
id: "workspace 1",
|
|
projectId: "project/1",
|
|
path: "/repo",
|
|
label: "repo",
|
|
isMain: false,
|
|
isGitRepo: true,
|
|
isGitWorktree: true,
|
|
};
|
|
|
|
describe("workspace actions client", () => {
|
|
it("builds the private workspace file URL", () => {
|
|
expect(workspaceFileUrl(workspace, ACTIONS_CONFIG_PATH)).toBe("/api/projects/project%2F1/workspaces/workspace%201/file?path=.pi-web%2Factions.json");
|
|
});
|
|
|
|
it("loads and parses a valid actions config", async () => {
|
|
const fetcher: FetchLike = () => Promise.resolve(jsonResponse({
|
|
content: JSON.stringify({ version: 1, actions: [{ id: "build", title: "Build", command: "npm run build" }] }),
|
|
truncated: false,
|
|
binary: false,
|
|
}));
|
|
|
|
await expect(loadWorkspaceActionsConfig(workspace, { fetch: fetcher })).resolves.toEqual({
|
|
kind: "loaded",
|
|
config: {
|
|
version: 1,
|
|
actions: [{ id: "build", title: "Build", command: "npm run build", confirm: false }],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("treats a missing optional actions config as unconfigured", async () => {
|
|
const fetcher: FetchLike = () => Promise.resolve(new Response(JSON.stringify({ error: "Path does not exist" }), { status: 400 }));
|
|
|
|
await expect(loadWorkspaceActionsConfig(workspace, { fetch: fetcher })).resolves.toEqual({
|
|
kind: "missing",
|
|
message: "No workspace actions configured here.",
|
|
hint: `${ACTIONS_CONFIG_PATH} is optional. Create it in this workspace if you want custom actions.`,
|
|
});
|
|
});
|
|
|
|
it("returns a visible unavailable state instead of throwing on request failures", async () => {
|
|
const fetcher: FetchLike = () => Promise.resolve(new Response(JSON.stringify({ error: "nope" }), { status: 400 }));
|
|
|
|
await expect(loadWorkspaceActionsConfig(workspace, { fetch: fetcher })).resolves.toMatchObject({
|
|
kind: "unavailable",
|
|
message: "Could not load workspace actions.",
|
|
hint: `Fix ${ACTIONS_CONFIG_PATH}, then click Refresh.`,
|
|
detail: `Unable to read ${ACTIONS_CONFIG_PATH}: HTTP 400: nope`,
|
|
});
|
|
});
|
|
|
|
it("returns parser details for invalid config files", async () => {
|
|
const fetcher: FetchLike = () => Promise.resolve(jsonResponse({
|
|
content: JSON.stringify({ version: 2, actions: [] }),
|
|
truncated: false,
|
|
binary: false,
|
|
}));
|
|
|
|
await expect(loadWorkspaceActionsConfig(workspace, { fetch: fetcher })).resolves.toMatchObject({
|
|
kind: "unavailable",
|
|
detail: "Config version must be 1",
|
|
});
|
|
});
|
|
|
|
it("validates workspace file responses", () => {
|
|
expect(parseWorkspaceFileResponse({ content: "{}", truncated: false, binary: false })).toEqual({ content: "{}", truncated: false, binary: false });
|
|
expect(parseWorkspaceFileResponse({ content: "{}", truncated: "no", binary: false })).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
function jsonResponse(value: unknown): Response {
|
|
return new Response(JSON.stringify(value), { status: 200, headers: { "content-type": "application/json" } });
|
|
}
|