131 lines
3.4 KiB
TypeScript
131 lines
3.4 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|||
|
|
import { buildDocumentTree, type DocumentRecord } from "./documents";
|
||
|
|
|
||
|
|
type TreeLike = { id: string; children: TreeLike[] };
|
||
|
|
|
||
|
|
function collectIds(nodes: TreeLike[]): string[] {
|
||
|
|
const ids: string[] = [];
|
||
|
|
const walk = (list: TreeLike[]) => {
|
||
|
|
list.forEach((node) => {
|
||
|
|
ids.push(node.id);
|
||
|
|
if (node.children.length > 0) {
|
||
|
|
walk(node.children);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
};
|
||
|
|
walk(nodes);
|
||
|
|
return ids;
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("buildDocumentTree", () => {
|
||
|
|
let warnSpy: ReturnType<typeof vi.spyOn> | null = null;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
warnSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
warnSpy?.mockRestore();
|
||
|
|
warnSpy = null;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("应当去重重复的记录 id(根节点)", () => {
|
||
|
|
const base: DocumentRecord = {
|
||
|
|
access_scope: "private",
|
||
|
|
id: "doc-1",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "A",
|
||
|
|
parent_id: null,
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:00.000Z",
|
||
|
|
updated_at: null,
|
||
|
|
};
|
||
|
|
|
||
|
|
const tree = buildDocumentTree([base, { ...base, title: "B" }]);
|
||
|
|
expect(tree).toHaveLength(1);
|
||
|
|
expect(tree[0].id).toBe("doc-1");
|
||
|
|
expect(tree[0].title).toBe("B");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("应当去重重复的记录 id(子节点)", () => {
|
||
|
|
const parent: DocumentRecord = {
|
||
|
|
access_scope: "private",
|
||
|
|
id: "doc-p",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "P",
|
||
|
|
parent_id: null,
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:00.000Z",
|
||
|
|
updated_at: null,
|
||
|
|
};
|
||
|
|
const child: DocumentRecord = {
|
||
|
|
access_scope: "private",
|
||
|
|
id: "doc-c",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "C",
|
||
|
|
parent_id: "doc-p",
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:01.000Z",
|
||
|
|
updated_at: null,
|
||
|
|
};
|
||
|
|
|
||
|
|
const tree = buildDocumentTree([parent, child, { ...child, title: "C2" }]);
|
||
|
|
expect(tree).toHaveLength(1);
|
||
|
|
expect(tree[0].children).toHaveLength(1);
|
||
|
|
expect(tree[0].children[0].id).toBe("doc-c");
|
||
|
|
expect(tree[0].children[0].title).toBe("C2");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("生成的树中不应出现重复 id", () => {
|
||
|
|
const records: DocumentRecord[] = [
|
||
|
|
{
|
||
|
|
access_scope: "private",
|
||
|
|
id: "a",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "A",
|
||
|
|
parent_id: null,
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:00.000Z",
|
||
|
|
updated_at: null,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
access_scope: "private",
|
||
|
|
id: "b",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "B",
|
||
|
|
parent_id: "a",
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:01.000Z",
|
||
|
|
updated_at: null,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
access_scope: "private",
|
||
|
|
id: "b",
|
||
|
|
workspace_id: "ws-1",
|
||
|
|
title: "B2",
|
||
|
|
parent_id: "a",
|
||
|
|
sort_order: null,
|
||
|
|
is_starred: null,
|
||
|
|
is_template: false,
|
||
|
|
created_at: "2025-01-01T00:00:01.000Z",
|
||
|
|
updated_at: "2025-01-01T00:00:02.000Z",
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const tree = buildDocumentTree(records);
|
||
|
|
const ids = collectIds(tree);
|
||
|
|
const unique = new Set(ids);
|
||
|
|
expect(unique.size).toBe(ids.length);
|
||
|
|
});
|
||
|
|
});
|