nils-api-testing-core 0.7.3

Library crate for nils-api-testing-core in the nils-cli workspace.
Documentation
use std::path::Path;

use api_testing_core::cli_util;
use pretty_assertions::assert_eq;
use tempfile::TempDir;

fn write_file(path: &Path, contents: &str) {
    std::fs::create_dir_all(path.parent().expect("parent")).expect("mkdir");
    std::fs::write(path, contents).expect("write");
}

#[test]
fn bool_from_env_parses_and_warns_with_label() {
    let mut stderr: Vec<u8> = Vec::new();
    let stderr_writer: &mut dyn std::io::Write = &mut stderr;
    let got = cli_util::bool_from_env(
        Some("true".to_string()),
        "GQL_FOO",
        false,
        Some("api-gql"),
        stderr_writer,
    );
    assert_eq!(got, true);

    let mut stderr: Vec<u8> = Vec::new();
    let stderr_writer: &mut dyn std::io::Write = &mut stderr;
    let got = cli_util::bool_from_env(
        Some("nope".to_string()),
        "GQL_FOO",
        true,
        Some("api-gql"),
        stderr_writer,
    );
    assert_eq!(got, false);
    let msg = String::from_utf8_lossy(&stderr);
    assert!(msg.contains("api-gql: warning: GQL_FOO must be true|false"));
    assert!(msg.contains("nope"));
}

#[test]
fn bool_from_env_parses_and_warns_without_label() {
    let mut warnings: Vec<String> = Vec::new();
    let got = cli_util::bool_from_env(
        Some("nope".to_string()),
        "REST_FOO",
        true,
        None,
        &mut warnings,
    );
    assert_eq!(got, false);
    assert_eq!(warnings.len(), 1);
    assert!(warnings[0].contains("REST_FOO must be true|false"));
    assert!(!warnings[0].contains("warning:"));
}

#[test]
fn bool_from_env_uses_default_on_empty() {
    let mut stderr: Vec<u8> = Vec::new();
    let stderr_writer: &mut dyn std::io::Write = &mut stderr;
    let got = cli_util::bool_from_env(
        Some("".to_string()),
        "REST_FOO",
        true,
        Some("api-rest"),
        stderr_writer,
    );
    assert_eq!(got, true);
    assert!(stderr.is_empty());
}

#[test]
fn parse_u64_default_enforces_min() {
    assert_eq!(cli_util::parse_u64_default(Some("".to_string()), 10, 1), 10);
    assert_eq!(
        cli_util::parse_u64_default(Some("abc".to_string()), 10, 1),
        10
    );
    assert_eq!(cli_util::parse_u64_default(Some("0".to_string()), 10, 1), 1);
    assert_eq!(
        cli_util::parse_u64_default(Some("10".to_string()), 5, 1),
        10
    );
}

#[test]
fn to_env_key_and_slugify_normalize() {
    assert_eq!(cli_util::to_env_key("prod-us"), "PROD_US");
    assert_eq!(cli_util::to_env_key("  foo@@bar  "), "FOO_BAR");
    assert_eq!(cli_util::slugify("Hello, world!"), "hello-world");
    assert_eq!(cli_util::slugify("  ___ "), "");
}

#[test]
fn maybe_relpath_and_shell_quote() {
    let tmp = TempDir::new().unwrap();
    let root = tmp.path();
    assert_eq!(cli_util::maybe_relpath(root, root), ".");

    let child = root.join("a/b");
    std::fs::create_dir_all(&child).unwrap();
    assert_eq!(cli_util::maybe_relpath(&child, root), "a/b");

    assert_eq!(cli_util::shell_quote(""), "''");
    assert_eq!(cli_util::shell_quote("a'b"), "'a'\\''b'");
}

#[test]
fn list_available_suffixes_parses_and_sorts() {
    let tmp = TempDir::new().unwrap();
    let file = tmp.path().join("endpoints.env");
    write_file(
        &file,
        "export REST_URL_PROD=http://prod\nREST_URL_DEV=http://dev\nREST_URL_=bad\nREST_URL_FOO-BAR=http://x\nREST_URL_TEST=http://t\nREST_URL_TEST=http://t2\n",
    );

    let suffixes = cli_util::list_available_suffixes(&file, "REST_URL_");
    assert_eq!(suffixes, vec!["dev", "prod", "test"]);
}

#[test]
fn report_dates_are_formatted() {
    let stamp = cli_util::report_stamp_now().unwrap();
    assert_eq!(stamp.len(), 13, "stamp={stamp}");

    let date = cli_util::report_date_now().unwrap();
    assert_eq!(date.len(), 10, "date={date}");
    assert!(date.contains('-'));
}

#[test]
fn history_timestamp_is_not_empty() {
    let stamp = cli_util::history_timestamp_now().unwrap();
    assert!(!stamp.is_empty());
    assert!(stamp.contains('T'));
}