diff --git a/e2e-tests/code-editing-and-ast-interaction.test.ts b/e2e-tests/code-editing-and-ast-interaction.test.ts index 3d683bd..bb1e02f 100644 --- a/e2e-tests/code-editing-and-ast-interaction.test.ts +++ b/e2e-tests/code-editing-and-ast-interaction.test.ts @@ -127,3 +127,404 @@ test(`should keep ESQuery highlights aligned while typing before a matching lite ).toBe(true); await expect(highlight).toHaveText(["42"]); }); + +test.describe("AST node expansion", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/"); + await page.getByRole("button", { name: "Language Options" }).click(); + }); + + test.describe("Language: JavaScript", () => {}); + + test.describe("Language: JSON", () => {}); + + test.describe("Language: Markdown", () => { + test.beforeEach(async ({ page }) => { + // `Language`: select `Markdown` + await page + .getByRole("combobox", { exact: true, name: "Language" }) + .click(); + await page + .getByRole("option", { exact: true, name: "Markdown" }) + .click(); + }); + + test("Mode: CommonMark", async ({ page }) => { + // `Mode`: `CommonMark` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "CommonMark" }) + .click(); + await expect(modeSelect).toHaveText("CommonMark"); + + // `Front Matter`: `Off` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "Off" }) + .click(); + await expect(frontMatterSelect).toHaveText("Off"); + + // `Math`: `false` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await expect(mathSwitch).toHaveAttribute("aria-checked", "false"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a CommonMark sample into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill("text, *emphasis*, **strong**"); + + // Verify that the AST structure matches expectations for CommonMark. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[1 element]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await page.getByRole("button", { name: "0. paragraph" }).click(); + + await page + .getByRole("region", { name: "0. paragraph" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[4 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. text" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. emphasis" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "2. text" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "3. strong" }), + ).toBeVisible(); + }); + + test("Mode: GFM", async ({ page }) => { + // `Mode`: `GFM` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "GitHub-Flavored" }) + .click(); + await expect(modeSelect).toHaveText("GitHub-Flavored"); + + // `Front Matter`: `Off` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "Off" }) + .click(); + await expect(frontMatterSelect).toHaveText("Off"); + + // `Math`: `false` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await expect(mathSwitch).toHaveAttribute("aria-checked", "false"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a GFM sample into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill("text, ~~delete~~, *emphasis*"); + + // Verify that the AST structure matches expectations for GFM. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[1 element]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await page.getByRole("button", { name: "0. paragraph" }).click(); + + await page + .getByRole("region", { name: "0. paragraph" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[4 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. text" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. delete" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "2. text" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "3. emphasis" }), + ).toBeVisible(); + }); + + test("Frontmatter: YAML", async ({ page }) => { + // `Mode`: `CommonMark` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "CommonMark" }) + .click(); + await expect(modeSelect).toHaveText("CommonMark"); + + // `Front Matter`: `YAML` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "YAML" }) + .click(); + await expect(frontMatterSelect).toHaveText("YAML"); + + // `Math`: `false` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await expect(mathSwitch).toHaveAttribute("aria-checked", "false"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a Markdown sample with YAML frontmatter into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill("---\ntitle: Test\n---\n\ntext"); + + // Verify that the AST structure matches expectations for YAML frontmatter. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[2 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. yaml" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. paragraph" }), + ).toBeVisible(); + }); + + test("Frontmatter: TOML", async ({ page }) => { + // `Mode`: `CommonMark` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "CommonMark" }) + .click(); + await expect(modeSelect).toHaveText("CommonMark"); + + // `Front Matter`: `TOML` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "TOML" }) + .click(); + await expect(frontMatterSelect).toHaveText("TOML"); + + // `Math`: `false` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await expect(mathSwitch).toHaveAttribute("aria-checked", "false"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a Markdown sample with TOML frontmatter into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill("+++\ncount = 1\n+++\n\ntext"); + + // Verify that the AST structure matches expectations for TOML frontmatter. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[2 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. toml" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. paragraph" }), + ).toBeVisible(); + }); + + test("Frontmatter: JSON", async ({ page }) => { + // `Mode`: `CommonMark` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "CommonMark" }) + .click(); + await expect(modeSelect).toHaveText("CommonMark"); + + // `Front Matter`: `JSON` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "JSON" }) + .click(); + await expect(frontMatterSelect).toHaveText("JSON"); + + // `Math`: `false` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await expect(mathSwitch).toHaveAttribute("aria-checked", "false"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a Markdown sample with JSON frontmatter into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill('---\n{"count":1}\n---\n\ntext'); + + // Verify that the AST structure matches expectations for JSON frontmatter. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[2 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. json" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. paragraph" }), + ).toBeVisible(); + }); + + test("Math: true", async ({ page }) => { + // `Mode`: `CommonMark` + const modeSelect = page.getByRole("combobox", { + exact: true, + name: "Mode", + }); + await modeSelect.click(); + await page + .getByRole("option", { exact: true, name: "CommonMark" }) + .click(); + await expect(modeSelect).toHaveText("CommonMark"); + + // `Front Matter`: `Off` + const frontMatterSelect = page.getByRole("combobox", { + exact: true, + name: "Front Matter", + }); + await frontMatterSelect.click(); + await page + .getByRole("option", { exact: true, name: "Off" }) + .click(); + await expect(frontMatterSelect).toHaveText("Off"); + + // `Math`: `true` + const mathSwitch = page.getByRole("switch", { + exact: true, + name: "Math", + }); + await mathSwitch.click(); + await expect(mathSwitch).toHaveAttribute("aria-checked", "true"); + + // Hide the settings menu to ensure it doesn't interfere with the test. + await page.keyboard.press("Escape"); + + // Fill a Markdown sample with inline and block math into the editor. + await page + .getByRole("textbox", { exact: true, name: "Code Editor" }) + .fill("inline $x + y$ math\n\n$$\nx + y\n$$"); + + // Verify that the AST structure matches expectations for math. + await page + .getByRole("region", { name: "root" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[2 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. paragraph" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. math" }), + ).toBeVisible(); + + await page.getByRole("button", { name: "0. paragraph" }).click(); + + await page + .getByRole("region", { name: "0. paragraph" }) + .getByRole("listitem") + .filter({ hasText: "childrenArray[3 elements]" }) + .getByRole("button", { name: "Toggle Property" }) + .click(); + + await expect( + page.getByRole("button", { name: "0. text" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "1. inlineMath" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "2. text" }), + ).toBeVisible(); + }); + }); + + test.describe("Language: CSS", () => {}); + + test.describe("Language: HTML", () => {}); +});