docs/slate-browser/next-api-candidates.md
Specialist testing/proof doc. For current queue and roadmap truth, see master-roadmap.md.
Proposed API research only. This file does not define the current shipped
slate-browsersurface.
This doc answers one narrower question than the system docs:
slate-browser should add if the goal is
the absolute best Slate-flavoured testing framework?This is not a “more helpers is better” doc.
It is a ranking.
The next best APIs are the ones that:
That means the next tranche should bias toward:
Not toward:
Current public Playwright API in /Users/zbeyens/git/slate-v2/packages/slate-browser/src/playwright/index.ts already covers:
openExample(...)editor.focus(), click(), type(), press()editor.get.text(), html(), selection(), domSelection(),
placeholderShape()editor.selection.selectAll(), get(), dom(), rect()editor.assert.text(...), htmlContains(...), htmlEquals(...),
selection(...), domSelection(...), placeholderShape(...),
placeholderVisible(...)editor.clipboard.copy(), copyPayload(), pasteText(...),
pasteHtml(...)editor.ime.compose(...)That is a real first tranche.
The missing pieces are no longer “do we have a package at all?”
The missing pieces are the next semantic seams.
Best API imports:
initialize(...)assertHTML(...)assertSelection(...)withExclusiveClipboardAccess(...)Files:
Best API imports:
getText
getSelection
getSelectedRectFiles:
Best API imports:
Files:
Best API import:
getState()File:
The existing example tests still show repeated pain:
page.goto(...)getByRole('textbox')Files:
That pain is where the next APIs should pay off.
ready ContractThis is the strongest next API.
Candidate shape:
const editor = await openExample(page, "custom-placeholder", {
ready: {
editor: "visible",
placeholder: "visible",
text: /Type something/,
selection: "settled",
selector: "#document-outline",
},
});
Optional harness form:
await editor.ready({
selection: {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 0], offset: 0 },
},
});
Why it wins:
initialize(...) bloatStrong rule:
ready object over more top-level waitForX booleanseditor.selection.select(...)This is the strongest Slate-flavoured candidate.
Candidate shape:
await editor.selection.select({
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 0], offset: 5 },
});
Convenience:
await editor.selection.collapse({ path: [0, 0], offset: 0 });
Why it wins:
Strong rule:
editor.get.blockTexts() and editor.assert.blockTexts(...)This is the best semantic getter missing today.
Candidate shape:
expect(await editor.get.blockTexts()).toEqual(["alpha", "beta"]);
await editor.assert.blockTexts(["alpha", "beta"]);
Optional narrow getter:
expect(await editor.get.textAt([1])).toBe("beta");
Why it wins:
getText(...)get.text() is too lossy for many Slate testsStrong rule:
editor.snapshot()This is the highest-value debugging API.
Candidate shape:
const snapshot = await editor.snapshot();
expect(snapshot).toEqual({
text: "Hello",
blockTexts: ["Hello"],
selection: {
anchor: { path: [0, 0], offset: 5 },
focus: { path: [0, 0], offset: 5 },
},
domSelection: {
anchorNodeText: "Hello",
anchorOffset: 5,
focusNodeText: "Hello",
focusOffset: 5,
},
});
Why it wins:
use-editable’s getState()Strong rule:
This is a precision upgrade, not a brand new domain.
Candidate shape:
await editor.assert.selection({
anchor: { path: [0, 0], offset: [0, 1] },
focus: { path: [0, 0], offset: [0, 1] },
});
And for DOM:
await editor.assert.domSelection({
anchorOffset: [0, 1],
focusOffset: [0, 1],
});
Why it wins:
Strong rule:
Current htmlEquals(...) is too literal for some browser-sensitive paths.
Candidate shape:
await editor.assert.htmlEquals(expectedHtml, {
ignoreClasses: true,
ignoreInlineStyles: true,
ignoreDir: true,
});
Why it wins:
Strong rule:
htmlEquals, not as a new pile of near-duplicate methodsCurrent surface has:
The next candidate is:
await editor.clipboard.copy();
expect(await editor.clipboard.readText()).toContain("Hello");
expect(await editor.clipboard.readHtml()).toContain("<p");
Why it matters:
navigator.clipboard.read() is useful in browser testsWhy it is not higher:
This is the strongest later candidate.
Candidate shape:
const block = editor.path([1]);
await block.click({ clickCount: 3 });
Or:
const textNode = editor.textNode([0, 0]);
Why it matters:
Why it is later:
selection.select(...) is higher value than locator sugarIf the goal is the best next API slice, do these first:
ready contracteditor.selection.select(...)editor.get.blockTexts() / assert.blockTexts(...)editor.snapshot()That is the smallest tranche that materially changes the framework from “helpful Playwright wrapper” to “real Slate-shaped test harness.”
Do not add these next:
openFixture(...)editor.driver()EditorDriver abstractionThe next candidate APIs are not random convenience sugar.
They are the missing Slate-shaped seams:
Everything else is secondary until those land.