Context: creating Gmail drafts in a user's real logged-in Chrome via a CDP relay (omp browser relay, Puppeteer page objects from browser.pages()/newPage()).
https://mail.google.com/mail/u/0/?view=cm&fs=1&tf=1&to=..&su=..&body=..prefills a full-screen compose but Gmail does not create a draft until an edit happens. Click the body, type a space, Backspace, then poll for the 'Draft saved' indicator before closing.- In a tab that is not foreground,
element.innerText(anddocument.body.innerText) returns empty strings (no layout), so/Draft saved/.test(document.body.innerText)never matches and Gmail list rows read as ''. UsetextContentinstead. ElementHandle.click() in a background tab can also hang ('Runtime.callFunctionOn timed out' inside isIntersectingViewport); callpage.bringToFront()first, or click viaevaluate(el => el.click())(works for Gmail list rows, opens the draft). - Edits made in a background tab may not trigger Gmail autosave at all; bring the tab to front before editing.
keyboard.down('Meta'); press('KeyA')does NOT select-all on macOS via CDP (known Puppeteer limitation); the new text was appended to the subject instead of replacing it. Useevaluate(() => input.select())after focusing, thenkeyboard.type.page.close()on a compose with unsaved changes fires beforeunload, which shows 'Changes you made may not be saved' in the user's real browser and blocks. Registerpage.on('dialog', d => d.accept()), setwindow.onbeforeunload = null, and usepage.close({runBeforeUnload:false})only after 'Draft saved' is observed. A stuck dialog can be dismissed with a CDP session:Page.handleJavaScriptDialog {accept:false}.- Gmail compose controls: subject
input[name=subjectbox], bodydiv[aria-label='Message Body'], close[aria-label='Save & close'], discard[aria-label^='Discard draft'](label includes a shortcut suffix like ' (⌘⇧D)', so exact match fails). - Never type into a compose the user may also be focused on: stray keystrokes landed in a draft body when both agent and user interacted with the same window; verify body text before/after each edit.