130 lines
4.6 KiB
TypeScript
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");
|
|
});
|
|
});
|
|
|