schemaui 0.11.0

A Rust library for generating TUI and Web UIs from JSON Schemas for configuration management.
Documentation
use crate::tui::view::{
    UiContext,
    components::footer::{
        FooterActionItem, FooterStatusTone, footer_action_items, footer_status_model,
    },
};

#[test]
fn footer_action_items_split_help_snippets_into_pairs() {
    let items = footer_action_items(Some(
        "Ctrl+S -> validate and save • Ctrl+Q -> quit • Tab -> next field",
    ));

    assert_eq!(
        items,
        vec![
            FooterActionItem {
                keys: "Ctrl+S".to_string(),
                action: "validate and save".to_string(),
            },
            FooterActionItem {
                keys: "Ctrl+Q".to_string(),
                action: "quit".to_string(),
            },
            FooterActionItem {
                keys: "Tab".to_string(),
                action: "next field".to_string(),
            },
        ]
    );
}

#[test]
fn footer_status_model_prioritizes_error_tone_and_focus_context() {
    let ctx = UiContext {
        status_message: "3 issue(s) remaining",
        dirty: true,
        error_count: 3,
        help: None,
        global_errors: &[String::from(
            "matrix[0][2] invalid: expected boolean or null but got string that keeps growing",
        )],
        focus_label: Some("Level4 › Matrix".to_string()),
        session_title: Some("Service Config"),
        popup: None,
        composite_overlay: None,
        help_overlay: None,
    };

    let status = footer_status_model(&ctx);

    assert_eq!(status.tone, FooterStatusTone::Error);
    assert_eq!(status.badge, "ERR 3");
    assert_eq!(status.message, "3 issue(s) remaining");
    assert!(
        status.meta.iter().any(|entry| entry == "Unsaved changes"),
        "dirty state should still be surfaced when errors exist"
    );
    assert!(
        status
            .meta
            .iter()
            .any(|entry| entry == "Focus Level4 › Matrix"),
        "focus label should remain visible in the footer meta line"
    );
    assert!(
        status
            .alert
            .as_deref()
            .is_some_and(|alert| alert.ends_with('')),
        "global alert text should be truncated for readability"
    );
    assert_eq!(status.session_title.as_deref(), Some("Service Config"));
}

#[test]
fn footer_status_model_compacts_ready_message() {
    let ctx = UiContext {
        status_message: crate::tui::app::status::READY_STATUS,
        dirty: false,
        error_count: 0,
        help: Some("Ctrl+S -> validate and save"),
        global_errors: &[],
        focus_label: None,
        session_title: Some("SchemaUI Demo"),
        popup: None,
        composite_overlay: None,
        help_overlay: None,
    };

    let status = footer_status_model(&ctx);

    assert_eq!(status.tone, FooterStatusTone::Ready);
    assert_eq!(status.badge, "READY");
    assert_eq!(status.message, "Ready for input");
    assert!(status.meta.is_empty());
    assert!(status.alert.is_none());
    assert_eq!(status.session_title.as_deref(), Some("SchemaUI Demo"));
}