Files
plainleaf/e2e/guide-journaling.test.ts
T

130 lines
4.6 KiB
TypeScript

import type { Page } from "@playwright/test";
import { expect, mod, test, waitForSaveAndReadFromServer } from "./fixtures.ts";
// This file exercises the workflow described in website/Guide/Journaling.md
// end-to-end. Each test seeds a space with the exact template shown in the
// guide, then drives the UI the way a user following the guide would.
//
// Notes for maintainers: if the guide is updated, update the constants below
// to match, so these tests remain a faithful executable version of the guide.
const JOURNAL_TEMPLATE = `---
command: "Journal: Today"
key: "Ctrl-q t"
suggestedName: "Journal/\${os.date('%Y-%m-%d')}"
confirmName: false
tags: meta/template/page
openIfExists: true
---
#journal
* |^|
`;
/** Today's date as YYYY-MM-DD, matching the template's suggestedName. */
function today(): string {
const d = new Date();
const yyyy = d.getFullYear();
const mm = String(d.getMonth() + 1).padStart(2, "0");
const dd = String(d.getDate()).padStart(2, "0");
return `${yyyy}-${mm}-${dd}`;
}
/**
* Wait for the welcome page to be loaded (proxy for "the editor is ready and
* the built-in libraries have registered their commands"), then run the
* "Journal: Today" command via the command palette.
*/
async function runJournalToday(sbPage: Page): Promise<void> {
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("Welcome");
await sbPage.keyboard.press(`${mod}+/`);
const modal = sbPage.locator(".sb-modal-box");
await expect(modal).toBeVisible();
const paletteInput = modal.locator(".cm-content");
await paletteInput.click();
await sbPage.keyboard.type("Journal: Today", { delay: 30 });
// The command defined by the Journal template should appear
await expect(
modal.locator(".sb-option .sb-name", { hasText: "Journal: Today" }),
).toBeVisible();
await sbPage.keyboard.press("Enter");
await expect(modal).not.toBeVisible();
const expectedPage = `Journal/${today()}`;
await expect(sbPage.locator("#sb-current-page")).toContainText(expectedPage);
}
test.describe("Guide: Journaling", () => {
test.use({
spaceFiles: {
"index.md": "# Welcome\nA fresh space, ready to journal.",
"Library/Page Templates/Journal.md": JOURNAL_TEMPLATE,
},
});
test("running 'Journal: Today' from the command palette creates today's journal page", async ({ sbPage }) => {
await runJournalToday(sbPage);
// The editor should show the template body, including the #journal tag
const editor = sbPage.locator("#sb-editor .cm-content");
await expect(editor).toContainText("#journal");
});
test("created journal page is tagged #journal on disk", async ({ sbPage, sbServer }) => {
await runJournalToday(sbPage);
// The file on disk must contain the #journal tag from the template body.
// This is the bug reported in the community:
// https://community.silverbullet.md/t/setting-up-new-space-with-journaling/4015
// The user reported that #journal does not get copied from the template
// to the newly created page, so the query over `tags.journal` returns
// nothing.
const expectedPage = `Journal/${today()}`;
const content = await waitForSaveAndReadFromServer(
sbPage,
sbServer,
`${expectedPage}.md`,
);
expect(content).toContain("#journal");
});
test("new journal entry mentioning a topic shows up under that topic's Linked Mentions", async ({ sbPage, sbServer }) => {
await runJournalToday(sbPage);
// Type a journal entry that links to [[Alice]] — this is the
// "watch topic pages come alive" flow from the guide.
const editor = sbPage.locator("#sb-editor .cm-content");
await editor.click();
// The template places the cursor at the first bullet's content.
await sbPage.keyboard.type("Reviewed the Q2 roadmap with [[Alice]]", { delay: 20 });
// Wait for the journal page to save
const expectedPage = `Journal/${today()}`;
const journalContent = await waitForSaveAndReadFromServer(
sbPage,
sbServer,
`${expectedPage}.md`,
);
expect(journalContent).toContain("[[Alice]]");
// Navigate to Alice's page via the wiki link
const wikiLinkText = editor.locator(".sb-wiki-link", { hasText: "Alice" });
await expect(wikiLinkText).toBeVisible({ timeout: 10_000 });
await wikiLinkText.click();
await expect(sbPage.locator("#sb-current-page")).toContainText("Alice");
// Alice's page should show a Linked Mentions section with the journal
// entry we just wrote. The widget is rendered by a built-in script.
const aliceEditor = sbPage.locator("#sb-editor .cm-content");
await expect(aliceEditor).toContainText("Linked Mentions", { timeout: 15_000 });
await expect(aliceEditor).toContainText("Reviewed the Q2 roadmap");
});
});