Add Dataview and Bases generators (Toolbox Phase 2)
Two more inside-LMS generators under /tools, completing the 6-tool set: - Dataview: DQL builder (TABLE/LIST/TASK/CALENDAR, FROM/WHERE/SORT/LIMIT), output wrapped in a dataview code block - Bases: .base YAML builder (views, filters and:, order, sort, groupBy, limit); filter expressions emitted as single-quoted YAML scalars for safety Syntax verified against official Obsidian docs (research workflow). Audit fix: Bases sort entries use 'column:' (not 'property:') per documented working .base files; 'property:' is kept only for groupBy. 14 new tests (47 total). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { buildBases } from "@/lib/tools/bases";
|
||||
|
||||
const base = {
|
||||
viewType: "table" as const,
|
||||
viewName: "Проекты",
|
||||
properties: ["file.name", "status"],
|
||||
filterScope: "none" as const,
|
||||
filterValue: "",
|
||||
};
|
||||
|
||||
describe("buildBases", () => {
|
||||
it("базовая таблица: type/name/order", () => {
|
||||
const y = buildBases(base);
|
||||
expect(y).toContain("views:");
|
||||
expect(y).toContain(" - type: table");
|
||||
expect(y).toContain(" name: Проекты");
|
||||
expect(y).toContain(" order:");
|
||||
expect(y).toContain(" - file.name");
|
||||
expect(y).toContain(" - status");
|
||||
expect(y).not.toContain("filters:");
|
||||
});
|
||||
|
||||
it("фильтр по папке", () => {
|
||||
const y = buildBases({ ...base, filterScope: "folder", filterValue: "Projects" });
|
||||
expect(y).toContain("filters:");
|
||||
expect(y).toContain(" and:");
|
||||
expect(y).toContain(` - 'file.inFolder("Projects")'`);
|
||||
});
|
||||
|
||||
it("фильтр по тегу снимает ведущий #", () => {
|
||||
const y = buildBases({ ...base, filterScope: "tag", filterValue: "#проект" });
|
||||
expect(y).toContain(`- 'file.hasTag("проект")'`);
|
||||
});
|
||||
|
||||
it("property-фильтр — готовое выражение как есть", () => {
|
||||
const y = buildBases({ ...base, filterScope: "property", filterValue: 'status == "done"' });
|
||||
expect(y).toContain(`- 'status == "done"'`);
|
||||
});
|
||||
|
||||
it("сортировка → sort: column/direction (не property)", () => {
|
||||
const y = buildBases({ ...base, sortBy: "status", sortDir: "DESC" });
|
||||
expect(y).toContain(" sort:");
|
||||
expect(y).toContain(" - column: status");
|
||||
expect(y).toContain(" direction: DESC");
|
||||
});
|
||||
|
||||
it("группировка и лимит", () => {
|
||||
const y = buildBases({ ...base, groupBy: "status", limit: 50 });
|
||||
expect(y).toContain(" groupBy:");
|
||||
expect(y).toContain(" property: status");
|
||||
expect(y).toContain(" limit: 50");
|
||||
});
|
||||
|
||||
it("имя вида квотится при двоеточии+пробеле", () => {
|
||||
expect(buildBases({ ...base, viewName: "Книги: всё" })).toContain('name: "Книги: всё"');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user