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<TestContext> {
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<TestContext> {
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<()> {
let mut repos = Vec::from(repos);
repos.sort_unstable_by_key(|r| r.0);
self.p.send_line("list")?;
self.p.exp_regex(r"\+-+\+-+\+\r\n")?;
self.p.exp_regex(r"^\| path +\| description +\|\r\n")?;
self.p.exp_regex(r"^\+=+\+\r\n")?;
for (path, description) in repos {
assert_eq!("", self.p.exp_string("| ")?);
assert_eq!("", self.p.exp_string(path)?);
self.p.exp_regex(r"^ +\| ")?;
assert_eq!("", self.p.exp_string(&description)?);
self.p.exp_regex(r"^ +\|\r\n")?;
self.p.exp_regex(r"^[|\+]-+\+-+[|\+]\r\n")?;
}
self.expect_prompt()?;
Ok(())
}
pub fn expect_list_table_verbose(&mut self, repos: &[(&str, &str)]) -> Result<()> {
let mut repos = Vec::from(repos);
repos.sort_unstable_by_key(|r| r.0);
self.p.send_line("list --verbose")?;
self.p.exp_regex(r"\+-+\+-+\+-+\+\r\n")?;
self.p
.exp_regex(r"^\| path +\| description +\| size +\|\r\n")?;
self.p.exp_regex(r"^\+=+\+\r\n")?;
for (path, description) in repos {
assert_eq!("", self.p.exp_string("| ")?);
assert_eq!("", self.p.exp_string(path)?);
self.p.exp_regex(r"^ +\| ")?;
assert_eq!("", self.p.exp_string(&description)?);
self.p.exp_regex(r"^ +\| ")?;
self.p.exp_regex(r"^\d+(\.\d+)? (MiB|KiB|B)")?;
self.p.exp_regex(r"^ +\|\r\n")?;
self.p.exp_regex(r"^[|\+]-+\+-+\+-+[|\+]\r\n")?;
}
self.expect_prompt()?;
Ok(())
}
}
pub fn arbitrary_user_group() -> String {
get_user_groups().into_iter().next().unwrap()
}
pub fn personal_repo_path(repo_name: &str) -> String {
let username = get_username().unwrap();
format!("git/{username}/{repo_name}.git")
}
pub fn group_repo_path(group: &str, repo_name: &str) -> String {
format!("git/{group}/{repo_name}.git")
}