use crate::cli::history::output_format::OutputFormatArgs;
use crate::cli::history::range::HistoryRangeArgs;
use clap::Args;
use greed::asset::AssetSymbol;
#[derive(Args, Debug)]
pub struct QuoteHistoryArgs {
#[arg(value_name = "SYMBOLS")]
pub symbols: Vec<AssetSymbol>,
#[command(flatten)]
pub history_range: HistoryRangeArgs,
#[command(flatten)]
pub output_format: OutputFormatArgs,
}
#[cfg(test)]
mod test {
use crate::cli::Cli;
use clap::Parser;
use greed::asset::AssetSymbol;
use greed::output_format::OutputFormat;
#[test]
fn parses_with_no_symbols_defaults_to_empty_filter() {
let cli = Cli::try_parse_from(["greed", "history", "quote-history"])
.expect("should parse with no symbols");
let crate::cli::Command::History(history_args) = cli.command else {
panic!("expected History command");
};
let crate::cli::history::HistoryCommand::QuoteHistory(args) = history_args.command else {
panic!("expected QuoteHistory subcommand");
};
assert_eq!(args.symbols, Vec::<AssetSymbol>::new());
assert!(args.history_range.days.is_none());
}
#[test]
fn parses_multiple_positional_symbols_before_range_flags() {
let cli = Cli::try_parse_from([
"greed",
"history",
"quote-history",
"VTI",
"AAPL",
"--days",
"3",
])
.expect("should parse with symbols and a range flag");
let crate::cli::Command::History(history_args) = cli.command else {
panic!("expected History command");
};
let crate::cli::history::HistoryCommand::QuoteHistory(args) = history_args.command else {
panic!("expected QuoteHistory subcommand");
};
assert_eq!(
args.symbols,
vec![AssetSymbol::new("VTI"), AssetSymbol::new("AAPL")]
);
assert_eq!(args.history_range.days, Some(3));
}
#[test]
fn rejects_combining_days_and_last_hour() {
let result = Cli::try_parse_from([
"greed",
"history",
"quote-history",
"--days",
"3",
"--last-hour",
]);
assert!(result.is_err());
}
#[test]
fn defaults_to_text_when_format_omitted() {
let cli = Cli::try_parse_from(["greed", "history", "quote-history"])
.expect("should parse with no format flag");
let crate::cli::Command::History(history_args) = cli.command else {
panic!("expected History command");
};
let crate::cli::history::HistoryCommand::QuoteHistory(args) = history_args.command else {
panic!("expected QuoteHistory subcommand");
};
assert_eq!(args.output_format.format, OutputFormat::Text);
}
#[test]
fn parses_explicit_json_format() {
let cli = Cli::try_parse_from(["greed", "history", "quote-history", "--format", "json"])
.expect("should parse with an explicit json format");
let crate::cli::Command::History(history_args) = cli.command else {
panic!("expected History command");
};
let crate::cli::history::HistoryCommand::QuoteHistory(args) = history_args.command else {
panic!("expected QuoteHistory subcommand");
};
assert_eq!(args.output_format.format, OutputFormat::Json);
}
#[test]
fn rejects_invalid_format_value() {
let result =
Cli::try_parse_from(["greed", "history", "quote-history", "--format", "bogus"]);
assert!(result.is_err());
}
}