6317dade9e
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>
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
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: "Книги: всё"');
|
|
});
|
|
});
|