summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2023-07-06 15:22:44 +0200
committerJustin Wernick <justin@worthe-it.co.za>2023-07-06 15:22:44 +0200
commit84be3c9ae7a1b6a86f3a4ccc58e48eab46466b22 (patch)
tree98aa8b470d31dab4d0c93f6887602391a67f505e /tests
parente18a928db5916fce43c35dff585072dace0da7e0 (diff)
Move test helper functions into their own helper module
Diffstat (limited to 'tests')
-rw-r--r--tests/cli.rs239
-rw-r--r--tests/cli_test_utils/context.rs114
-rw-r--r--tests/cli_test_utils/git.rs41
-rw-r--r--tests/cli_test_utils/mod.rs5
4 files changed, 200 insertions, 199 deletions
diff --git a/tests/cli.rs b/tests/cli.rs
index dbe99b2..b8ada66 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -1,94 +1,22 @@
+mod cli_test_utils;
+
use anyhow::Result;
-use assert_cmd::{cargo::cargo_bin, Command};
-use rexpect::session::{spawn_command, PtySession};
-use shackle_shell::user_info::{get_user_groups, get_username};
-use std::path::{Path, PathBuf};
-use tempfile::TempDir;
+use cli_test_utils::*;
const REPO_NAME: &str = "my-repository";
const REPO_NAME_2: &str = "my-other-repository";
-
-struct TestContext {
- p: PtySession,
- workdir: TempDir,
-}
-
-impl TestContext {
- 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))
- }
-
- fn group_repo_dir(&self, group: &str, repo_name: &str) -> PathBuf {
- self.workdir
- .as_ref()
- .join("git")
- .join(group)
- .join(&format!("{}.git", repo_name))
- }
-
- fn expect_prompt(&mut self) -> Result<()> {
- self.p.exp_string("> ")?;
- Ok(())
- }
-
- fn expect_successful_init_message(&mut self, repo_path: &str) -> Result<()> {
- self.p
- .exp_string(&format!("Successfully created \"{repo_path}\""))?;
- self.expect_prompt()
- }
-}
-
-fn personal_repo_path(repo_name: &str) -> String {
- let username = get_username().unwrap();
- format!("git/{username}/{repo_name}.git")
-}
-
-fn arbitrary_user_group() -> String {
- get_user_groups().into_iter().next().unwrap()
-}
-
-fn group_repo_path(group: &str, repo_name: &str) -> String {
- format!("git/{group}/{repo_name}.git")
-}
-
-fn spawn_interactive_process() -> 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)
-}
-
-fn run_batch_command(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 })
-}
+const DEFAULT_DESCRIPTION: &str =
+ "Unnamed repository; edit this file 'description' to name the repository.";
#[test]
fn shows_a_prompt() -> Result<()> {
- spawn_interactive_process()?;
+ TestContext::new_interactive()?;
Ok(())
}
#[test]
fn does_nothing_after_receiving_whitespace_input() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line("")?;
c.expect_prompt()?;
c.p.send_line(" ")?;
@@ -98,7 +26,7 @@ fn does_nothing_after_receiving_whitespace_input() -> Result<()> {
#[test]
fn quits_when_eof_is_sent() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_control('d')?;
c.p.exp_eof()?;
Ok(())
@@ -106,7 +34,7 @@ fn quits_when_eof_is_sent() -> Result<()> {
#[test]
fn quits_when_exit_command_is_sent() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line("exit")?;
c.p.exp_eof()?;
Ok(())
@@ -114,7 +42,7 @@ fn quits_when_exit_command_is_sent() -> Result<()> {
#[test]
fn reports_error_with_unsupported_shell_commands() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line("ls")?;
c.p.exp_string("error: unrecognized subcommand 'ls'")?;
c.expect_prompt()?;
@@ -123,55 +51,16 @@ fn reports_error_with_unsupported_shell_commands() -> Result<()> {
#[test]
fn reports_error_with_nonsense_input() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(" asd fg ")?;
c.p.exp_string("error: unrecognized subcommand 'asd'")?;
c.expect_prompt()?;
Ok(())
}
-fn verify_repo_exists(repo_dir: &Path) {
- Command::new("git")
- .arg("rev-list")
- .arg("--all")
- .current_dir(repo_dir)
- .assert()
- .success()
- .stdout("");
-}
-
-fn verify_repo_does_not_exist(repo_dir: &Path) {
- assert!(!repo_dir.exists());
-}
-
-fn verify_current_branch(repo_dir: &Path, expected_ref: &str) {
- Command::new("git")
- .arg("symbolic-ref")
- .arg("HEAD")
- .current_dir(repo_dir)
- .assert()
- .success()
- .stdout(format!("{expected_ref}\n"));
-}
-
-fn verify_repo_config_value(repo_dir: &Path, config_key: &str, config_value: Option<&str>) {
- let assert = Command::new("git")
- .args(["config", "--local", config_key])
- .current_dir(repo_dir)
- .assert();
- match config_value {
- Some(value) => {
- assert.success().stdout(format!("{value}\n"));
- }
- None => {
- assert.failure().code(1);
- }
- }
-}
-
#[test]
fn can_init_a_new_git_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("init {}", REPO_NAME))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
@@ -185,7 +74,7 @@ fn can_init_a_new_git_repo() -> Result<()> {
#[test]
fn can_init_a_new_shared_git_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let group = arbitrary_user_group();
c.p.send_line(&format!("init --group {} {}", group, REPO_NAME))?;
c.expect_successful_init_message(&group_repo_path(&group, REPO_NAME))?;
@@ -199,7 +88,7 @@ fn can_init_a_new_shared_git_repo() -> Result<()> {
#[test]
fn does_not_init_shared_repo_if_the_user_isnt_in_the_group() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let group = "not-a-real-group";
c.p.send_line(&format!("init --group {} {}", group, REPO_NAME))?;
c.p.exp_string("Unknown group")?;
@@ -209,7 +98,7 @@ fn does_not_init_shared_repo_if_the_user_isnt_in_the_group() -> Result<()> {
#[test]
fn runs_a_single_command_and_exit_with_cli_flag() -> Result<()> {
- let mut c = run_batch_command(&format!("init {}", REPO_NAME))?;
+ let mut c = TestContext::new_batch(&format!("init {}", REPO_NAME))?;
c.p.exp_string(&format!(
"Successfully created \"{}\"",
personal_repo_path(REPO_NAME)
@@ -220,7 +109,7 @@ fn runs_a_single_command_and_exit_with_cli_flag() -> Result<()> {
#[test]
fn allows_quotes_arguments() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("\"init\" '{REPO_NAME}'"))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
Ok(())
@@ -228,7 +117,7 @@ fn allows_quotes_arguments() -> Result<()> {
#[test]
fn errors_with_an_open_double_quote() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line("\"init 'another-new-repo'")?;
c.p.exp_string("Incomplete input")?;
Ok(())
@@ -236,7 +125,7 @@ fn errors_with_an_open_double_quote() -> Result<()> {
#[test]
fn errors_with_an_open_single_quote() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line("'init 'another-new-repo'")?;
c.p.exp_string("Incomplete input")?;
Ok(())
@@ -245,76 +134,34 @@ fn errors_with_an_open_single_quote() -> Result<()> {
#[test]
fn allows_single_quotes_and_spaces_inside_double_quotes() -> Result<()> {
let repo_name = "shukkie's new repo";
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("init \"{repo_name}\""))?;
c.expect_successful_init_message(&personal_repo_path(repo_name))?;
Ok(())
}
-const DEFAULT_DESCRIPTION: &str =
- "Unnamed repository; edit this file 'description' to name the repository.";
-
-fn expect_list_table(c: &mut TestContext, repos: &[(&str, &str)]) -> Result<()> {
- c.p.send_line("list")?;
- c.p.exp_regex(r"\+-+\+-+\+")?;
- c.p.exp_regex(r"\| path +\| description +\|")?;
- c.p.exp_regex(r"\+=+\+")?;
- for (path, description) in repos {
- c.p.exp_string("| ")?;
- c.p.exp_string(path)?;
- c.p.exp_regex(r" +\| ")?;
- c.p.exp_string(&description)?;
- c.p.exp_regex(r" +\|")?;
- }
- c.p.exp_regex(r"\+-+\+-+\+")?;
- c.expect_prompt()?;
- Ok(())
-}
-
-fn expect_list_table_verbose(c: &mut TestContext, repos: &[(&str, &str)]) -> Result<()> {
- c.p.send_line("list --verbose")?;
- c.p.exp_regex(r"\+-+\+-+\+-+\+")?;
- c.p.exp_regex(r"\| path +\| description +\| size +\|")?;
- c.p.exp_regex(r"\+=+\+")?;
- for (path, description) in repos {
- c.p.exp_string("| ")?;
- c.p.exp_string(path)?;
- c.p.exp_regex(r" +\| ")?;
- c.p.exp_string(&description)?;
- c.p.exp_regex(r" +\|")?;
- c.p.exp_regex(r"\d+ (MiB|KiB|B)")?;
- c.p.exp_regex(r" +\|")?;
- }
- c.p.exp_regex(r"\+-+\+-+\+-+\+")?;
- c.expect_prompt()?;
- Ok(())
-}
-
#[test]
fn list_can_print_an_empty_list() -> Result<()> {
- let mut c = spawn_interactive_process()?;
- expect_list_table(&mut c, &[])?;
+ let mut c = TestContext::new_interactive()?;
+ c.expect_list_table(&[])?;
Ok(())
}
#[test]
fn list_can_print_a_list_of_personal_repos_with_descriptions() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("init {}", REPO_NAME))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
- expect_list_table(
- &mut c,
- &[(&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION)],
- )?;
+ c.expect_list_table(&[(&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION)])?;
Ok(())
}
#[test]
fn list_can_print_a_list_of_all_repos_with_descriptions() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("init {}", REPO_NAME))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
@@ -322,20 +169,17 @@ fn list_can_print_a_list_of_all_repos_with_descriptions() -> Result<()> {
c.p.send_line(&format!("init --group {} {}", group, REPO_NAME_2))?;
c.expect_successful_init_message(&group_repo_path(&group, REPO_NAME_2))?;
- expect_list_table(
- &mut c,
- &[
- (&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION),
- (&group_repo_path(&group, REPO_NAME_2), DEFAULT_DESCRIPTION),
- ],
- )?;
+ c.expect_list_table(&[
+ (&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION),
+ (&group_repo_path(&group, REPO_NAME_2), DEFAULT_DESCRIPTION),
+ ])?;
Ok(())
}
#[test]
fn list_can_print_a_verbose_list_of_all_repos() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
c.p.send_line(&format!("init {}", REPO_NAME))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
@@ -343,32 +187,29 @@ fn list_can_print_a_verbose_list_of_all_repos() -> Result<()> {
c.p.send_line(&format!("init --group {} {}", group, REPO_NAME_2))?;
c.expect_successful_init_message(&group_repo_path(&group, REPO_NAME_2))?;
- expect_list_table_verbose(
- &mut c,
- &[
- (&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION),
- (&group_repo_path(&group, REPO_NAME_2), DEFAULT_DESCRIPTION),
- ],
- )?;
+ c.expect_list_table_verbose(&[
+ (&personal_repo_path(REPO_NAME), DEFAULT_DESCRIPTION),
+ (&group_repo_path(&group, REPO_NAME_2), DEFAULT_DESCRIPTION),
+ ])?;
Ok(())
}
#[test]
fn can_set_the_description_on_a_repo_during_init() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let description = "A cool repo that does cool things";
c.p.send_line(&format!("init --description \"{description}\" {REPO_NAME}"))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
- expect_list_table(&mut c, &[(&personal_repo_path(REPO_NAME), description)])?;
+ c.expect_list_table(&[(&personal_repo_path(REPO_NAME), description)])?;
Ok(())
}
#[test]
fn can_change_the_description_on_a_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let description = "A cool repo that does cool things";
let repo_path = personal_repo_path(REPO_NAME);
c.p.send_line(&format!("init {REPO_NAME}"))?;
@@ -378,14 +219,14 @@ fn can_change_the_description_on_a_repo() -> Result<()> {
))?;
c.p.exp_string("Successfully updated description")?;
c.expect_prompt()?;
- expect_list_table(&mut c, &[(&repo_path, description)])?;
+ c.expect_list_table(&[(&repo_path, description)])?;
Ok(())
}
#[test]
fn can_set_the_main_branch_of_a_new_git_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let main_branch = "foobar";
c.p.send_line(&format!("init --branch {} {}", main_branch, REPO_NAME))?;
c.expect_successful_init_message(&personal_repo_path(REPO_NAME))?;
@@ -398,7 +239,7 @@ fn can_set_the_main_branch_of_a_new_git_repo() -> Result<()> {
#[test]
fn can_change_the_main_branch_on_a_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let main_branch = "foobar";
let repo_path = personal_repo_path(REPO_NAME);
@@ -416,7 +257,7 @@ fn can_change_the_main_branch_on_a_repo() -> Result<()> {
#[test]
fn can_delete_a_repo() -> Result<()> {
- let mut c = spawn_interactive_process()?;
+ let mut c = TestContext::new_interactive()?;
let repo_path = personal_repo_path(REPO_NAME);
let repo_dir = c.personal_repo_dir(REPO_NAME);
diff --git a/tests/cli_test_utils/context.rs b/tests/cli_test_utils/context.rs
new file mode 100644
index 0000000..2517040
--- /dev/null
+++ b/tests/cli_test_utils/context.rs
@@ -0,0 +1,114 @@
+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<()> {
+ 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")
+}
diff --git a/tests/cli_test_utils/git.rs b/tests/cli_test_utils/git.rs
new file mode 100644
index 0000000..d3f35c4
--- /dev/null
+++ b/tests/cli_test_utils/git.rs
@@ -0,0 +1,41 @@
+use assert_cmd::Command;
+use std::path::Path;
+
+pub fn verify_repo_exists(repo_dir: &Path) {
+ Command::new("git")
+ .arg("rev-list")
+ .arg("--all")
+ .current_dir(repo_dir)
+ .assert()
+ .success()
+ .stdout("");
+}
+
+pub fn verify_repo_does_not_exist(repo_dir: &Path) {
+ assert!(!repo_dir.exists());
+}
+
+pub fn verify_current_branch(repo_dir: &Path, expected_ref: &str) {
+ Command::new("git")
+ .arg("symbolic-ref")
+ .arg("HEAD")
+ .current_dir(repo_dir)
+ .assert()
+ .success()
+ .stdout(format!("{expected_ref}\n"));
+}
+
+pub fn verify_repo_config_value(repo_dir: &Path, config_key: &str, config_value: Option<&str>) {
+ let assert = Command::new("git")
+ .args(["config", "--local", config_key])
+ .current_dir(repo_dir)
+ .assert();
+ match config_value {
+ Some(value) => {
+ assert.success().stdout(format!("{value}\n"));
+ }
+ None => {
+ assert.failure().code(1);
+ }
+ }
+}
diff --git a/tests/cli_test_utils/mod.rs b/tests/cli_test_utils/mod.rs
new file mode 100644
index 0000000..7aaf1db
--- /dev/null
+++ b/tests/cli_test_utils/mod.rs
@@ -0,0 +1,5 @@
+pub mod context;
+pub mod git;
+
+pub use context::*;
+pub use git::*;