diff --git a/crates/spaceshd/src/server.rs b/crates/spaceshd/src/server.rs index 75d5749..1c33c78 100644 --- a/crates/spaceshd/src/server.rs +++ b/crates/spaceshd/src/server.rs @@ -398,4 +398,37 @@ mod tests { } panic!("socket never came up"); } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn reattach_returns_snapshot_with_prior_output() { + let dir = tempdir_path(); + let sock = dir.join("sock"); + let sock_for_task = sock.clone(); + tokio::spawn(async move { let _ = serve(&sock_for_task).await; }); + wait_for_socket(&sock).await; + + // First client: open, new surface that prints a marker, attach, then disconnect. + let surface_id; + { + let mut s = UnixStream::connect(&sock).await.unwrap(); + let r = req(&mut s, 1, Cmd::Open { path: std::env::temp_dir().to_string_lossy().into() }).await; + let ws = res_data(&r)["workspace_id"].as_str().unwrap().to_string(); + let r = req(&mut s, 2, Cmd::NewSurface { + workspace_id: spacesh_proto::WorkspaceId(ws), + command: Some("/bin/sh".into()), + args: vec!["-c".into(), "printf REPAINT_ME; sleep 2".into()], + cols: 80, rows: 24, + }).await; + surface_id = spacesh_proto::SurfaceId(res_data(&r)["surface_id"].as_str().unwrap().to_string()); + // Give the actor time to flush output into the grid. + tokio::time::sleep(tokio::time::Duration::from_millis(300)).await; + // disconnect by dropping `s` + } + + // Second client: attach to the same surface, expect snapshot to contain the marker. + let mut s2 = UnixStream::connect(&sock).await.unwrap(); + let r = req(&mut s2, 1, Cmd::Attach { surface_id: surface_id.clone() }).await; + let snap = res_data(&r)["snapshot"].as_str().unwrap(); + assert!(snap.contains("REPAINT_ME"), "snapshot was: {snap:?}"); + } }