91 lines
2.4 KiB
TypeScript
91 lines
2.4 KiB
TypeScript
import { expect, gotoSilverBulletPage, test } from "./fixtures.ts";
|
|
|
|
const SPACE_FILES = {
|
|
"Outline.md": `# Outline
|
|
* plain
|
|
- hyphen
|
|
* [ ] task
|
|
10. ten
|
|
100. hundred
|
|
* outer
|
|
* inner
|
|
* deeper
|
|
`,
|
|
};
|
|
|
|
const PROBES = [
|
|
{ text: "plain", label: "plain-asterisk" },
|
|
{ text: "hyphen", label: "plain-hyphen" },
|
|
{ text: "task", label: "task" },
|
|
{ text: "ten", label: "ordered-2-digit" },
|
|
{ text: "hundred", label: "ordered-3-digit" },
|
|
{ text: "deeper", label: "deep-nesting" },
|
|
];
|
|
|
|
test.use({ spaceFiles: SPACE_FILES });
|
|
|
|
function measureFirstGlyphX(text: string) {
|
|
const line = Array.from(document.querySelectorAll(".cm-line")).find((l) =>
|
|
l.textContent?.includes(text),
|
|
);
|
|
if (!line) return null;
|
|
const lineRect = line.getBoundingClientRect();
|
|
const walker = document.createTreeWalker(line, NodeFilter.SHOW_TEXT);
|
|
let node: Node | null;
|
|
while ((node = walker.nextNode())) {
|
|
const t = node.textContent ?? "";
|
|
if (!t.length) continue;
|
|
const r = document.createRange();
|
|
r.selectNodeContents(node);
|
|
const rect = r.getBoundingClientRect();
|
|
if (rect.width === 0 && rect.height === 0) continue;
|
|
return rect.left - lineRect.left;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
test("list lines: zero horizontal shift on cursor in/out", async ({
|
|
sbPage,
|
|
sbServer,
|
|
}) => {
|
|
await gotoSilverBulletPage(sbPage, sbServer, "Outline");
|
|
await sbPage.locator(".cm-line.sb-line-li").first().waitFor({
|
|
state: "visible",
|
|
timeout: 10_000,
|
|
});
|
|
|
|
const h1 = sbPage.locator(".cm-line.sb-line-h1").first();
|
|
|
|
for (const probe of PROBES) {
|
|
const lineLocator = sbPage
|
|
.locator(".cm-line", { hasText: probe.text })
|
|
.first();
|
|
await lineLocator.scrollIntoViewIfNeeded();
|
|
|
|
// Cursor OUT: park on H1 (live-preview rendering for our line)
|
|
await h1.click();
|
|
await sbPage.waitForTimeout(75);
|
|
|
|
const xOut = await sbPage.evaluate(measureFirstGlyphX, probe.text);
|
|
expect(
|
|
xOut,
|
|
`${probe.label}: should have a measurable first glyph (out)`,
|
|
).not.toBeNull();
|
|
|
|
// Cursor IN: click into this list line (raw-source rendering)
|
|
await lineLocator.click();
|
|
await sbPage.waitForTimeout(75);
|
|
|
|
const xIn = await sbPage.evaluate(measureFirstGlyphX, probe.text);
|
|
expect(
|
|
xIn,
|
|
`${probe.label}: should have a measurable first glyph (in)`,
|
|
).not.toBeNull();
|
|
|
|
expect(
|
|
Math.abs((xOut as number) - (xIn as number)),
|
|
`${probe.label}: |xOut - xIn| ≤ 1px`,
|
|
).toBeLessThanOrEqual(1);
|
|
}
|
|
});
|