Files
plainleaf/client/components/plainleaf_workspace.test.ts
T
wushenghuaandCodex bab4b36fae
CI / config (push) Canceled after 0s
CI / test-frontend (push) Canceled after 0s
CI / test-rust (push) Canceled after 0s
CI / test-e2e (push) Canceled after 0s
CI / test-e2e-release (push) Canceled after 0s
CI / build (push) Canceled after 0s
CI / release (push) Canceled after 0s
CI / docker (push) Canceled after 0s
CI / docker-website (push) Canceled after 0s
feat: build Markdown-native task center
Co-Authored-By: Codex <noreply@anthropic.com>
2026-08-12 19:26:10 +08:00

164 lines
4.3 KiB
TypeScript

import type { PageMeta } from "@silverbulletmd/silverbullet/type/index";
import { expect, test } from "vitest";
import {
buildPageTree,
collectPlainleafTags,
plainleafPageLabel,
plainleafTaskReference,
plainleafTaskTitle,
visiblePlainleafPages,
} from "./plainleaf_workspace.tsx";
function page(name: string, extra: Partial<PageMeta> = {}): PageMeta {
return {
ref: name,
tag: "page",
name,
created: "2026-08-12T00:00:00Z",
lastModified: "2026-08-12T00:00:00Z",
perm: "rw",
...extra,
};
}
test("builds nested folders from slash-separated page names", () => {
const tree = buildPageTree([
page("Inbox"),
page("Projects/Plainleaf/Plan"),
page("Projects/Plainleaf/Research"),
page("Projects/Website"),
]);
expect(tree.map((node) => [node.kind, node.name])).toEqual([
["folder", "Projects"],
["page", "Inbox"],
]);
expect(tree[0]).toMatchObject({
kind: "folder",
name: "Projects",
children: [
{
kind: "folder",
name: "Plainleaf",
children: [
{ kind: "page", name: "Projects/Plainleaf/Plan", label: "Plan" },
{
kind: "page",
name: "Projects/Plainleaf/Research",
label: "Research",
},
],
},
{ kind: "page", name: "Projects/Website", label: "Website" },
],
});
});
test("keeps a page and a same-named folder as separate nodes", () => {
const tree = buildPageTree([page("Projects"), page("Projects/Plan")]);
expect(tree).toMatchObject([
{
kind: "folder",
name: "Projects",
children: [{ kind: "page", name: "Projects/Plan" }],
},
{ kind: "page", name: "Projects" },
]);
});
test("omits aspiring and decorated hidden pages", () => {
const tree = buildPageTree([
page("Visible"),
page("Aspiring", { _isAspiring: true }),
page("Hidden", { pageDecoration: { hide: true } }),
]);
expect(tree).toMatchObject([{ kind: "page", name: "Visible" }]);
});
test("hides SilverBullet system roots and meta-tagged pages", () => {
const pages = [
page("Notes/Visible"),
page("Library/Std"),
page("Repositories/Std"),
page("CONFIG"),
page("Internal", { tags: ["meta/library"] }),
];
expect(visiblePlainleafPages(pages).map((item) => item.name)).toEqual([
"Notes/Visible",
]);
expect(visiblePlainleafPages(pages, true).map((item) => item.name)).toEqual([
"Notes/Visible",
"Library/Std",
"Repositories/Std",
"CONFIG",
"Internal",
]);
});
test("uses a friendly home label without changing the stored page name", () => {
expect(plainleafPageLabel("index", "index")).toBe("首页");
expect(plainleafPageLabel("项目/计划", "index")).toBe("计划");
expect(plainleafPageLabel("Library/Std", "index")).toBe("内置");
expect(plainleafPageLabel("CONFIG", "index")).toBe("系统配置");
const tree = buildPageTree([page("index")], "index");
expect(tree).toMatchObject([{ kind: "page", name: "index", label: "首页" }]);
});
test("counts user tags and excludes internal tags", () => {
const tags = collectPlainleafTags([
page("A", { tags: ["产品"] }),
page("B", { tags: ["产品", "灵感"] }),
page("C", { tags: ["template"] }),
page("D", { tags: ["产品", "meta/library"] }),
]);
expect(tags).toEqual([
{ name: "产品", count: 2 },
{ name: "灵感", count: 1 },
]);
expect(
collectPlainleafTags(
[page("Library/Test", { tags: ["meta/library"] })],
true,
),
).toEqual([{ name: "meta/library", count: 1 }]);
});
test("qualifies anchor-backed task refs with their source page", () => {
expect(
plainleafTaskReference({
ref: "follow-up",
page: "项目/计划",
name: "跟进",
state: " ",
done: false,
}),
).toBe("项目/计划$follow-up");
expect(
plainleafTaskReference({
ref: "项目/计划@42",
page: "项目/计划",
name: "跟进",
state: " ",
done: false,
}),
).toBe("项目/计划@42");
});
test("separates explicit project links from the editable task title", () => {
expect(
plainleafTaskTitle({
ref: "项目/计划@42",
page: "项目/计划",
name: "跟进设计稿 [[项目/Plainleaf]]",
state: " ",
done: false,
links: ["项目/Plainleaf"],
}),
).toBe("跟进设计稿");
});