nvpn 4.0.80

CLI and daemon for Nostr VPN private mesh networks
use clap::{CommandFactory, error::ErrorKind};

use crate::Cli;

#[test]
fn clap_binary_name_is_nvpn() {
    let command = Cli::command();
    assert_eq!(command.get_name(), "nvpn");
}

#[test]
fn clap_supports_root_version_flag() {
    let error = Cli::command()
        .try_get_matches_from(["nvpn", "--version"])
        .expect_err("--version should display version and exit");
    assert_eq!(error.kind(), ErrorKind::DisplayVersion);
    assert!(
        error
            .to_string()
            .contains(&format!("nvpn {}", env!("CARGO_PKG_VERSION"))),
        "version output should include binary name and package version"
    );
}

#[test]
fn clap_includes_tailscale_style_commands() {
    let command = Cli::command();
    for name in [
        "start",
        "stop",
        "repair-network",
        "reload",
        "pause",
        "resume",
        "connect",
        "status",
        "set",
        "ping",
        "doctor",
        "ip",
        "whois",
        "install-cli",
        "uninstall-cli",
        "service",
        "version",
    ] {
        assert!(
            command
                .get_subcommands()
                .any(|subcommand| subcommand.get_name() == name),
            "missing subcommand {name}"
        );
    }
}

#[test]
fn clap_roster_device_commands_keep_participant_aliases() {
    Cli::command()
        .try_get_matches_from(["nvpn", "add-device", "--device", "npub1example"])
        .expect("new device command parses");
    Cli::command()
        .try_get_matches_from(["nvpn", "add-participant", "--participant", "npub1example"])
        .expect("legacy participant command parses");
}

#[test]
fn clap_set_supports_autoconnect_flag() {
    let command = Cli::command();
    let set = command
        .get_subcommands()
        .find(|subcommand| subcommand.get_name() == "set")
        .expect("set subcommand exists");
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("autoconnect")),
        "missing --autoconnect on set command"
    );
}

#[test]
fn clap_set_supports_join_request_listener_flag() {
    let command = Cli::command();
    let set = command
        .get_subcommands()
        .find(|subcommand| subcommand.get_name() == "set")
        .expect("set subcommand exists");
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("join-requests-enabled")),
        "missing --join-requests-enabled on set command"
    );
}

#[test]
fn clap_set_supports_route_advertisement_flags() {
    let command = Cli::command();
    let set = command
        .get_subcommands()
        .find(|subcommand| subcommand.get_name() == "set")
        .expect("set subcommand exists");
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("advertise-routes")),
        "missing --advertise-routes on set command"
    );
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("advertise-exit-node")),
        "missing --advertise-exit-node on set command"
    );
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("exit-node")),
        "missing --exit-node on set command"
    );
    assert!(
        set.get_arguments()
            .any(|argument| argument.get_long() == Some("exit-node-leak-protection")),
        "missing --exit-node-leak-protection on set command"
    );
}

#[test]
fn clap_set_supports_wireguard_exit_flags() {
    let command = Cli::command();
    let set = command
        .get_subcommands()
        .find(|subcommand| subcommand.get_name() == "set")
        .expect("set subcommand exists");
    for flag in [
        "wireguard-exit-enabled",
        "wireguard-exit-address",
        "wireguard-exit-private-key",
        "wireguard-exit-peer-public-key",
        "wireguard-exit-endpoint",
        "wireguard-exit-allowed-ips",
        "wireguard-exit-config",
        "wireguard-exit-config-file",
    ] {
        assert!(
            set.get_arguments()
                .any(|argument| argument.get_long() == Some(flag)),
            "missing --{flag} on set command"
        );
    }
}