fix(tree): address realtime-tree-server review findings
- make addTreeNode receivers idempotent (invalidateOnCreatePage guard + buildTree dedup) so the author's self-echo no longer duplicates the node - broadcast realtime tree updates for bulk copy/duplicate and import via a root refetch: PAGE_CREATED now carries spaceId and the WS listener falls back to refetchRootTreeNodeEvent when no per-node snapshot is present - remove the now-dead client-relay inbound path (isTreeEvent/handleTreeEvent) that remained a stale-restriction-cache attack surface - honest string|null cast for a root move's parent id - add tests: buildTree dedup; onPageCreated per-node vs refetch branching Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
40
apps/client/src/features/page/tree/utils/utils.test.ts
Normal file
40
apps/client/src/features/page/tree/utils/utils.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { buildTree } from "./utils";
|
||||
import type { IPage } from "@/features/page/types/page.types.ts";
|
||||
|
||||
function page(id: string, position: string): IPage {
|
||||
return {
|
||||
id,
|
||||
slugId: `slug-${id}`,
|
||||
title: id.toUpperCase(),
|
||||
icon: "",
|
||||
position,
|
||||
hasChildren: false,
|
||||
spaceId: "space-1",
|
||||
parentPageId: null as unknown as string,
|
||||
} as IPage;
|
||||
}
|
||||
|
||||
describe("buildTree", () => {
|
||||
it("builds one node per unique page", () => {
|
||||
const tree = buildTree([page("a", "a1"), page("b", "a2")]);
|
||||
expect(tree.map((n) => n.id)).toEqual(["a", "b"]);
|
||||
});
|
||||
|
||||
it("dedups a duplicate id so the tree has no duplicate node", () => {
|
||||
// A realtime cache write could append a page twice; buildTree must not emit
|
||||
// two references to the same node (which would crash the sidebar render with
|
||||
// a duplicate React key).
|
||||
const tree = buildTree([
|
||||
page("a", "a1"),
|
||||
page("b", "a2"),
|
||||
page("a", "a1"), // duplicate id
|
||||
]);
|
||||
|
||||
expect(tree).toHaveLength(2);
|
||||
expect(tree.map((n) => n.id).sort()).toEqual(["a", "b"]);
|
||||
// No id appears more than once.
|
||||
const ids = tree.map((n) => n.id);
|
||||
expect(new Set(ids).size).toBe(ids.length);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user