@platejs/browser is Slate's Playwright proof harness for model, DOM, native selection, focus, screenshots, trace, clipboard, and replayable scenario assertions. It is test infrastructure, not the product editing API; application code builds editors with @platejs/slate, @platejs/slate-dom, @platejs/slate-react, and extensions. Read Editing Behavior for the runtime pipeline, Selection And DOM for caret proof, Clipboard And Paste for payload proof, and Projection And Overlays for visible highlight and overlay proof.
Install
pnpm add -D @platejs/browser @playwright/testpnpm add -D @platejs/browser @playwright/testImports
The package is subpath-only:
@platejs/browser/playwrightfor Playwright editor harnesses.@platejs/browser/corefor pure proof contracts, release-proof artifacts, classifiers, and selection serialization helpers.@platejs/browser/browserfor DOM selection snapshots and zero-width placeholder inspection in browser-capable test environments.@platejs/browser/transportsfor device/browser proof-scope descriptors.
Do not import from @platejs/browser directly.
First Test
import { expect, test } from "@playwright/test";
import { openExample } from "@platejs/browser/playwright";
test("types through the Slate browser path", async ({ page }) => {
const editor = await openExample(page, "plaintext", {
ready: { editor: "visible" },
});
await editor.focus();
await editor.type("Hello from @platejs/browser");
await editor.assert.text("Hello from @platejs/browser");
await editor.assert.noDoubleSelectionHighlight();
expect(await editor.get.selectedText()).toBe("");
});import { expect, test } from "@playwright/test";
import { openExample } from "@platejs/browser/playwright";
test("types through the Slate browser path", async ({ page }) => {
const editor = await openExample(page, "plaintext", {
ready: { editor: "visible" },
});
await editor.focus();
await editor.type("Hello from @platejs/browser");
await editor.assert.text("Hello from @platejs/browser");
await editor.assert.noDoubleSelectionHighlight();
expect(await editor.get.selectedText()).toBe("");
});openExample waits for the mounted editor-ready contract before actions run.
Prefer editor.type(...), semantic selection helpers, clipboard helpers, and
native event traces over raw Playwright DOM shortcuts when the claim is editor
behavior.
Proof Contracts
Slate browser proof should usually assert more than model state:
| Claim | Useful proof |
|---|---|
| Model state changed correctly | model text, block text, operations, or commit metadata |
| Browser caret is correct | DOM caret, DOM selection, or native selection snapshot |
| Visible selection is sane | displayed selection snapshot and no double-highlight |
| Editor stayed active | focus ownership |
| Native input path is the bug | native event trace for input, paste, selection, or IME |
| Visual evidence matters | screenshot or JSON artifact |
| The editor still works afterward | follow-up typing after navigation, paste, undo, selection, or DOM repair |
Feature contracts group browser behavior families by the owning Slate feature area. Use them to keep example coverage honest without turning one manual route check into a fake global guarantee.
Transport Claims
@platejs/browser/transports classifies proof scope. A Playwright mobile viewport
does not prove raw-device behavior. Appium descriptors close raw-device lanes
only when the device gate runs. Proxy browser lanes are useful evidence, but
they do not claim native mobile clipboard, human soft-keyboard, glide typing,
or voice input.
Commands
bun run test:slate-browser
bun run test:slate-browser:core
bun run test:slate-browser:dom
bun run test:slate-browser:selectionbun run test:slate-browser
bun run test:slate-browser:core
bun run test:slate-browser:dom
bun run test:slate-browser:selectionUse focused Playwright specs for behavior routes and generated stress replay for portable editing failures.