#![cfg(feature = "tui")]
use std::collections::BTreeSet;
use clap::CommandFactory;
use ignition_cli::cli::Cli;
use ignition_tui::routes::{Mapping, routes};
fn walk(cmd: &clap::Command, prefix: &str, out: &mut Vec<String>) {
for sub in cmd.get_subcommands() {
if sub.get_name() == "help" {
continue;
}
let path = if prefix.is_empty() {
sub.get_name().to_string()
} else {
format!("{prefix} {}", sub.get_name())
};
let has_real_children = sub
.get_subcommands()
.any(|child| child.get_name() != "help");
if !has_real_children || !sub.is_subcommand_required_set() {
out.push(path.clone());
}
walk(sub, &path, out);
}
}
#[test]
fn every_row_requiring_cli_node_is_mapped_and_no_orphans() {
let mut cli_nodes = Vec::new();
walk(&Cli::command(), "", &mut cli_nodes);
assert!(!cli_nodes.is_empty(), "the walk found the tree");
let cli_set: BTreeSet<&str> = cli_nodes.iter().map(String::as_str).collect();
let registry_set: BTreeSet<&str> = routes().iter().map(|route| route.path).collect();
let missing: Vec<&str> = cli_set.difference(®istry_set).copied().collect();
assert!(
missing.is_empty(),
"CLI row-requiring nodes with no TUI mapping (add routes() rows or \
an OutOfBand justification): {missing:#?}"
);
let orphans: Vec<&str> = registry_set.difference(&cli_set).copied().collect();
assert!(
orphans.is_empty(),
"TUI registry rows with no CLI node (stale or misspelled paths): {orphans:#?}"
);
assert_eq!(
cli_set.len(),
registry_set.len(),
"bidirectional equality over {} row-requiring nodes",
registry_set.len()
);
}
#[test]
fn out_of_band_rows_are_exactly_the_completions_leaf() {
let out_of_band: Vec<&str> = routes()
.iter()
.filter(|route| matches!(route.mapping, Mapping::OutOfBand))
.map(|route| route.path)
.collect();
assert_eq!(
out_of_band,
vec!["completions"],
"the OutOfBand set must stay exactly the completions leaf"
);
}
#[test]
fn bare_option_forms_are_row_requiring_nodes() {
let mut cli_nodes = Vec::new();
walk(&Cli::command(), "", &mut cli_nodes);
let cli_set: BTreeSet<&str> = cli_nodes.iter().map(String::as_str).collect();
for bare in ["sessions", "logs", "logs loggers"] {
assert!(
cli_set.contains(bare),
"the bare form {bare:?} must be row-requiring (Option subcommand)"
);
}
for group in [
"wait",
"project",
"tags",
"rig",
"rig trial",
"profile",
"resource",
"webdev",
] {
assert!(
!cli_set.contains(group),
"the required-subcommand group {group:?} must not be a row of its own"
);
}
}