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(),