malvin 0.2.6

Non-interactive research and coding agent
use super::{Commands, Exit, entrypoint_from};

fn git_flag_is_rejected_by_clap() {
    use clap::Parser;
    let err = crate::cli::Cli::try_parse_from(["malvin", "--git", "--doc"])
        .expect_err("--git must be rejected");
    let msg = err.to_string();
    assert!(
        msg.contains("unexpected") || msg.contains("unknown") || msg.contains("--git"),
        "clap must reject --git; got {msg}"
    );
}

fn help_omits_git_flag() {
    use clap::CommandFactory;
    let help = crate::cli::Cli::command().render_help().to_string();
    assert!(!help.contains("--git"), "help={help}");
}

fn shared_opts_parses_creative_flag_default_off() {
    use clap::Parser;
    let cli = crate::cli::Cli::try_parse_from(["malvin", "--doc"]).expect("parse");
    assert!(cli.router.creative.is_none());
}

fn shared_opts_parses_creative_flag_on() {
    use clap::Parser;
    let cli = crate::cli::Cli::try_parse_from(["malvin", "--creative", "--doc"]).expect("parse");
    assert_eq!(cli.router.creative, Some(1.0));
}

fn help_lists_creative_flag() {
    use clap::CommandFactory;
    let help = crate::cli::Cli::command().render_help().to_string();
    assert!(help.contains("--creative"), "help={help}");
}

fn shared_opts_parses_no_kpop_flag_default_off() {
    use clap::Parser;
    let cli = crate::cli::Cli::try_parse_from(["malvin", "--doc"]).expect("parse");
    assert!(!cli.router.no_kpop);
}

fn shared_opts_parses_no_kpop_flag_on() {
    use clap::Parser;
    let cli = crate::cli::Cli::try_parse_from(["malvin", "--no-kpop", "--doc"]).expect("parse");
    assert!(cli.router.no_kpop);
}

fn help_hides_no_kpop_flag() {
    use clap::CommandFactory;
    let help = crate::cli::Cli::command().render_help().to_string();
    assert!(
        !help.contains("--no-kpop"),
        "hidden --no-kpop must not appear in help: {help}"
    );
}

fn help_omits_name_flag() {
    use clap::CommandFactory;
    let help = crate::cli::Cli::command().render_help().to_string();
    assert!(
        !help.contains("--name"),
        "help must not list removed --name: {help}"
    );
}

fn doc_does_not_create_name_files() {
    crate::test_utils::with_isolated_home(|work| {
        let _ = work;
        let root = crate::names_registry_root();
        assert_eq!(entrypoint_from(["malvin", "--doc"]), Exit::Success);
        assert!(
            !root.exists()
                || std::fs::read_dir(&root)
                    .expect("read names")
                    .next()
                    .is_none(),
            "doc must not create name files"
        );
    });
}

fn bare_help_does_not_create_name_files() {
    crate::test_utils::with_isolated_home(|work| {
        let _ = work;
        let root = crate::names_registry_root();
        assert_eq!(entrypoint_from(["malvin"]), Exit::Success);
        assert!(
            !root.exists()
                || std::fs::read_dir(&root)
                    .expect("read names")
                    .next()
                    .is_none(),
            "bare help must not create name files"
        );
    });
}

fn do_workflow_parses_without_name_flag() {
    use crate::cli::config_defaults::parse_cli_with_config_defaults;

    crate::test_utils::with_isolated_home(|_| {
        let (cli, _) =
            parse_cli_with_config_defaults(["malvin", "--do", "say hello"]).expect("parse --do");
        assert!(cli.do_workflow);
        assert_eq!(cli.request.as_deref(), Some("say hello"));
        assert!(cli.command.is_none());
    });
}

fn gates_only_route_needs_session() {
    use clap::Parser;
    assert!(crate::cli::config_defaults::is_gates_only_route(
        &crate::cli::Cli::try_parse_from(["malvin", "-g"]).expect("parse")
    ));
}

fn admin_command_is_not_gates_only() {
    use crate::cli::{AdminArgs, AdminCommand};
    use crate::cli::models_cmd::ModelsArgs;
    let _ = Commands::Admin(AdminArgs {
        command: AdminCommand::Models(ModelsArgs::default()),
    });
}

fn name_flag_is_rejected_by_clap() {
    use clap::Parser;
    let err = crate::cli::Cli::try_parse_from(["malvin", "--name", "probe", "--doc"])
        .expect_err("--name must be unknown");
    let msg = err.to_string();
    assert!(
        msg.contains("unexpected") || msg.contains("unknown") || msg.contains("--name"),
        "clap must reject --name; got: {msg}"
    );
}

#[test]
fn kiss_bundled_cli_entrypoint_name_tests() {
    git_flag_is_rejected_by_clap();
    help_omits_git_flag();
    shared_opts_parses_creative_flag_default_off();
    shared_opts_parses_creative_flag_on();
    help_lists_creative_flag();
    shared_opts_parses_no_kpop_flag_default_off();
    shared_opts_parses_no_kpop_flag_on();
    help_hides_no_kpop_flag();
    help_omits_name_flag();
    doc_does_not_create_name_files();
    bare_help_does_not_create_name_files();
    do_workflow_parses_without_name_flag();
    gates_only_route_needs_session();
    admin_command_is_not_gates_only();
    name_flag_is_rejected_by_clap();
}