Automating React, DraftJS, ProseMirror & CodeMirror
How to reliably automate modern framework-controlled inputs, virtualized textareas, and rich-text document editors where conventional synthetic typing fails.
el.value = '...') during framework re-renders. To automate React inputs, override the prototype setter using Object.getOwnPropertyDescriptor(proto, 'value').set. For DraftJS, allow 100ms for selection reconciliation before inserting text. For CodeMirror, invoke .CodeMirror.setValue() directly on the host element.
1. React Synthetic Value Setter Override
React overrides native HTML input value properties to maintain internal state. If you set el.value = "val" directly, React ignores the change and reverts it on the next render. Use this helper via browser_evaluate:
// Executes inside browser_evaluate
(() => {
const el = document.querySelector('input#target-field');
const proto = el.tagName === 'TEXTAREA' ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
const setter = Object.getOwnPropertyDescriptor(proto, 'value').set;
el.focus();
setter.call(el, 'My Value');
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
return true;
})()
2. DraftJS Caret Drift & Selection Reconciliation
DraftJS (used in Twitter/X and social publishers) updates its internal immutable state asynchronously when selection changes. Calling el.focus() immediately before inserting text collapses the cursor to the end of the text, causing words to be appended rather than replaced.
The Fix:
- Dispatch a Select-All command.
- Pause execution for 100ms so DraftJS reconciles its internal model with the DOM.
- Dispatch
document.execCommand('insertText', false, text)without refocusing.
3. CodeMirror & Monaco Virtual Editors
CodeMirror (used by GitHub Gists, JSFiddle, and developer consoles) renders virtualized lines and will discard direct keystroke events. Instead, access the CodeMirror instance attached to the DOM node:
// Executes inside browser_evaluate
(() => {
const cm = document.querySelector('.CodeMirror')?.CodeMirror;
if (cm) {
cm.setValue('// Injected code\nconsole.log("hello world");');
if (cm.save) cm.save();
return true;
}
return false;
})()
4. Generic ContentEditable Prompt Boxes
For rich prompt boxes (e.g. Google Flow, Notion, Slack):
// Executes inside browser_evaluate
(() => {
const el = document.querySelector('div[contenteditable="true"]');
el.focus();
const s = window.getSelection();
s.removeAllRanges();
const r = document.createRange();
r.selectNodeContents(el);
s.addRange(r);
document.execCommand('insertText', false, 'Your formatted prompt text here');
return true;
})()