use anyhow::Result; use assert_cmd::{cargo::cargo_bin, Command}; use rexpect::session::{spawn_command, PtySession}; use tempfile::TempDir; use user_info::get_username; struct TestContext { p: PtySession, workdir: TempDir, } fn spawn_interactive_process() -> Result { let workdir = tempfile::tempdir()?; let path = cargo_bin(env!("CARGO_PKG_NAME")); let mut command = std::process::Command::new(&path); command.current_dir(&workdir); let mut p = spawn_command(command, Some(3000))?; expect_prompt(&mut p)?; Ok(TestContext { p, workdir }) } fn run_batch_command(batch_command: &str) -> Result { let workdir = tempfile::tempdir()?; let path = cargo_bin(env!("CARGO_PKG_NAME")); let mut command = std::process::Command::new(&path); command.current_dir(&workdir); command.args(["-c", batch_command]); let p = spawn_command(command, Some(3000))?; Ok(TestContext { p, workdir }) } fn expect_prompt(p: &mut PtySession) -> Result<()> { p.exp_string("> ")?; Ok(()) } #[test] fn shows_a_prompt() -> Result<()> { spawn_interactive_process()?; Ok(()) } #[test] fn does_nothing_after_receiving_whitespace_input() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line("")?; expect_prompt(&mut c.p)?; c.p.send_line(" ")?; expect_prompt(&mut c.p)?; Ok(()) } #[test] fn quits_when_eof_is_sent() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_control('d')?; c.p.exp_eof()?; Ok(()) } #[test] fn quits_when_exit_command_is_sent() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line("exit")?; c.p.exp_eof()?; Ok(()) } #[test] fn reports_error_with_unsupported_shell_commands() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line("ls")?; c.p.exp_string("error: unrecognized subcommand 'ls'")?; expect_prompt(&mut c.p)?; Ok(()) } #[test] fn reports_error_with_nonsense_input() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line(" asd fg ")?; c.p.exp_string("error: unrecognized subcommand 'asd'")?; expect_prompt(&mut c.p)?; Ok(()) } #[test] fn can_init_a_new_git_repo() -> Result<()> { let mut c = spawn_interactive_process()?; let username = get_username().unwrap(); let repo_name = "my-new-repo"; c.p.send_line(&format!("git-init {}", repo_name))?; c.p.exp_string(&format!( "Successfully created \"git/{}/{}.git\"", username, repo_name ))?; expect_prompt(&mut c.p)?; Command::new("git") .arg("rev-list") .arg("--all") .current_dir( c.workdir .as_ref() .join("git") .join(username) .join("my-new-repo.git"), ) .assert() .success() .stdout(""); Ok(()) } #[test] fn runs_a_single_command_and_exit_with_cli_flag() -> Result<()> { let username = get_username().unwrap(); let repo_name = "another-new-repo"; let mut c = run_batch_command(&format!("git-init {}", repo_name))?; c.p.exp_string(&format!( "Successfully created \"git/{}/{}.git\"", username, repo_name ))?; c.p.exp_eof()?; Ok(()) } #[test] fn allows_quotes_arguments() -> Result<()> { let username = get_username().unwrap(); let mut c = spawn_interactive_process()?; c.p.send_line("\"git-init\" 'another-new-repo'")?; c.p.exp_string(&format!( "Successfully created \"git/{}/another-new-repo.git\"", username ))?; Ok(()) } #[test] fn errors_with_an_open_double_quote() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line("\"git-init 'another-new-repo'")?; c.p.exp_string("Incomplete input")?; Ok(()) } #[test] fn errors_with_an_open_single_quote() -> Result<()> { let mut c = spawn_interactive_process()?; c.p.send_line("'git-init 'another-new-repo'")?; c.p.exp_string("Incomplete input")?; Ok(()) } #[test] fn allows_single_quotes_and_spaces_inside_double_quotes() -> Result<()> { let username = get_username().unwrap(); let mut c = spawn_interactive_process()?; c.p.send_line("git-init \"shukkie's new repo\"")?; c.p.exp_string(&format!( "Successfully created \"git/{}/shukkie's new repo.git\"", username ))?; Ok(()) }