diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-09-06 02:27:06 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-06 02:27:06 +0300 |
| commit | 9e9bc8a144667a6b7debfd4f0c7a31ff0e11493a (patch) | |
| tree | 03f1259f91fd9edeacfd4b904f2e84d4acf25232 /src/client/shell/tests/mobile.rs | |
| parent | 35b0dff96579f099e0436290085024424ffb289c (diff) | |
feat: manage multiple ssh machines from one client (#3670)
Diffstat (limited to 'src/client/shell/tests/mobile.rs')
| -rw-r--r-- | src/client/shell/tests/mobile.rs | 95 |
1 files changed, 91 insertions, 4 deletions
diff --git a/src/client/shell/tests/mobile.rs b/src/client/shell/tests/mobile.rs index 094b141f..b7cc2a47 100644 --- a/src/client/shell/tests/mobile.rs +++ b/src/client/shell/tests/mobile.rs @@ -30,6 +30,7 @@ fn navigate_update_status_uses_released_desktop_and_mobile_placement() { state.config.tab_bar_position = crate::config::TabBarPositionConfig::Top; state.visible_notification = Some(ClientVisibleNotification { + endpoint_id: ClientEndpointId::Local, event: SemanticNotification { kind: SemanticNotificationKind::Custom, title: "bottom notification".into(), @@ -69,6 +70,74 @@ fn mobile_layout_reserves_only_client_header() { } #[test] +fn mobile_switcher_can_activate_an_online_saved_machine() { + let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); + let profile = crate::client::endpoint::SavedSshEndpoint { + id: crate::client::endpoint::ProfileId::parse("0123456789abcdef0123456789abcdef").unwrap(), + label: "Build".into(), + target: "build".into(), + session: "agents".into(), + enabled: true, + }; + let endpoint_id = ClientEndpointId::Ssh(profile.id.clone()); + state.set_endpoint_catalog(&[profile]); + state.set_endpoint_status(&endpoint_id, ClientEndpointStatus::Online); + state.set_snapshot(Box::new(snapshot())); + state.set_pane_surface(surface()); + let mut remote = snapshot(); + remote.boot_id = "remote-boot".into(); + state.set_endpoint_snapshot(&endpoint_id, Box::new(remote)); + state.mode = ClientShellMode::Navigate; + + let frame = state.compose(44, 30).expect("mobile machine switcher"); + let text = frame + .cells + .iter() + .map(|cell| cell.symbol.as_str()) + .collect::<String>(); + assert!(text.contains("machines")); + assert!(text.contains("Build")); + let machine = state + .hits + .mobile_targets + .iter() + .find_map(|(rect, target)| { + matches!(target, ClientMobileTarget::Machine(id) if id == &endpoint_id).then_some(*rect) + }) + .expect("saved machine target"); + let outcome = state.handle_raw_events(vec![RawInputEvent::Mouse(MouseEvent { + kind: MouseEventKind::Down(MouseButton::Left), + column: machine.x, + row: machine.y, + modifiers: KeyModifiers::empty(), + })]); + assert!(matches!( + outcome.actions.as_slice(), + [ClientShellAction::ActivateEndpoint { + endpoint_id: activated, + target: None, + }] if activated == &endpoint_id + )); + + state.set_endpoint_status(&endpoint_id, ClientEndpointStatus::Online); + assert!(state.activate_endpoint_projection(&endpoint_id)); + let mut remote_surface = surface(); + remote_surface.boot_id = "remote-boot".into(); + state.set_pane_surface(remote_surface); + state.mark_endpoint_disconnected(&endpoint_id); + state.receive_endpoint_unavailable("network lost".into()); + state.mode = ClientShellMode::Navigate; + let stale = state.compose(44, 30).expect("stale mobile switcher"); + let text = stale + .cells + .iter() + .map(|cell| cell.symbol.as_str()) + .collect::<String>(); + assert!(text.contains("reconnecting"), "frame: {text}"); + assert!(text.contains("network lost"), "frame: {text}"); +} + +#[test] fn mobile_shell_controls_remain_clickable_when_pane_mouse_capture_is_disabled() { let mut config = ClientShellConfig::from_config(&Config::default()); config.mouse_capture = false; @@ -175,7 +244,11 @@ fn mobile_header_and_switcher_render_released_sections_and_stable_targets() { .mobile_targets .iter() .find_map(|(rect, target)| { - matches!(target, ClientMobileTarget::Workspace(id) if id == "ws_1").then_some(*rect) + matches!( + target, + ClientMobileTarget::Workspace { workspace_id, .. } if workspace_id == "ws_1" + ) + .then_some(*rect) }) .expect("workspace hit"); let focused = state.handle_raw_events(vec![click(workspace_hit)]); @@ -199,7 +272,11 @@ fn mobile_header_and_switcher_render_released_sections_and_stable_targets() { .mobile_targets .iter() .find_map(|(rect, target)| { - matches!(target, ClientMobileTarget::Agent(id) if id == "pane_1").then_some(*rect) + matches!( + target, + ClientMobileTarget::Agent { pane_id, .. } if pane_id == "pane_1" + ) + .then_some(*rect) }) .expect("agent hit"); let focused = state.handle_raw_events(vec![click(agent_hit)]); @@ -221,7 +298,14 @@ fn mobile_header_and_switcher_render_released_sections_and_stable_targets() { .mobile_targets .iter() .find_map(|(rect, target)| { - matches!(target, ClientMobileTarget::Tab(id) if id == "tab_1").then_some(*rect) + matches!( + target, + ClientMobileTarget::Tab { + endpoint_id, + tab_id, + } if endpoint_id.is_local() && tab_id == "tab_1" + ) + .then_some(*rect) }) .expect("tab hit"); let focused = state.handle_raw_events(vec![click(tab_hit)]); @@ -534,7 +618,10 @@ fn mobile_switcher_scroll_close_and_width_transition_clear_mobile_hits() { assert_eq!(state.navigate_workspace_id.as_deref(), Some("ws_8")); assert!(state.mobile_switcher_scroll > 2); assert!(state.hits.mobile_targets.iter().any(|(_, target)| { - matches!(target, ClientMobileTarget::Workspace(id) if id == "ws_8") + matches!( + target, + ClientMobileTarget::Workspace { workspace_id, .. } if workspace_id == "ws_8" + ) })); let close = state.hits.mobile_close; state.handle_raw_events(vec