docs/solutions/test-failures/2026-04-29-slate-browser-command-rows-must-share-app-text-policy-with-native-input.md
bun test:integration-local had real reds after excluding stress rows. The
broken examples put editing policy in browser-event-only handlers, while
slate-browser command rows use editor handles that must prove the same user
behavior without depending on DOM event transport.
inlines did not wrap a typed URL when the test used editor.insertText(...).markdown-shortcuts did not convert - through the same command-style text
insertion path.persistent-annotation-anchors inserted raw nodes where the expected behavior
was fragment insertion semantics.large-document-runtime rich HTML paste over shell-backed selection depended
on whether Firefox synthetic paste mutated selection before the fallback path.onDOMBeforeInput.
That only proves native event transport, not the command path used by
slate-browser.Put example-owned text insertion policy on the shared Editable inputRules
surface and keep browser-event hooks for browser-event-only bookkeeping.
const inputRules = useMemo<readonly EditableInputRule[]>(
() => [
({ data, inputType }) => {
if (inputType === 'insertText' && typeof data === 'string') {
return applyMarkdownTextShortcut(editor, data)
}
},
],
[editor]
)
return <Editable inputRules={inputRules} />
Make the public wrapper expose the same input-rule path as the DOM root:
export type { EditableInputRule } from 'slate-react'
For paste-like behavior, use transaction fragment insertion instead of raw node insertion:
editor.update(tx => {
tx.fragment.insert([
{
type: 'paragraph',
children: [{ bold: true, text }],
},
])
})
For Firefox synthetic paste rows that already need the proof handle fallback, call the handle directly and import DOM selection before inserting data.
The browser proof handle is not just a testing convenience. It is the executable
contract for model-owned editor operations. If an example puts real editing
policy only in onDOMBeforeInput, native browser input and command-style proof
paths can drift.
Editable inputRules gives native and command-style text insertion one shared
policy point. insertFragment(...) gives paste and fragment buttons the same
merge/replacement semantics that users expect from Slate editing, instead of
depending on raw node insertion details.
onDOMBeforeInput.slate-browser command rows on editor handles when the contract is model
behavior, even if a page-keyboard version would pass.insertFragment(...) for paste-like and fragment-like insertion tests.handle.insertData(...).PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration --max-failures=1 --reporter=line