From 4be4605543cd06dc4321e167215f02b3235198a5 Mon Sep 17 00:00:00 2001 From: Lppy <376286605@qq.com> Date: Wed, 18 Mar 2026 23:59:56 +0800 Subject: [PATCH] fix: dedup text content in snapshot (#909) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: dedup text content in snapshot * fix: format --------- Co-authored-by: 羲洋 --- cli/src/native/e2e_tests.rs | 63 +++++++++++++++++++++++++++++++++++++ cli/src/native/snapshot.rs | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/cli/src/native/e2e_tests.rs b/cli/src/native/e2e_tests.rs index 42919a1..d18c8d9 100644 --- a/cli/src/native/e2e_tests.rs +++ b/cli/src/native/e2e_tests.rs @@ -2210,3 +2210,66 @@ async fn e2e_snapshot_cursor_many_elements() { let resp = execute_command(&json!({ "id": "99", "action": "close" }), &mut state).await; assert_success(&resp); } + +/// Test that InlineTextBox nodes are filtered from snapshot output while preserving +/// the actual text content from parent elements. +#[tokio::test] +#[ignore] +async fn e2e_snapshot_inline_text_box_filtered() { + let mut state = DaemonState::new(); + + let resp = execute_command( + &json!({ "id": "1", "action": "launch", "headless": true }), + &mut state, + ) + .await; + assert_success(&resp); + + // Simple HTML with text content that would generate InlineTextBox nodes + let html = + "data:text/html,
Hello World
"; + + let resp = execute_command( + &json!({ "id": "2", "action": "navigate", "url": html }), + &mut state, + ) + .await; + assert_success(&resp); + + // Take snapshot to capture full output and verify InlineTextBox filtering + let start = std::time::Instant::now(); + let resp = execute_command(&json!({ "id": "3", "action": "snapshot" }), &mut state).await; + assert_success(&resp); + let elapsed = start.elapsed(); + + let snapshot_output = get_data(&resp)["snapshot"].as_str().unwrap(); + + // Verify that InlineTextBox does not appear in the output + assert!( + !snapshot_output.contains("InlineTextBox"), + "Snapshot output should not contain InlineTextBox: {}", + snapshot_output + ); + + // Verify that the actual text content is preserved + assert!( + snapshot_output.contains("Hello"), + "Snapshot should contain 'Hello': {}", + snapshot_output + ); + assert!( + snapshot_output.contains("World"), + "Snapshot should contain 'World': {}", + snapshot_output + ); + + // Must complete quickly + assert!( + elapsed.as_secs() < 5, + "snapshot with InlineTextBox filtering took {:?}, expected < 5s", + elapsed, + ); + + let resp = execute_command(&json!({ "id": "99", "action": "close" }), &mut state).await; + assert_success(&resp); +} diff --git a/cli/src/native/snapshot.rs b/cli/src/native/snapshot.rs index addcf6d..8d170a4 100644 --- a/cli/src/native/snapshot.rs +++ b/cli/src/native/snapshot.rs @@ -712,7 +712,7 @@ fn build_tree(nodes: &[AXNode]) -> (Vec, Vec) { let (level, checked, expanded, selected, disabled, required) = extract_properties(&node.properties); - if node.ignored.unwrap_or(false) && role != "RootWebArea" { + if (node.ignored.unwrap_or(false) && role != "RootWebArea") || role == "InlineTextBox" { tree_nodes.push(TreeNode { role: String::new(), name: String::new(),