diff options
| author | akbash <akbash@herdr.dev> | 2026-09-09 23:56:53 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-09 23:56:53 +0300 |
| commit | 120c682008a85dc17d7a13cc619a2fd5d25f3924 (patch) | |
| tree | 0119dfbe37bba91053f985ba60f3ee399d2ea797 /src/client/shell/tests | |
| parent | 985d3442b4b8a6f2e25a62821aab58d63d8ce2cf (diff) | |
fix: restore connected session navigator tree glyphs (#3861)
refs #3843
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src/client/shell/tests')
| -rw-r--r-- | src/client/shell/tests/copy.rs | 137 | ||||
| -rw-r--r-- | src/client/shell/tests/endpoints.rs | 16 |
2 files changed, 153 insertions, 0 deletions
diff --git a/src/client/shell/tests/copy.rs b/src/client/shell/tests/copy.rs index 95413f8a..fa0635af 100644 --- a/src/client/shell/tests/copy.rs +++ b/src/client/shell/tests/copy.rs @@ -732,6 +732,143 @@ fn copy_search_owns_prompt_repeat_highlights_selection_and_restore() { } #[test] +fn navigator_renders_connected_siblings_and_ancestor_lines() { + let mut snapshot = snapshot(); + snapshot.focused_pane_id = None; + snapshot.tabs[0].label = "editor".into(); + snapshot.panes[0].label = Some("agent".into()); + snapshot.panes[0].focused = false; + let mut shell = snapshot.panes[0].clone(); + shell.pane_id = "pane_shell".into(); + shell.label = Some("shell".into()); + snapshot.panes.push(shell); + for label in ["notes", "logs"] { + let mut tab = snapshot.tabs[0].clone(); + tab.tab_id = format!("tab_{label}"); + tab.label = label.into(); + tab.focused = false; + tab.number = snapshot.tabs.len() + 1; + let mut pane = snapshot.panes[0].clone(); + pane.pane_id = format!("pane_{label}"); + pane.tab_id = tab.tab_id.clone(); + pane.label = Some(label.into()); + pane.focused = false; + snapshot.tabs.push(tab); + snapshot.panes.push(pane); + } + let mut workspace = snapshot.workspaces[0].clone(); + workspace.workspace_id = "ws_2".into(); + workspace.active_tab_id = "tab_last".into(); + workspace.label = "second".into(); + workspace.number = 2; + workspace.focused = false; + let mut tab = snapshot.tabs[0].clone(); + tab.workspace_id = workspace.workspace_id.clone(); + tab.tab_id = workspace.active_tab_id.clone(); + tab.label = "last".into(); + tab.focused = false; + let mut pane = snapshot.panes[0].clone(); + pane.workspace_id = workspace.workspace_id.clone(); + pane.tab_id = tab.tab_id.clone(); + pane.pane_id = "pane_last".into(); + snapshot.workspaces.push(workspace); + snapshot.tabs.push(tab); + snapshot.panes.push(pane); + let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); + state.set_snapshot(Box::new(snapshot)); + state.set_pane_surface(surface()); + state.open_navigator_overlay(); + let prefixes = |state: &mut ClientShellState, height| { + let frame = state.compose(106, height).expect("navigator frame"); + state + .hits + .navigator_rows + .iter() + .map(|(rect, _)| { + frame.cells[rect.y as usize * frame.width as usize + rect.x as usize + 1..] + .iter() + .take(6) + .map(|cell| cell.symbol.as_str()) + .collect::<String>() + }) + .collect::<Vec<_>>() + }; + assert_eq!( + prefixes(&mut state, 30), + [ + "▾ clie", + "├── ed", + "│ ├──", + "│ └──", + "├── no", + "│ └──", + "└── lo", + " └──", + "▾ seco", + "└── la", + " └──" + ] + ); + + // The editor ancestor is above this viewport; the logs sibling is below it. + let Some(ClientShellOverlay::Navigator(navigator)) = state.overlay.as_mut() else { + panic!("expected navigator"); + }; + navigator.scroll = 2; + navigator.selected = Some(ClientNavigatorTarget::Pane { + endpoint_id: state.active_endpoint_id.clone(), + pane_id: "pane_shell".into(), + }); + assert_eq!( + prefixes(&mut state, 12), + ["│ ├──", "│ └──", "├── no", "│ └──"] + ); + + // Excluded siblings must not leave dangling continuation lines. + let Some(ClientShellOverlay::Navigator(navigator)) = state.overlay.as_mut() else { + panic!("expected navigator"); + }; + navigator.query = "shell".into(); + navigator.scroll = 0; + assert_eq!(prefixes(&mut state, 30), ["▾ clie", "└── ed", " └──"]); + let Some(ClientShellOverlay::Navigator(navigator)) = state.overlay.as_mut() else { + panic!("expected navigator"); + }; + navigator.query.clear(); + navigator.expanded_workspaces.clear(); + assert_eq!(prefixes(&mut state, 30), ["▸ clie", "▸ seco"]); +} + +#[test] +#[ignore = "manual navigator composition scaling profile"] +fn navigator_render_scale_profile() { + for panes in [1, 15, 52] { + let mut snapshot = snapshot(); + for index in 1..panes { + let mut pane = snapshot.panes[0].clone(); + pane.pane_id = format!("pane_{index}_extra"); + pane.focused = false; + snapshot.panes.push(pane); + } + let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); + state.set_snapshot(Box::new(snapshot)); + state.set_pane_surface(surface()); + state.open_navigator_overlay(); + for _ in 0..20 { + std::hint::black_box(state.compose(106, 30).expect("navigator frame")); + } + let start = std::time::Instant::now(); + for _ in 0..1000 { + std::hint::black_box(state.compose(106, 30).expect("navigator frame")); + } + eprintln!( + "navigator: {panes} panes, {:.1} us/frame", + start.elapsed().as_secs_f64() * 1000.0 + ); + } +} + +#[test] fn navigator_owns_search_mouse_selection_and_stable_target_focus() { let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); state.set_snapshot(Box::new(snapshot())); diff --git a/src/client/shell/tests/endpoints.rs b/src/client/shell/tests/endpoints.rs index e425b794..0b69135e 100644 --- a/src/client/shell/tests/endpoints.rs +++ b/src/client/shell/tests/endpoints.rs @@ -1008,6 +1008,22 @@ fn navigator_uses_machine_parents_only_for_federated_clients() { })); assert_eq!(rows.iter().filter(|row| row.current).count(), 1); + let frame = state.compose(106, 30).expect("federated navigator"); + for (rect, target) in &state.hits.navigator_rows { + let expected = match target { + ClientNavigatorTarget::Machine { .. } => " ▾ ", + ClientNavigatorTarget::Workspace { .. } => " ▾ ", + ClientNavigatorTarget::Tab { .. } => " └── ", + ClientNavigatorTarget::Pane { .. } => " └── ", + }; + let prefix = frame.cells[rect.y as usize * frame.width as usize + rect.x as usize..] + .iter() + .take(expected.chars().count()) + .map(|cell| cell.symbol.as_str()) + .collect::<String>(); + assert_eq!(prefix, expected, "{target:?}"); + } + let mut local = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); local.set_snapshot(Box::new(snapshot())); local.set_pane_surface(surface()); |
