use anyhow::Result; use assert_cmd::cargo::cargo_bin; use rexpect::session::{spawn_command, PtySession}; use shackle_shell::user_info::{get_user_groups, get_username}; use std::path::PathBuf; use tempfile::TempDir; pub struct TestContext { pub p: PtySession, pub workdir: TempDir, } impl TestContext { pub fn new_interactive() -> 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 p = spawn_command(command, Some(3000))?; let mut c = TestContext { p, workdir }; c.expect_prompt()?; Ok(c) } pub fn new_batch(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 }) } pub fn personal_repo_dir(&self, repo_name: &str) -> PathBuf { let username = get_username().unwrap(); self.workdir .as_ref() .join("git") .join(username) .join(&format!("{}.git", repo_name)) } pub fn group_repo_dir(&self, group: &str, repo_name: &str) -> PathBuf { self.workdir .as_ref() .join("git") .join(group) .join(&format!("{}.git", repo_name)) } pub fn expect_prompt(&mut self) -> Result<()> { self.p.exp_string("> ")?; Ok(()) } pub fn expect_successful_init_message(&mut self, repo_path: &str) -> Result<()> { self.p .exp_string(&format!("Successfully created \"{repo_path}\""))?; self.expect_prompt() } pub fn expect_list_table(&mut self, repos: &[(&str, &str)]) -> Result<()> { self.p.send_line("list")?; self.p.exp_regex(r"\+-+\+-+\+")?; self.p.exp_regex(r"\| path +\| description +\|")?; self.p.exp_regex(r"\+=+\+")?; for (path, description) in repos { self.p.exp_string("| ")?; self.p.exp_string(path)?; self.p.exp_regex(r" +\| ")?; self.p.exp_string(&description)?; self.p.exp_regex(r" +\|")?; } self.p.exp_regex(r"\+-+\+-+\+")?; self.expect_prompt()?; Ok(()) } pub fn expect_list_table_verbose(&mut self, repos: &[(&str, &str)]) -> Result<()> { self.p.send_line("list --verbose")?; self.p.exp_regex(r"\+-+\+-+\+-+\+")?; self.p.exp_regex(r"\| path +\| description +\| size +\|")?; self.p.exp_regex(r"\+=+\+")?; for (path, description) in repos { self.p.exp_string("| ")?; self.p.exp_string(path)?; self.p.exp_regex(r" +\| ")?; self.p.exp_string(&description)?; self.p.exp_regex(r" +\|")?; self.p.exp_regex(r"\d+ (MiB|KiB|B)")?; self.p.exp_regex(r" +\|")?; } self.p.exp_regex(r"\+-+\+-+\+-+\+")?; self.expect_prompt()?; Ok(()) } } pub fn personal_repo_path(repo_name: &str) -> String { let username = get_username().unwrap(); format!("git/{username}/{repo_name}.git") } pub fn arbitrary_user_group() -> String { get_user_groups().into_iter().next().unwrap() } pub fn group_repo_path(group: &str, repo_name: &str) -> String { format!("git/{group}/{repo_name}.git") }