Interact and wait for results
Interact and wait for results.
Wait for the thing you need
Navigation reaching domcontentloaded does not mean every application widget is ready. Use locators and explicit result assertions rather than fixed sleeps. The following Playwright fragment expects a page with a labeled Name input, a Save button, and a status element:
await page.getByLabel('Name', { exact: true }).fill('Ada');
await page.getByRole('button', { name: 'Save', exact: true }).click();
await page.getByRole('status').filter({ hasText: 'Saved Ada' }).waitFor();
console.log(await page.getByRole('status').innerText());Replace labels and expected results with your application's actual contract. Match unique controls; a selector that happens to find the first button is not reliable. For iframe content, select the correct frame first. Handle dialogs before the action that opens them.
Retry carefully
A navigation retry and a form-submit retry have different consequences. If a submit times out, inspect whether it already succeeded before clicking again. Set bounded timeouts and use the application's confirmation ID/status as the success signal, not just the absence of browser errors.
Use session lifecycle cleanup even when a wait fails. For terminal automation, inspect browser-cli action fill-label --help, click-role --help, and wait-text --help for the installed command syntax.
