128 lines
4.4 KiB
TypeScript
128 lines
4.4 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
import { expect, mod, test, waitForSaveAndReadFromServer } from "./fixtures.ts";
|
|
|
|
// This file exercises the workflow described in docs/Journal.md end-to-end.
|
|
// The Journal feature is built in: the `Journal: Today` command and the
|
|
// default template at `Library/Std/Journal/Template` ship with SilverBullet.
|
|
|
|
/** Today's date as YYYY-MM-DD, matching the default journal page name. */
|
|
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("input.sb-input");
|
|
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 input.sb-input")).toHaveValue(
|
|
expectedPage,
|
|
);
|
|
}
|
|
|
|
test.describe("Guide: Journaling", () => {
|
|
test.use({
|
|
spaceFiles: {
|
|
"index.md": "# Welcome\nA fresh space, ready to journal.",
|
|
},
|
|
});
|
|
|
|
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 — frontmatter sets
|
|
// `tags: journal` (from the built-in template at
|
|
// Library/Std/Journal/Template).
|
|
const editor = sbPage.locator("#sb-editor .cm-content");
|
|
await expect(editor).toContainText("tags: 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
|
|
// frontmatter, so queries over `index.tag("journal")` (used by the
|
|
// built-in `Journal: Previous Day` / `Next Day` commands and the
|
|
// default index-page section) return this entry.
|
|
const expectedPage = `Journal/${today()}`;
|
|
const content = await waitForSaveAndReadFromServer(
|
|
sbPage,
|
|
sbServer,
|
|
`${expectedPage}.md`,
|
|
);
|
|
expect(content).toContain("tags: 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 input.sb-input")).toHaveValue(
|
|
"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");
|
|
});
|
|
});
|