wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
use super::*;

use axum::body::Body;
use axum::http::Request;
use serde_json::json;
use tower::ServiceExt;

async fn call(router: &Router, method: &str, body: Option<serde_json::Value>) -> (StatusCode, serde_json::Value) {
    let request = Request::builder()
        .method(method)
        .uri("/api/v1/workbench/layout")
        .header("content-type", "application/json")
        .body(body.map_or_else(Body::empty, |body| Body::from(body.to_string())))
        .expect("a request");
    let response = router.clone().oneshot(request).await.expect("the router answers");
    let status = response.status();
    let bytes = hyper::body::to_bytes(response.into_body()).await.expect("a body");
    (status, serde_json::from_slice(&bytes).unwrap_or(serde_json::Value::Null))
}

/// TEST20179: the machine keeps one workbench layout: none until one is saved,
/// what was saved given back whole — a tab's input is the workbench's and is not
/// reshaped — a second save replacing the first, and anything but an object
/// refused.
#[tokio::test]
async fn test20179_the_machine_keeps_one_layout_given_back_as_saved() {
    let machine_dir = tempfile::tempdir().expect("a machine folder");
    let _env = wsb::test_environment::Environment::set(&[(wsb::daemon::MACHINE_DIR_ENV, &machine_dir.path().to_string_lossy())]);
    let machine = crate::machine::MachineState::new(
        machine_dir.path().to_path_buf(),
        &machine_dir.path().join("wsb.db"),
        std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST),
        0,
        std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST),
        0,
    )
    .expect("a machine");
    let router = routes().with_state(machine);

    let (status, said) = call(&router, "GET", None).await;
    assert_eq!(status, StatusCode::NOT_FOUND, "a machine that never saved a layout has none: {said}");

    let layout = json!({
        "groups": [{ "id": "group:1", "tabs": [{ "key": "file:wsb:main|README.md", "side": "worktree", "input": { "kind": "file", "worktree": "wsb:main", "path": "README.md", "nested": [1, 2] } }], "active": "file:wsb:main|README.md", "share": 1 }],
        "focused": "group:1",
        "arrangement": "beside",
    });
    let (status, _) = call(&router, "PUT", Some(layout.clone())).await;
    assert_eq!(status, StatusCode::OK);
    let (status, back) = call(&router, "GET", None).await;
    assert_eq!(status, StatusCode::OK);
    assert_eq!(back, layout, "the layout came back reshaped");

    let next = json!({ "groups": [], "focused": "group:2", "arrangement": "stacked" });
    call(&router, "PUT", Some(next.clone())).await;
    assert_eq!(call(&router, "GET", None).await.1, next, "a second save did not replace the first");

    let (status, said) = call(&router, "PUT", Some(json!(["not", "a", "layout"]))).await;
    assert_eq!(status, StatusCode::BAD_REQUEST, "{said}");
    assert_eq!(call(&router, "GET", None).await.1, next, "a refused save changed the layout");
}