Files
plainleaf/e2e/guide-task-management.test.ts

128 lines
4.2 KiB
TypeScript

import {
expect,
gotoSilverBulletPage,
test,
waitForSaveAndReadFromServer,
} from "./fixtures.ts";
// This file exercises the workflow described in docs/Guide/Task Management.md
// end-to-end. It seeds a small project + task space and verifies the
// load-bearing claims of the guide:
// - tasks on a project page render with checkboxes
// - tasks scattered across other pages that link back to a project show up
// in the project's Linked Tasks widget
// - clicking a checkbox persists the new state to disk
// - a query over `tags.project` returns project pages
// - a query over `tags.task where not t.done` returns open tasks
const WEBSITE_REDESIGN = `---
tags: project
status: active
priority: high
---
# Website Redesign
A redesign of the marketing website.
* [ ] Write the project proposal
* [ ] Create wireframes
* [ ] Set up staging environment
`;
const MEETING_NOTE = `# Meeting Notes/2026-03-04
* [ ] Send updated mockups to client [[Website Redesign]]
* [ ] Schedule review meeting [[Website Redesign]]
`;
const DASHBOARD = `# Dashboard
# Active projects
\${query[[from p = tags.project where p.status == "active"]]}
# Open tasks
\${template.each(query[[
from t = tags.task
where not t.done
order by t.lastModified desc
limit 10
]], templates.taskItem)}
`;
test.describe("Guide: Task Management", () => {
test.use({
spaceFiles: {
"index.md": "# Welcome\nThis is the index.",
"Website Redesign.md": WEBSITE_REDESIGN,
"Meeting Notes/2026-03-04.md": MEETING_NOTE,
"Dashboard.md": DASHBOARD,
},
});
test("project page renders task checkboxes", async ({ sbPage, sbServer }) => {
await gotoSilverBulletPage(sbPage, sbServer, "Website Redesign");
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("Website Redesign");
const checkboxes = sbPage.locator(
"#sb-editor .cm-content .sb-checkbox input[type='checkbox']",
);
await expect(checkboxes.first()).toBeVisible({ timeout: 10_000 });
// Three native tasks; linked tasks may add more, so just assert >= 3
const count = await checkboxes.count();
expect(count).toBeGreaterThanOrEqual(3);
});
test("project page surfaces tasks scattered across other pages as Linked Tasks", async ({
sbPage,
sbServer,
}) => {
await gotoSilverBulletPage(sbPage, sbServer, "Website Redesign");
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("Website Redesign");
await expect(editor).toContainText("Linked Tasks", { timeout: 15_000 });
// Tasks from Meeting Notes/2026-03-04 that link to [[Website Redesign]]
await expect(editor).toContainText("Send updated mockups");
await expect(editor).toContainText("Schedule review meeting");
});
test("toggling a task on the project page persists to disk", async ({
sbPage,
sbServer,
}) => {
await gotoSilverBulletPage(sbPage, sbServer, "Website Redesign");
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("Write the project proposal");
// Click the first checkbox in the editor body
const firstCheckbox = editor
.locator(".sb-checkbox input[type='checkbox']")
.first();
await expect(firstCheckbox).toBeVisible({ timeout: 10_000 });
await expect(firstCheckbox).not.toBeChecked();
await firstCheckbox.click();
await expect(firstCheckbox).toBeChecked();
const content = await waitForSaveAndReadFromServer(
sbPage,
sbServer,
"Website Redesign.md",
);
expect(content).toMatch(/\* \[x\] Write the project proposal/);
});
test("dashboard query renders active projects and open tasks", async ({
sbPage,
sbServer,
}) => {
await gotoSilverBulletPage(sbPage, sbServer, "Dashboard");
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("Dashboard");
// "Active projects" section should list Website Redesign
await expect(editor).toContainText("Website Redesign", { timeout: 20_000 });
// "Open tasks" section should include at least one of our seeded tasks
await expect(editor).toContainText("Write the project proposal");
});
});