use clap::Parser;
use helm_schema_cli::Cli;
use helm_schema_cli::cli::{CrdVersionLookup, DiagFormat, K8sVersionFallback};
use test_util::prelude::sim_assert_eq;
fn parse(args: &[&str]) -> Result<Cli, String> {
let mut full = vec!["helm-schema"];
full.extend_from_slice(args);
full.push("/tmp/chart");
Cli::try_parse_from(full).map_err(|e| e.to_string())
}
#[test]
fn cli_diag_format_text_is_default() {
let cli = parse(&[]).expect("parse");
sim_assert_eq!(have: cli.diag.diag_format, want: DiagFormat::Text);
}
#[test]
fn cli_perf_flags_parse() {
let cli = parse(&["--trace-output", "/tmp/helm-schema.trace"]).expect("parse");
sim_assert_eq!(
have: cli.perf.trace_output.as_deref(),
want: Some(std::path::Path::new("/tmp/helm-schema.trace"))
);
}
#[test]
fn cli_output_minimize_defaults_on_with_opt_out() {
let cli = parse(&[]).expect("parse");
assert!(
cli.output.minimize,
"interning is the default output policy"
);
let cli = parse(&["--no-minimize"]).expect("parse");
assert!(!cli.output.minimize);
}
#[test]
fn cli_output_strip_descriptions_flag_parses() {
let cli = parse(&["--strip-descriptions"]).expect("parse");
assert!(cli.output.strip_descriptions);
}
#[test]
fn cli_output_inline_refs_flag_parses() {
let cli = parse(&["--inline-refs"]).expect("parse");
assert!(cli.output.inline_refs);
}
#[test]
fn cli_output_ref_modes_conflict() {
let err = parse(&["--keep-refs", "--inline-refs"]).expect_err("expected clap conflict");
assert!(err.contains("--keep-refs") || err.contains("--inline-refs"));
}
#[test]
fn cli_values_files_flag_is_repeatable() {
let cli = parse(&["-f", "/tmp/base.yaml", "--values", "/tmp/override.yaml"]).expect("parse");
sim_assert_eq!(
have: cli.chart.values_files,
want: vec![
std::path::PathBuf::from("/tmp/base.yaml"),
std::path::PathBuf::from("/tmp/override.yaml")
]
);
}
#[test]
fn cli_repeated_k8s_version_preserves_order() {
let cli = parse(&["--k8s-version", "v1.24.0", "--k8s-version", "v1.35.0"]).expect("parse");
sim_assert_eq!(
have: cli.k8s.k8s_version,
want: vec!["v1.24.0".to_string(), "v1.35.0".to_string()]
);
}
#[test]
fn cli_rejects_auto_with_multiple_explicit_versions() {
let cli = parse(&[
"--k8s-version",
"v1.35.0",
"--k8s-version",
"v1.30.0",
"--k8s-version-fallback=auto",
])
.expect("parse should succeed");
assert!(
cli.k8s.resolved_fallback_window().is_err(),
"--k8s-version-fallback=auto + multiple --k8s-version must be rejected"
);
}
#[test]
fn cli_strict_and_heuristic_flags_conflict() {
let err = parse(&["--strict-k8s-version", "--k8s-version-fallback=auto"])
.expect_err("expected clap conflict");
assert!(err.contains("--k8s-version-fallback") || err.contains("strict_k8s_version"));
let err = parse(&["--strict-api-versions", "--api-version-guess"])
.expect_err("expected clap conflict");
assert!(err.contains("--api-version-guess") || err.contains("strict_api_versions"));
}
#[test]
fn k8s_strict_does_not_conflict_with_mirror_flag() {
let cli = parse(&[
"--strict-k8s-version",
"--k8s-schema-mirror",
"https://example/",
])
.expect("strict + mirror must be accepted at parse time");
assert!(cli.k8s.strict_k8s_version);
sim_assert_eq!(
have: cli.k8s.k8s_schema_mirror,
want: vec!["https://example/".to_string()]
);
}
#[test]
fn crd_strict_does_not_conflict_with_mirror_flag() {
let cli = parse(&[
"--strict-crd-version",
"--crd-catalog-mirror",
"https://example/",
])
.expect("strict + mirror must be accepted at parse time");
assert!(cli.crd.strict_crd_version);
sim_assert_eq!(
have: cli.crd.crd_catalog_mirror,
want: vec!["https://example/".to_string()]
);
sim_assert_eq!(have: cli.crd.lookup_mode(), want: CrdVersionLookup::Strict);
}
#[test]
fn cli_rejects_removed_crd_catalog_dir_flag() {
let cli = parse(&["--crd-catalog-dir", "/some/path"]).expect("parse");
let err = cli.crd.validate().expect_err("removed flag must error");
assert!(err.contains("--crd-catalog-dir is removed"));
assert!(err.contains("--crd-override-dir"));
assert!(err.contains("--crd-catalog-cache-dir"));
}
#[test]
fn cli_rejects_override_and_cache_dir_same_path() {
let cli = parse(&[
"--crd-override-dir",
"/foo",
"--crd-catalog-cache-dir",
"/foo",
])
.expect("parse");
let err = cli.crd.validate().expect_err("same path must error");
assert!(err.contains("must point at different paths"));
}
#[test]
fn k8s_strict_collapses_chain_to_explicit_versions() {
let cli = parse(&["--strict-k8s-version", "--k8s-version", "v1.35.0"]).expect("parse");
let window = cli.k8s.resolved_fallback_window().expect("resolve");
sim_assert_eq!(have: window, want: None, "strict mode must disable auto-fallback");
}
#[test]
fn k8s_version_fallback_auto_resolves_to_default_window() {
let cli = parse(&["--k8s-version-fallback=auto"]).expect("parse");
let window = cli.k8s.resolved_fallback_window().expect("resolve");
sim_assert_eq!(have: window, want: Some(helm_schema_cli::cli::DEFAULT_AUTO_WINDOW));
sim_assert_eq!(have: cli.k8s.k8s_version_fallback, want: Some(K8sVersionFallback::Auto));
}
#[test]
fn k8s_auto_fallback_default_reaches_v1_24_from_v1_35() {
let cli = parse(&["--k8s-version-fallback=auto"]).expect("parse");
let window = cli.k8s.resolved_fallback_window().expect("resolve");
let versions =
helm_schema::provider::K8sVersionChain::new(cli.k8s.k8s_version.clone(), window).ordered();
assert!(
versions.contains(&"v1.24.0".to_string()),
"auto window must reach v1.24.0 from default v1.35.0; got {versions:?}"
);
}
#[test]
fn k8s_version_fallback_explicit_window() {
let cli = parse(&["--k8s-version-fallback=3"]).expect("parse");
let window = cli.k8s.resolved_fallback_window().expect("resolve");
sim_assert_eq!(have: window, want: Some(3));
}
#[test]
fn k8s_version_fallback_zero_means_disabled() {
let cli = parse(&["--k8s-version-fallback=0"]).expect("parse");
let window = cli.k8s.resolved_fallback_window().expect("resolve");
sim_assert_eq!(have: window, want: None);
}