From 7b7cb7da15cb1d046181cdc35c5c7a218aa639fc Mon Sep 17 00:00:00 2001 From: slhx agent Date: Tue, 2 Jun 2026 00:11:55 +0200 Subject: [PATCH] test(browser): avoid selector scripts in e2e Pass WebDriver-found elements into browser E2E helper scripts and build the probe island with DOM APIs, keeping test-only JavaScript from reintroducing querySelector or unchecked HTML insertion. req: runtime/001 req: examples/005 --- examples/techdemo/tests/browser_e2e.rs | 54 +++++++++++++++----------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/examples/techdemo/tests/browser_e2e.rs b/examples/techdemo/tests/browser_e2e.rs index 1cb2a25..eabede6 100644 --- a/examples/techdemo/tests/browser_e2e.rs +++ b/examples/techdemo/tests/browser_e2e.rs @@ -138,43 +138,53 @@ fn card_button_selector(handle_id: impl std::fmt::Display, work_id: u64) -> Stri } async fn insert_probe_island(driver: &WebDriver) -> WebDriverResult<()> { + let root = driver.find(By::Css("[data-slhx-root]")).await?; driver .execute( r#" - document.querySelector('[data-slhx-root]').insertAdjacentHTML('beforeend', ` -
- -

waiting

-
- `); + const root = arguments[0]; + const island = document.createElement('article'); + island.id = 'probe-island'; + island.setAttribute('data-slhx-island', 'orbit'); + island.setAttribute('data-island-snapshot', '1|1|1|probe waiting'); + + const canvas = document.createElement('canvas'); + canvas.width = 32; + canvas.height = 16; + island.appendChild(canvas); + + const readout = document.createElement('p'); + readout.setAttribute('data-island-readout', ''); + readout.textContent = 'waiting'; + island.appendChild(readout); + + root.appendChild(island); setTimeout(() => { - document.querySelector('[data-slhx-root]').dispatchEvent(new CustomEvent('slhx:island-orbit', { bubbles: true, detail: '7|2|8|probe live' })); + root.dispatchEvent(new CustomEvent('slhx:island-orbit', { bubbles: true, detail: '7|2|8|probe live' })); }, 25); return true; "#, - Vec::new(), + vec![root.to_json()?], ) .await?; Ok(()) } async fn drag_card_to_lane(driver: &WebDriver, work_id: u64, lane: &str) -> WebDriverResult<()> { + let card = driver.find(By::Css(format!(".work-card[data-key='{work_id}']"))).await?; + let lane = driver.find(By::Css(format!(".lane[data-lane='{lane}']"))).await?; driver .execute( - &format!( - r#" - const card = document.querySelector({:?}); - const lane = document.querySelector({:?}); - const data = new DataTransfer(); - card.dispatchEvent(new DragEvent('dragstart', {{ bubbles: true, dataTransfer: data }})); - lane.dispatchEvent(new DragEvent('dragover', {{ bubbles: true, cancelable: true, dataTransfer: data }})); - lane.dispatchEvent(new DragEvent('drop', {{ bubbles: true, cancelable: true, dataTransfer: data }})); - return true; - "#, - format!(".work-card[data-key='{work_id}']"), - format!(".lane[data-lane='{lane}']"), - ), - Vec::new(), + r#" + const card = arguments[0]; + const lane = arguments[1]; + const data = new DataTransfer(); + card.dispatchEvent(new DragEvent('dragstart', { bubbles: true, dataTransfer: data })); + lane.dispatchEvent(new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer: data })); + lane.dispatchEvent(new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: data })); + return true; + "#, + vec![card.to_json()?, lane.to_json()?], ) .await?; Ok(())