Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-icebergview/tests/robot.rs

//! **Robot JSON-drive scenario for the Iceberg browse + time-travel viewer**,
//! driven through the SHARED generic-Facet probe in `facett_core::harness` (no
//! hand-rolled render+emit boilerplate). The pane's `update_json` robot seam was a
//! **dead no-op** — the `impl_facet_via_elm!` bridge does not generate one and the
//! pane never overrode `Facet::update_json`, so a headless robot could not drive
//! it (only the in-view `ui_render` self-cell existed). This test (a) proves the
//! now-LIVE seam end-to-end — feed a scripted message list (time-travel), watch
//! `state_json` transition — and (b) adds the shared probe's `headless_render` +
//! `responds_to_input` functional cells via `facett_core::testmatrix::probe_and_emit`
//! (a no-op unless built with `--features testmatrix`). The `responds_to_input`
//! aspect is NEW coverage: it would go RED if the JSON drive seam regressed back
//! to a no-op. See `.nornir/facett-platform-gaps.md`.

use std::sync::Arc;

use arrow_array::{Int64Array, RecordBatch, StringArray};
use arrow_schema::{DataType, Field, Schema};
use facett_icebergview::{IcebergView, Snapshot, SnapshotMeta};

fn batch(ids: &[i64], names: &[&str]) -> RecordBatch {
    RecordBatch::try_new(
        Arc::new(Schema::new(vec![
            Field::new("id", DataType::Int64, false),
            Field::new("name", DataType::Utf8, false),
        ])),
        vec![
            Arc::new(Int64Array::from(ids.to_vec())),
            Arc::new(StringArray::from(names.to_vec())),
        ],
    )
    .unwrap()
}

#[test]
fn robot_json_drive_scenario() {
    // Two snapshots: v1 (older, 2 rows) and v2 (newer, 3 rows). The view selects
    // the newest (200) first.
    let v1 = Snapshot::new(SnapshotMeta::new(100, 1_000, 2), vec![batch(&[1, 2], &["knut", "korp"])]);
    let v2 = Snapshot::new(SnapshotMeta::new(200, 2_000, 3), vec![batch(&[1, 2, 3], &["knut", "korp", "skade"])]);
    let mut view = IcebergView::new("🧊 Tables", "Person", vec![v1, v2]);

    // Time-travel to the older snapshot, then back — the exact JSON a headless
    // robot sends through the `update_json` seam (serde-tagged, no concrete Msg).
    let script = [
        r#"{"select_snapshot":100}"#, // time-travel to v1
        r#"{"select_snapshot":200}"#, // back to v2
    ];

    let probe = facett_core::testmatrix::probe_and_emit("facett-icebergview", &mut view, &script);

    // The initial render drew real geometry (row grid) over non-empty state.
    assert!(probe.drew(), "the row grid must tessellate to vertices");
    assert!(probe.cardinality() > 0, "state_json reports snapshots / rows");
    // The input surface is LIVE: at least one scripted message moved state.
    assert!(probe.responded(), "update_json must drive state — a dead seam is a regression");

    // Pane-specific: time-travel lands the selected snapshot id in `current`.
    assert_eq!(probe.steps[0].state["current"], 100, "select_snapshot time-travels to v1");
    assert!(probe.steps[0].changed, "select_snapshot moved state");
    assert_eq!(probe.final_state["current"], 200, "selecting back lands on v2");
}