//! The terminal command line is a thin parser over `Command`. //! //! Anything the core can do on its own becomes `Shell::Run`; connecting, //! prompting for credentials and host maintenance stay with the adapter. use zagan_bet::client::shell::{Shell, parse}; use zagan_bet::client::view::Command; use zagan_bet::history::{DEFAULT_HISTORY, MAX_HISTORY}; fn run(line: &str) -> Command { match parse(line) { Shell::Run(command) => command, other => panic!("expected a command, got {other:?}"), } } #[test] fn blank_lines_do_nothing() { assert_eq!(parse(""), Shell::Empty); assert_eq!(parse(" \t "), Shell::Empty); } #[test] fn play_without_a_game_prints_usage() { assert_eq!( parse("play"), Shell::Usage("Usage: play [bet]".to_string()) ); } #[test] fn play_carries_the_game_and_an_optional_bet() { assert_eq!( run("play slots"), Command::Play { game: "slots".to_string(), bet: None, } ); assert_eq!( run("play roulette 25"), Command::Play { game: "roulette".to_string(), bet: Some(25), } ); } #[test] fn play_rejects_a_bet_below_the_table_minimum() { assert_eq!( parse("play slots 5"), Shell::Usage("Bet must be at least 10 Kr".to_string()) ); assert_eq!( parse("play slots ten"), Shell::Usage("Invalid bet: ten".to_string()) ); } #[test] fn history_defaults_to_the_recent_limit() { let expected = Command::History { limit: DEFAULT_HISTORY, }; assert_eq!(run("history"), expected); assert_eq!(run("history 5"), Command::History { limit: 5 }); } #[test] fn history_rejects_counts_outside_the_range() { let usage = Shell::Usage(format!("Usage: history [1-{MAX_HISTORY}]")); assert_eq!(parse("history 0"), usage); assert_eq!(parse(&format!("history {}", MAX_HISTORY + 1)), usage); assert_eq!(parse("history many"), usage); } #[test] fn simple_commands_are_pure_core_commands() { assert_eq!(run("games"), Command::Games); assert_eq!(run("logout"), Command::Logout); assert_eq!(run("ping"), Command::Ping); assert_eq!(run("info"), Command::Info); } #[test] fn send_keeps_the_whole_message_including_extra_spaces() { assert_eq!( run("send hello there friend"), Command::Echo("hello there friend".to_string()) ); assert_eq!( parse("send"), Shell::Usage("Usage: send ".to_string()) ); } #[test] fn connection_flows_stay_with_the_adapter() { assert_eq!(parse("connect"), Shell::Connect(None)); assert_eq!( parse("connect 127.0.0.1:11525"), Shell::Connect(Some("127.0.0.1:11525".to_string())) ); assert_eq!(parse("login"), Shell::Login); assert_eq!(parse("register"), Shell::Register); assert_eq!(parse("setcred"), Shell::SetCred); assert_eq!(parse("disconnect"), Shell::Disconnect); } #[test] fn host_maintenance_is_adapter_owned() { assert_eq!(parse("hosts"), Shell::Hosts); assert_eq!(parse("forget-host"), Shell::ForgetHost(None)); assert_eq!( parse("forget-host 10.0.0.2:11525"), Shell::ForgetHost(Some("10.0.0.2:11525".to_string())) ); } #[test] fn forgetting_a_saved_login_is_separate_from_forgetting_trust() { assert_eq!(parse("forget-login"), Shell::ForgetLogin(None)); assert_eq!( parse("forget-login 10.0.0.2:11525"), Shell::ForgetLogin(Some("10.0.0.2:11525".to_string())) ); } #[test] fn help_and_quit_are_terminal_only() { assert_eq!(parse("help"), Shell::Help); assert_eq!(parse("quit"), Shell::Quit); } #[test] fn an_unknown_word_falls_back_to_help() { assert_eq!(parse("frobnicate"), Shell::Help); assert_eq!(parse("quit now"), Shell::Quit); } #[test] fn surrounding_whitespace_is_ignored() { assert_eq!(run(" ping "), Command::Ping); assert_eq!( run(" play slots 30 "), Command::Play { game: "slots".to_string(), bet: Some(30), } ); }