use super::*;
use crate::test_support::temp_dir;
use std::fs;
#[test]
fn parses_status_options() {
let default_options = StatusOptions::parse([]).expect("parse default options");
assert_eq!(default_options.environment, "local");
assert_eq!(default_options.icp, "icp");
let options = StatusOptions::parse([
OsString::from(crate::cli::globals::INTERNAL_ENVIRONMENT_OPTION),
OsString::from("ic"),
OsString::from(crate::cli::globals::INTERNAL_ICP_OPTION),
OsString::from("/tmp/icp"),
])
.expect("parse explicit options");
assert_eq!(options.environment, "ic");
assert_eq!(options.icp, "/tmp/icp");
}
#[test]
fn renders_status_report() {
let report = StatusReport {
environment: "local".to_string(),
replica: ReplicaStatus::Running,
replica_port: "8000".to_string(),
icp_cli: "icp 0.2.5".to_string(),
icp_project: "ok (icp.yaml)".to_string(),
canonical_network_id: "network-1".to_string(),
apps: vec![
StatusAppRow {
app: "shop".to_string(),
config: "apps/demo/canic.toml".to_string(),
canisters: "4".to_string(),
},
StatusAppRow {
app: "test".to_string(),
config: "apps/test/canic.toml".to_string(),
canisters: "7".to_string(),
},
],
fleets: vec![StatusFleetRow {
fleet: "staging".to_string(),
app: "shop".to_string(),
network: "network-1".to_string(),
deployed: "yes".to_string(),
coordinator: "aaaaa-aa".to_string(),
}],
};
let rendered = render_status_report(&report);
assert!(rendered.contains("Apps: 2 configured"));
assert!(rendered.contains("Fleets: 1/1 deployed (environment local, network network-1)"));
assert!(rendered.contains("APP CONFIG CANISTERS"));
assert!(rendered.contains("shop apps/demo/canic.toml 4"));
assert!(rendered.contains("FLEET APP NETWORK DEPLOYED COORDINATOR"));
assert!(rendered.contains("staging shop network-1 yes aaaaa-aa"));
assert!(!rendered.contains("DEPLOYMENT"));
}
#[test]
fn renders_empty_status_report() {
let report = StatusReport {
environment: "local".to_string(),
replica: ReplicaStatus::Stopped,
replica_port: "8001".to_string(),
icp_cli: "icp 0.2.5".to_string(),
icp_project: "not checked (no Canic App configs)".to_string(),
canonical_network_id: "network-1".to_string(),
apps: Vec::new(),
fleets: Vec::new(),
};
assert_eq!(
render_status_report(&report),
"Replica: stopped (local, port 8001)\nICP CLI: icp 0.2.5\nICP project: not checked (no Canic App configs)\nApps: 0 configured\nFleets: 0/0 deployed (environment local, network network-1)"
);
}
#[test]
fn renders_http_fallback_replica_status() {
let report = StatusReport {
environment: "local".to_string(),
replica: ReplicaStatus::RunningHttpFallback,
replica_port: "8000".to_string(),
icp_cli: "icp 0.2.6".to_string(),
icp_project: "ok (icp.yaml)".to_string(),
canonical_network_id: "network-1".to_string(),
apps: Vec::new(),
fleets: Vec::new(),
};
assert_eq!(
render_status_report(&report),
"Replica: running (local, port 8000, HTTP reachable; ICP CLI status stopped)\nICP CLI: icp 0.2.6\nICP project: ok (icp.yaml)\nApps: 0 configured\nFleets: 0/0 deployed (environment local, network network-1)"
);
}
#[test]
fn status_app_inventory_uses_project_root_for_config_paths() {
let root = temp_dir("canic-status-project-root");
let config = root.join("apps/toko/canic.toml");
fs::create_dir_all(config.parent().expect("config parent")).expect("create config parent");
fs::write(
&config,
r#"
[app]
name = "toko"
[roles.root]
kind = "root"
package = "root"
[roles.app]
kind = "canister"
package = "app"
[auth.delegated_tokens]
enabled = false
[component_specs.app]
component_role = "app"
maximum_instances = 1
"#,
)
.expect("write config");
let inventory = load_status_apps(&root, std::slice::from_ref(&config));
let row = inventory.rows.first().expect("status App row");
fs::remove_dir_all(root).expect("remove temp root");
assert_eq!(row.app, "toko");
assert_eq!(row.config, "apps/toko/canic.toml");
assert_eq!(row.canisters, "2");
}
#[test]
fn fleet_status_uses_explicit_catalog_app_binding() {
let fleet = fleet_catalog_entry();
let row = status_fleet_row(&fleet);
assert_eq!(row.fleet, "demo");
assert_eq!(row.app, "shop");
assert_ne!(row.fleet, row.app);
assert_eq!(row.network, fleet.canonical_network_id.to_string());
assert_eq!(row.deployed, "yes");
assert_eq!(row.coordinator, fleet.coordinator_principal);
}
#[test]
fn status_usage_lists_options_and_examples() {
let text = usage();
assert!(text.contains("Show quick Canic project status"));
assert!(text.contains("Usage: canic status"));
assert!(!text.contains("--environment"));
assert!(!text.contains("--icp"));
assert!(text.contains("Examples:"));
assert!(text.contains("terminal catalog receipts"));
assert!(text.contains("does not query live Coordinator"));
}
fn fleet_catalog_entry() -> FleetCatalogEntryV1 {
FleetCatalogEntryV1 {
canonical_network_id: canic_core::ids::CanonicalNetworkId::public_ic(),
fleet_id: canic_core::ids::FleetId::from_generated_bytes([1; 32]),
fleet_name: "demo".parse().expect("Fleet name"),
app: canic_core::ids::AppId::from("shop"),
environment: "local".to_string(),
deployed_at_unix_secs: 1,
coordinator_principal: "aaaaa-aa".to_string(),
}
}