src/cli/args_test.rs

#[cfg(test)]
mod tests {
    use clap::Parser;

    use crate::cli::args::{Cli, Command, Shell};

    #[test]
    fn tail_parses_basic_paths() {
        let cli = Cli::parse_from(["ripgrab", "tail", "a.log", "b.log"]);
        match cli.command {
            Command::Tail(args) => {
                assert_eq!(args.paths.len(), 2);
                assert_eq!(args.from_end, 0);
                assert!(!args.no_origin);
            }
            _ => panic!("expected tail"),
        }
    }

    #[test]
    fn tail_includes_and_excludes_are_repeatable() {
        let cli = Cli::parse_from([
            "ripgrab", "tail", "a.log",
            "-i", "error", "-i", "warn",
            "-e", "heartbeat",
        ]);
        let Command::Tail(args) = cli.command else { panic!() };
        assert_eq!(args.includes, vec!["error", "warn"]);
        assert_eq!(args.excludes, vec!["heartbeat"]);
    }

    #[test]
    fn tail_where_clause_captured() {
        let cli = Cli::parse_from([
            "ripgrab", "tail", "a.log", "--where", "status >= 400",
        ]);
        let Command::Tail(args) = cli.command else { panic!() };
        assert_eq!(args.where_clause.as_deref(), Some("status >= 400"));
    }

    #[test]
    fn grep_requires_paths() {
        let err = Cli::try_parse_from(["ripgrab", "grep"]).unwrap_err();
        assert_eq!(err.kind(), clap::error::ErrorKind::MissingRequiredArgument);
    }

    #[test]
    fn json_pretty_flag() {
        let cli = Cli::parse_from(["ripgrab", "json", "a.log", "--pretty"]);
        let Command::Json(args) = cli.command else { panic!() };
        assert!(args.pretty);
    }

    #[test]
    fn completions_parses_shell() {
        let cli = Cli::parse_from(["ripgrab", "completions", "zsh"]);
        let Command::Completions(args) = cli.command else { panic!() };
        assert!(matches!(args.shell, Shell::Zsh));
    }

    #[test]
    fn unknown_command_rejected() {
        assert!(Cli::try_parse_from(["ripgrab", "blorp"]).is_err());
    }
}