feat: rename graph titles with select-then-edit interaction
This commit is contained in:
+19
-1
@@ -27,7 +27,16 @@ const upstream = createServer(async (req, res) => {
|
||||
res.end(JSON.stringify({ id: graph.id, workspace_id: graph.workspace_id, kind: graph.kind, version: graph.version }));
|
||||
} else if (req.url === "/projects/endoleap/workspaces/space/materials/foundry-generated-id") {
|
||||
assert.equal(req.headers.authorization, "Bearer test-only-session");
|
||||
res.end(JSON.stringify(graphs.get("foundry-generated-id")));
|
||||
if (req.method === "PATCH") {
|
||||
assert.equal(req.headers["if-match"], '"1"');
|
||||
let raw = "";
|
||||
for await (const chunk of req) raw += chunk;
|
||||
const input = JSON.parse(raw);
|
||||
const current = graphs.get("foundry-generated-id");
|
||||
graphs.set(current.id, { ...current, ...input, version: current.version + 1 });
|
||||
res.statusCode = 204;
|
||||
res.end();
|
||||
} else res.end(JSON.stringify(graphs.get("foundry-generated-id")));
|
||||
} else if (req.url.includes("/workspaces/space/materials")) {
|
||||
res.end(JSON.stringify({ url: req.url, method: req.method }));
|
||||
} else if (req.url.endsWith("/auth/login")) {
|
||||
@@ -157,6 +166,15 @@ try {
|
||||
assert.equal(stored.title, "未命名图谱");
|
||||
assert.equal(stored.workspace_id, "space");
|
||||
assert.equal(stored.content.schema_version, 1);
|
||||
const rename = await fetch(host + `/api/foundry/workspaces/${graph.workspace_id}/materials/${graph.id}`, {
|
||||
method: "PATCH", headers: { "Content-Type": "application/json", Cookie: session, Origin: host, "If-Match": '"1"' },
|
||||
body: JSON.stringify({ title: "改名后的图谱", description: "", content: stored.content }),
|
||||
});
|
||||
assert.equal(rename.status, 204);
|
||||
const renamed = await (await fetch(host + `/api/foundry/workspaces/${graph.workspace_id}/materials/${graph.id}`, { headers: { Cookie: session } })).json();
|
||||
assert.equal(renamed.title, "改名后的图谱");
|
||||
assert.equal(renamed.version, 2);
|
||||
assert.deepEqual(renamed.content, stored.content);
|
||||
|
||||
for (const origin of ["https://example.com", "null"])
|
||||
assert.equal(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { boardHref, createBoard, DEFAULT_BOARD_TITLE, loadWorkspaceHome } from "../src/lib/workspace.ts";
|
||||
import { boardHref, createBoard, renameBoard, DEFAULT_BOARD_TITLE, loadWorkspaceHome } from "../src/lib/workspace.ts";
|
||||
|
||||
test("profile and workspace reads both start before either completes", async () => {
|
||||
const calls = [];
|
||||
@@ -101,3 +101,36 @@ test("graph URLs preserve workspace identity and safely encode route segments",
|
||||
assert.equal(boardHref("space/a", "id?b"), "/dashboard/space%2Fa/id%3Fb");
|
||||
assert.equal(boardHref("demo", "board", true), "/dashboard/demo/board?demo=1");
|
||||
});
|
||||
|
||||
|
||||
test("renaming reads the latest version and preserves description and content", async () => {
|
||||
const calls = [];
|
||||
const content = { schema_version: 1, preserved: { key: "value" } };
|
||||
const renamed = await renameBoard(async (path, options) => {
|
||||
calls.push(path);
|
||||
if (!options) return { id: "board", workspace_id: "space", kind: "board", title: "Old", version: 7, description: "Keep this", content };
|
||||
assert.equal(options.method, "PATCH");
|
||||
assert.equal(options.headers["If-Match"], '"7"');
|
||||
assert.deepEqual(JSON.parse(options.body), { title: "新名称", description: "Keep this", content });
|
||||
return null;
|
||||
}, "space", "board", " 新名称 ");
|
||||
assert.deepEqual(calls, ["workspaces/space/materials/board", "workspaces/space/materials/board"]);
|
||||
assert.equal(renamed.title, "新名称");
|
||||
assert.equal(renamed.version, 8);
|
||||
});
|
||||
|
||||
test("rename rejects empty or oversized names without any API calls", async () => {
|
||||
for (const name of [" ", "字".repeat(101)]) {
|
||||
await assert.rejects(renameBoard(() => assert.fail("unexpected API call"), "space", "board", name), /invalid_title/);
|
||||
}
|
||||
});
|
||||
|
||||
test("rename surfaces a version conflict without retrying or overwriting", async () => {
|
||||
let patches = 0;
|
||||
await assert.rejects(renameBoard(async (_path, options) => {
|
||||
if (!options) return { id: "board", workspace_id: "space", kind: "board", title: "Old", version: 1 };
|
||||
patches++;
|
||||
throw new Error("version_conflict");
|
||||
}, "space", "board", "New"), /version_conflict/);
|
||||
assert.equal(patches, 1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user