use embers_core::{NodeId, new_request_id};
use embers_protocol::{ClientMessage, InputRequest, SessionSnapshot};
use embers_test_support::{TestConnection, TestServer, acquire_test_lock};
use crate::support::{cli_command, run_cli, session_snapshot_by_name, stdout};
fn side_by_side_panes(server: &TestServer) -> (u64, u64) {
run_cli(server, ["new-session", "alpha"]);
run_cli(server, ["new-window", "-t", "alpha", "--", "/bin/sh"]);
let split = run_cli(server, ["split-window", "--", "/bin/sh"]);
let right = stdout(&split)
.trim()
.parse::<u64>()
.expect("split-window returns pane id");
let listed = run_cli(server, ["list-panes"]);
let left = stdout(&listed)
.lines()
.filter_map(|line| line.split('\t').next()?.parse::<u64>().ok())
.find(|pane| *pane != right)
.expect("other pane exists");
(left, right)
}
fn split_sizes(snapshot: &SessionSnapshot, pane: u64) -> Vec<u16> {
snapshot
.nodes
.iter()
.find_map(|node| {
node.split
.as_ref()
.filter(|split| split.child_ids.contains(&NodeId(pane)))
})
.expect("pane sits in a split")
.sizes
.clone()
}
async fn draw_at_80x24(connection: &mut TestConnection, snapshot: &SessionSnapshot) {
let split = snapshot
.nodes
.iter()
.find_map(|node| node.split.as_ref())
.expect("window has a split");
for (child, cols) in split.child_ids.iter().zip([39, 40]) {
let buffer_id = snapshot
.nodes
.iter()
.find(|node| node.id == *child)
.and_then(|node| node.buffer_view.as_ref())
.expect("split child is a pane")
.buffer_id;
connection
.request(&ClientMessage::Input(InputRequest::Resize {
request_id: new_request_id(),
buffer_id,
cols,
rows: 22,
pixel_width: 0,
pixel_height: 0,
}))
.await
.expect("resize pane pty");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn resize_pane_moves_borders_in_cells_like_tmux() {
let _guard = acquire_test_lock().await.expect("acquire test lock");
let server = TestServer::start().await.expect("start server");
let (left, right) = side_by_side_panes(&server);
let mut connection = TestConnection::connect(server.socket_path())
.await
.expect("connect protocol client");
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
draw_at_80x24(&mut connection, &snapshot).await;
run_cli(
&server,
["resize-pane", "-t", &right.to_string(), "-L", "3"],
);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(split_sizes(&snapshot, right), vec![36, 43]);
run_cli(&server, ["resize-pane", "-t", &left.to_string(), "-R"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(split_sizes(&snapshot, right), vec![37, 42]);
run_cli(&server, ["resize-pane", "-t", &left.to_string(), "-U", "5"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(split_sizes(&snapshot, right), vec![37, 42]);
run_cli(&server, ["resize-pane", "-R", "2"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(split_sizes(&snapshot, right), vec![39, 40]);
run_cli(&server, ["resize-pane", "-t", &left.to_string(), "-Z"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(snapshot.session.zoomed_node_id, Some(NodeId(left)));
run_cli(&server, ["resize-pane", "-t", &left.to_string(), "-Z"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(snapshot.session.zoomed_node_id, None);
cli_command(&server)
.args(["resize-pane", "-t", &left.to_string(), "-L", "-R"])
.assert()
.failure();
cli_command(&server)
.args(["resize-pane", "-t", &left.to_string()])
.assert()
.failure();
server.shutdown().await.expect("shutdown server");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn synchronize_panes_toggles_per_window() {
let _guard = acquire_test_lock().await.expect("acquire test lock");
let server = TestServer::start().await.expect("start server");
side_by_side_panes(&server);
run_cli(&server, ["new-window", "-t", "alpha", "--", "/bin/sh"]);
let mut connection = TestConnection::connect(server.socket_path())
.await
.expect("connect protocol client");
let synchronized = |snapshot: &SessionSnapshot| {
let root = snapshot
.nodes
.iter()
.find(|node| node.id == snapshot.session.root_node_id)
.expect("root node");
root.tabs
.as_ref()
.expect("root tabs")
.tabs
.iter()
.map(|tab| tab.synchronize_panes)
.collect::<Vec<_>>()
};
let toggled = run_cli(&server, ["synchronize-panes", "-t", "alpha:0"]);
assert_eq!(stdout(&toggled).trim(), "on");
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(synchronized(&snapshot), vec![true, false]);
let on = run_cli(&server, ["synchronize-panes", "-t", "alpha:0", "on"]);
assert_eq!(stdout(&on).trim(), "on");
run_cli(&server, ["synchronize-panes", "on"]);
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(synchronized(&snapshot), vec![true, true]);
let off = run_cli(&server, ["synchronize-panes", "-t", "alpha:0", "off"]);
assert_eq!(stdout(&off).trim(), "off");
let snapshot = session_snapshot_by_name(&mut connection, "alpha").await;
assert_eq!(synchronized(&snapshot), vec![false, true]);
server.shutdown().await.expect("shutdown server");
}