aboutsummaryrefslogtreecommitdiff
path: root/src/server/headless/tests
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-09 22:40:57 +0300
committerGitHub <noreply@github.com>2026-09-09 22:40:57 +0300
commit985d3442b4b8a6f2e25a62821aab58d63d8ce2cf (patch)
treef744eade5e90f7ae22b7843dc51465eb99fae533 /src/server/headless/tests
parent1f1b20cb5d2a62437e1b21e237164478f9582f52 (diff)
fix: project public agent focus to attached clients (#3764)
refs #3760 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src/server/headless/tests')
-rw-r--r--src/server/headless/tests/mod.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/server/headless/tests/mod.rs b/src/server/headless/tests/mod.rs
index 78949d6e..f124e52e 100644
--- a/src/server/headless/tests/mod.rs
+++ b/src/server/headless/tests/mod.rs
@@ -2130,6 +2130,96 @@ async fn public_workspace_focus_preserves_each_clients_remembered_tabs() {
}
#[tokio::test]
+async fn public_agent_focus_replaces_a_diverged_client_shell_projection() {
+ let mut server = test_headless_server();
+ let mut first = crate::workspace::Workspace::test_new("first");
+ let first_pane = first.tabs[0].root_pane;
+ first.insert_test_runtime(
+ first_pane,
+ crate::terminal::TerminalRuntime::test_with_screen_bytes(80, 24, b"FIRST_AGENT"),
+ );
+ let mut second = crate::workspace::Workspace::test_new("second");
+ let second_pane = second.tabs[0].root_pane;
+ second.insert_test_runtime(
+ second_pane,
+ crate::terminal::TerminalRuntime::test_with_screen_bytes(80, 24, b"SECOND_WORKSPACE"),
+ );
+ server.app.state.workspaces = vec![first, second];
+ server.app.state.ensure_test_terminals();
+ server.app.state.active = Some(0);
+ server.app.state.selected = 0;
+ server.app.state.mode = crate::app::Mode::Terminal;
+ let first_workspace_id = server.app.public_workspace_id(0);
+ let first_tab_id = server.app.public_tab_id(0, 0).unwrap();
+ let first_pane_id = server.app.public_pane_id(0, first_pane).unwrap();
+ let second_tab_id = server.app.public_tab_id(1, 0).unwrap();
+
+ let (control_rx, render_rx) = connect_test_shell(&mut server, 9, 80, 23);
+ let _ = control_rx.recv().expect("initial snapshot");
+ assert!(server.focus_shell_client_on_tab(9, &second_tab_id));
+ assert!(server.claim_shell_tab_geometry(9, false));
+ server.render_and_stream();
+ let diverged = client_shell_snapshot(read_server_message(
+ control_rx.recv().expect("diverged snapshot"),
+ ));
+ assert_eq!(
+ diverged.focused_workspace_id.as_deref(),
+ Some(server.app.public_workspace_id(1).as_str())
+ );
+ let diverged_surface = recv_pane_surface(&render_rx, "diverged surface");
+ assert!(frame_text(&diverged_surface.frame).contains("SECOND_WORKSPACE"));
+
+ server
+ .app
+ .event_tx
+ .try_send(AppEvent::AgentProcessDetected {
+ pane_id: first_pane,
+ agent: crate::detect::Agent::Claude,
+ observed_at: Instant::now(),
+ })
+ .unwrap();
+ let (respond_to, response_rx) = std::sync::mpsc::channel();
+ server.handle_api_request_with_shutdown_check(crate::api::ApiRequestMessage {
+ request: crate::api::schema::Request {
+ id: "focus-first-agent".into(),
+ method: crate::api::schema::Method::AgentFocus(crate::api::schema::AgentTarget {
+ target: first_pane_id.clone(),
+ }),
+ },
+ respond_to,
+ response_write_complete: None,
+ stream_active: None,
+ });
+ let response: crate::api::schema::SuccessResponse =
+ serde_json::from_str(&response_rx.recv().expect("agent focus response")).unwrap();
+ let crate::api::schema::ResponseResult::AgentInfo { agent } = response.result else {
+ panic!("expected agent info");
+ };
+ assert_eq!(agent.pane_id, first_pane_id);
+ assert!(agent.focused);
+ assert_eq!(server.app.state.active, Some(0));
+ let location = server.clients[&9].shell_location.as_ref().unwrap();
+ assert_eq!(
+ location.focused_workspace_id.as_deref(),
+ Some(first_workspace_id.as_str())
+ );
+ assert_eq!(location.focused_tab_id(), Some(first_tab_id.as_str()));
+
+ server.render_and_stream();
+ let replacement = client_shell_snapshot(read_server_message(
+ control_rx.recv().expect("agent focus replacement snapshot"),
+ ));
+ assert_eq!(
+ replacement.focused_workspace_id.as_deref(),
+ Some(first_workspace_id.as_str())
+ );
+ let replacement_surface = recv_pane_surface(&render_rx, "agent focus replacement surface");
+ assert!(frame_text(&replacement_surface.frame).contains("FIRST_AGENT"));
+ assert!(!frame_text(&replacement_surface.frame).contains("SECOND_WORKSPACE"));
+ shutdown_test_runtimes(&mut server);
+}
+
+#[tokio::test]
async fn public_api_focus_replaces_every_client_shell_projection() {
let mut server = test_headless_server();
let first = crate::workspace::Workspace::test_new("first");