diff --git a/.gitignore b/.gitignore
index 958be4e10..963cff618 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,3 @@ Cargo.lock
# Intellij IDE configuration
.idea/
-
-# Cobertura coverage report
-cobertura.xml
diff --git a/README.md b/README.md
index 576f003bb..bae3808f9 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,6 @@
The cross-shell prompt for astronauts.
-
diff --git a/adapters/fish_prompt.fish b/adapters/fish_prompt.fish
index 965398ea1..cd3d77120 100644
--- a/adapters/fish_prompt.fish
+++ b/adapters/fish_prompt.fish
@@ -1,3 +1,3 @@
function fish_prompt
- starship $status
+ starship prompt --status=$status
end
diff --git a/adapters/starship.zsh-theme b/adapters/starship.zsh-theme
index ded509824..0da0bd713 100644
--- a/adapters/starship.zsh-theme
+++ b/adapters/starship.zsh-theme
@@ -1 +1 @@
-PROMPT='$(starship $?)'
+PROMPT='$(starship prompt --status=$?)'
diff --git a/ci/azure-test-docker.yml b/ci/azure-test-docker.yml
index 93b8cfcbf..22df04cb5 100644
--- a/ci/azure-test-docker.yml
+++ b/ci/azure-test-docker.yml
@@ -5,11 +5,11 @@ jobs:
vmImage: ubuntu-16.04
steps:
- - script: ./integration_test
- displayName: Run integration test within Docker
+ - script: docker pull starshipcommand/starship-test
+ displayName: Pull docker image
- - script: bash <(curl -s https://codecov.io/bash) -t $(CODECOV_TOKEN)
- displayName: Report coverage to Codecov
+ - script: ./integration_test
+ displayName: Run integration test suite
- script: |
docker login -u $(dockerUsername) -p $(dockerPassword)
diff --git a/integration_test b/integration_test
index 81c7ba3b2..cf91a2134 100755
--- a/integration_test
+++ b/integration_test
@@ -6,9 +6,6 @@ if ! (docker --version); then
exit 1
fi
-printf 'Pulling latest docker image'
-docker pull starshipcommand/starship-test
-
printf 'Building test docker image:\n'
docker build -f tests/Dockerfile \
--tag starshipcommand/starship-test \
@@ -16,6 +13,4 @@ docker build -f tests/Dockerfile \
.
printf 'Running test suite:\n'
-# `seccomp=unconfined` is needed to allow tarpaulin to disable ASLR
-# Details found here: https://github.com/xd009642/tarpaulin/issues/146
-docker run --rm --security-opt seccomp=unconfined -v $(pwd):/starship starshipcommand/starship-test
+docker run --rm -v $(pwd):/starship starshipcommand/starship-test
diff --git a/src/context.rs b/src/context.rs
index b86bd0708..e0e7e286c 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -15,11 +15,15 @@ pub struct Context<'a> {
impl<'a> Context<'a> {
pub fn new(arguments: ArgMatches) -> Context {
- let current_dir = env::current_dir().expect("Unable to identify current directory.");
- Context::new_with_dir(arguments, current_dir)
+ // Retreive the "path" flag. If unavailable, use the current directory instead.
+ let path = arguments
+ .value_of("path")
+ .map(From::from)
+ .unwrap_or_else(|| env::current_dir().expect("Unable to identify current directory."));
+
+ Context::new_with_dir(arguments, path)
}
- #[allow(dead_code)]
pub fn new_with_dir(arguments: ArgMatches, dir: T) -> Context
where
T: Into,
diff --git a/src/main.rs b/src/main.rs
index 1f69d4ed9..4707cd816 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,36 +1,77 @@
#[macro_use]
extern crate clap;
-extern crate ansi_term;
-extern crate battery;
-extern crate dirs;
-extern crate git2;
-extern crate pretty_env_logger;
-
mod context;
mod module;
mod modules;
mod print;
mod segment;
-use clap::{App, Arg};
+use clap::{App, Arg, SubCommand};
fn main() {
pretty_env_logger::init();
- let args = App::new("Starship")
+ let matches = App::new("Starship")
.about("The cross-shell prompt for astronauts. ✨🚀")
// pull the version number from Cargo.toml
.version(crate_version!())
// pull the authors from Cargo.toml
.author(crate_authors!())
.after_help("https://github.com/matchai/starship")
- .arg(
- Arg::with_name("status_code")
- .help("The status code of the previously run command")
- .required(true),
+ .subcommand(
+ SubCommand::with_name("prompt")
+ .about("Prints the full starship prompt")
+ .arg(
+ Arg::with_name("status_code")
+ .short("s")
+ .long("status")
+ .value_name("STATUS_CODE")
+ .help("The status code of the previously run command")
+ .takes_value(true),
+ )
+ .arg(
+ Arg::with_name("path")
+ .short("p")
+ .long("path")
+ .value_name("PATH")
+ .help("The path that the prompt should render for ($PWD by default)")
+ .takes_value(true),
+ ),
+ )
+ .subcommand(
+ SubCommand::with_name("module")
+ .about("Prints a specific prompt module")
+ .arg(
+ Arg::with_name("name")
+ .help("The name of the module to be printed")
+ .required(true),
+ )
+ .arg(
+ Arg::with_name("status_code")
+ .short("s")
+ .long("status")
+ .value_name("STATUS_CODE")
+ .help("The status code of the previously run command")
+ .takes_value(true),
+ )
+ .arg(
+ Arg::with_name("path")
+ .short("p")
+ .long("path")
+ .value_name("PATH")
+ .help("The path the prompt should render for ($PWD by default)")
+ .takes_value(true),
+ ),
)
.get_matches();
- print::prompt(args);
+ match matches.subcommand() {
+ ("prompt", Some(sub_m)) => print::prompt(sub_m.clone()),
+ ("module", Some(sub_m)) => {
+ let module_name = sub_m.value_of("name").expect("Module name missing.");
+ print::module(module_name, sub_m.clone());
+ }
+ _ => {}
+ }
}
diff --git a/src/modules/character.rs b/src/modules/character.rs
index 2a9334894..1dfc27991 100644
--- a/src/modules/character.rs
+++ b/src/modules/character.rs
@@ -20,7 +20,7 @@ pub fn segment(context: &Context) -> Option {
let symbol = module.new_segment("symbol", PROMPT_CHAR);
let arguments = &context.arguments;
- if arguments.value_of("status_code").unwrap() == "0" {
+ if arguments.value_of("status_code").unwrap_or("0") == "0" {
symbol.set_style(color_success.bold());
} else {
symbol.set_style(color_failure.bold());
diff --git a/src/print.rs b/src/print.rs
index 53442f23f..71d453e34 100644
--- a/src/print.rs
+++ b/src/print.rs
@@ -46,3 +46,14 @@ pub fn prompt(args: ArgMatches) {
// Print all remaining modules
printable.for_each(|module| write!(handle, "{}", module).unwrap());
}
+
+pub fn module(module_name: &str, args: ArgMatches) {
+ let context = Context::new(args);
+
+ // If the module returns `None`, print an empty string
+ let module = modules::handle(module_name, &context)
+ .map(|m| m.to_string())
+ .unwrap_or_default();
+
+ print!("{}", module);
+}
diff --git a/tests/Dockerfile b/tests/Dockerfile
index 532b42dc5..4d1cd3217 100644
--- a/tests/Dockerfile
+++ b/tests/Dockerfile
@@ -1,9 +1,5 @@
FROM rust
-# Install Tarpaulin (code coverage tool)
-# https://github.com/xd009642/tarpaulin
-COPY --from=xd009642/tarpaulin /usr/local/cargo/bin/cargo-tarpaulin /usr/local/cargo/bin/cargo-tarpaulin
-
# Install Node.js
ENV NODE_VERSION 12.0.0
ENV PATH /root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH
@@ -54,5 +50,4 @@ RUN rm -rf /starship
RUN mkdir starship
WORKDIR /starship
-# Instrument coverage tooling and run the full test suite
-CMD ["cargo", "tarpaulin", "--ignored", "--out", "Xml"]
+CMD ["cargo", "test", "--", "--ignored"]
diff --git a/tests/character.rs b/tests/character.rs
deleted file mode 100644
index be0b1a8e3..000000000
--- a/tests/character.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use ansi_term::Color;
-use std::path::Path;
-
-mod common;
-
-#[test]
-fn char_module_success_status() {
- let dir = Path::new("~");
- let expected = format!("{} ", Color::Green.bold().paint("➜"));
- let actual = common::render_module_with_status("char", &dir, "0");
- assert_eq!(expected, actual);
-}
-
-#[test]
-fn char_module_failure_status() {
- let dir = Path::new("~");
- let expected = format!("{} ", Color::Red.bold().paint("➜"));
- let actual = common::render_module_with_status("char", &dir, "1");
- assert_eq!(expected, actual);
-}
diff --git a/tests/common.rs b/tests/common.rs
deleted file mode 100644
index 2d2cd2a00..000000000
--- a/tests/common.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use clap::{App, Arg};
-use starship::context::Context;
-use starship::modules;
-use std::path::PathBuf;
-
-#[allow(dead_code)]
-pub fn render_module(module: &str, path: T) -> String
-where
- T: Into,
-{
- render_module_with_status(module, path.into(), "0")
-}
-
-pub fn render_module_with_status(module: &str, path: T, status: &str) -> String
-where
- T: Into,
-{
- // Create an `Arg` with status_code of "0"
- let args = App::new("starship")
- .arg(Arg::with_name("status_code"))
- .get_matches_from(vec!["starship", status]);
- let context = Context::new_with_dir(args, path.into());
-
- let module = modules::handle(module, &context);
-
- module.unwrap().to_string()
-}
diff --git a/tests/directory.rs b/tests/directory.rs
deleted file mode 100644
index 42d6398ad..000000000
--- a/tests/directory.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-use ansi_term::Color;
-use dirs::home_dir;
-use git2::Repository;
-use std::fs;
-use std::io;
-use std::path::Path;
-use tempfile::TempDir;
-
-mod common;
-
-#[test]
-fn home_directory() -> io::Result<()> {
- let dir = Path::new("~");
-
- let expected = format!("in {} ", Color::Cyan.bold().paint("~").to_string());
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn directory_in_home() -> io::Result<()> {
- let dir = home_dir().unwrap().join("starship/engine");
- fs::create_dir_all(&dir)?;
-
- let expected = format!(
- "in {} ",
- Color::Cyan.bold().paint("~/starship/engine").to_string()
- );
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn truncated_directory_in_home() -> io::Result<()> {
- let dir = home_dir().unwrap().join("starship/engine/schematics");
- fs::create_dir_all(&dir)?;
-
- let expected = format!(
- "in {} ",
- Color::Cyan
- .bold()
- .paint("starship/engine/schematics")
- .to_string()
- );
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-fn root_directory() -> io::Result<()> {
- let dir = Path::new("/");
-
- let expected = format!("in {} ", Color::Cyan.bold().paint("/").to_string());
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-fn directory_in_root() -> io::Result<()> {
- let dir = Path::new("/tmp");
-
- let expected = format!("in {} ", Color::Cyan.bold().paint("/tmp").to_string());
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn truncated_directory_in_root() -> io::Result<()> {
- let dir = Path::new("/tmp/starship/thrusters/rocket");
- fs::create_dir_all(&dir)?;
-
- let expected = format!(
- "in {} ",
- Color::Cyan
- .bold()
- .paint("starship/thrusters/rocket")
- .to_string()
- );
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn git_repo_root() -> io::Result<()> {
- let tmp_dir = TempDir::new_in(home_dir().unwrap())?;
- let repo_dir = tmp_dir.path().join("rocket-controls");
- fs::create_dir(&repo_dir)?;
-
- Repository::init(&repo_dir).unwrap();
-
- let expected = format!(
- "in {} ",
- Color::Cyan.bold().paint("rocket-controls").to_string()
- );
- let actual = common::render_module("dir", &repo_dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn directory_in_git_repo() -> io::Result<()> {
- let tmp_dir = TempDir::new_in(home_dir().unwrap())?;
- let repo_dir = tmp_dir.path().join("rocket-controls");
- let dir = repo_dir.join("src");
- fs::create_dir_all(&dir)?;
-
- Repository::init(&repo_dir).unwrap();
-
- let expected = format!(
- "in {} ",
- Color::Cyan.bold().paint("rocket-controls/src").to_string()
- );
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn truncated_directory_in_git_repo() -> io::Result<()> {
- let tmp_dir = TempDir::new()?;
- let repo_dir = tmp_dir.path().join("rocket-controls");
- let dir = repo_dir.join("src/meters/fuel-gauge");
- fs::create_dir_all(&dir)?;
-
- Repository::init(&repo_dir).unwrap();
-
- let expected = format!(
- "in {} ",
- Color::Cyan
- .bold()
- .paint("src/meters/fuel-gauge")
- .to_string()
- );
- let actual = common::render_module("dir", &dir);
- assert_eq!(expected, actual);
-
- Ok(())
-}
diff --git a/tests/go.rs b/tests/go.rs
deleted file mode 100644
index 369530abc..000000000
--- a/tests/go.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-use ansi_term::Color;
-use starship::segment::Segment;
-use std::fs::{self, File};
-use std::io;
-use tempfile::TempDir;
-
-mod common;
-
-#[test]
-#[ignore]
-fn folder_with_go_file() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("main.go"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_go_mod() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("go.mod"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_go_sum() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("go.sum"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_godeps() -> io::Result<()> {
- let dir = TempDir::new()?;
- let godeps = dir.path().join("Godeps");
- fs::create_dir_all(&godeps)?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_glide_yaml() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("glide.yaml"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_gopkg_yml() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("Gopkg.yml"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_gopkg_lock() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("Gopkg.lock"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("go")
- .set_value("🐹 v1.10")
- .set_style(Color::Cyan.bold())
- );
- let actual = common::render_module("go", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
diff --git a/tests/nodejs.rs b/tests/nodejs.rs
deleted file mode 100644
index 38bca73bf..000000000
--- a/tests/nodejs.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-use ansi_term::Color;
-use starship::segment::Segment;
-use std::fs::{self, File};
-use std::io;
-use tempfile::TempDir;
-
-mod common;
-
-#[test]
-#[ignore]
-fn folder_with_package_json() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("package.json"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("node")
- .set_value("⬢ v12.0.0")
- .set_style(Color::Green.bold())
- );
- let actual = common::render_module("nodejs", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_js_file() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("index.js"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("node")
- .set_value("⬢ v12.0.0")
- .set_style(Color::Green.bold())
- );
- let actual = common::render_module("nodejs", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_node_modules() -> io::Result<()> {
- let dir = TempDir::new()?;
- let node_modules = dir.path().join("node_modules");
- fs::create_dir_all(&node_modules)?;
-
- let expected = format!(
- "via {} ",
- Segment::new("node")
- .set_value("⬢ v12.0.0")
- .set_style(Color::Green.bold())
- );
- let actual = common::render_module("nodejs", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
diff --git a/tests/python.rs b/tests/python.rs
deleted file mode 100644
index 237c1f306..000000000
--- a/tests/python.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use ansi_term::Color;
-use starship::segment::Segment;
-use std::fs::File;
-use std::io;
-use tempfile::TempDir;
-
-mod common;
-
-#[test]
-#[ignore]
-fn folder_with_python_version() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join(".python-version"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("python")
- .set_value("🐍 v3.6.8")
- .set_style(Color::Yellow.bold())
- );
- let actual = common::render_module("python", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_requirements_txt() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("requirements.txt"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("python")
- .set_value("🐍 v3.6.8")
- .set_style(Color::Yellow.bold())
- );
- let actual = common::render_module("python", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_pyproject_toml() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("pyproject.toml"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("python")
- .set_value("🐍 v3.6.8")
- .set_style(Color::Yellow.bold())
- );
- let actual = common::render_module("python", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
-
-#[test]
-#[ignore]
-fn folder_with_py_file() -> io::Result<()> {
- let dir = TempDir::new()?;
- File::create(dir.path().join("main.py"))?;
-
- let expected = format!(
- "via {} ",
- Segment::new("python")
- .set_value("🐍 v3.6.8")
- .set_style(Color::Yellow.bold())
- );
- let actual = common::render_module("python", &dir.path());
- assert_eq!(expected, actual);
-
- Ok(())
-}
diff --git a/tests/testsuite/character.rs b/tests/testsuite/character.rs
new file mode 100644
index 000000000..80a12bd32
--- /dev/null
+++ b/tests/testsuite/character.rs
@@ -0,0 +1,47 @@
+use ansi_term::Color;
+use std::io;
+
+use crate::common;
+
+#[test]
+fn char_module_success_status() -> io::Result<()> {
+ let expected = format!("{} ", Color::Green.bold().paint("➜"));
+
+ // Status code 0
+ let output = common::render_module("char").arg("--status=0").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ // No status code
+ let output = common::render_module("char").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ Ok(())
+}
+
+#[test]
+fn char_module_failure_status() -> io::Result<()> {
+ let expected = format!("{} ", Color::Red.bold().paint("➜"));
+
+ // Error status code 1
+ let output = common::render_module("char").arg("--status=1").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ // Random non-zero status code
+ let output = common::render_module("char")
+ .arg("--status=54321")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ // Negative status code!?
+ let output = common::render_module("char")
+ .arg("--status=-5000")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ Ok(())
+}
diff --git a/tests/testsuite/common.rs b/tests/testsuite/common.rs
new file mode 100644
index 000000000..451880288
--- /dev/null
+++ b/tests/testsuite/common.rs
@@ -0,0 +1,22 @@
+use std::{io, process};
+
+pub fn render_prompt() -> process::Command {
+ let mut command = process::Command::new("./target/debug/starship");
+ command.arg("prompt");
+
+ command
+}
+
+pub fn render_module(module_name: &str) -> process::Command {
+ let mut command = process::Command::new("./target/debug/starship");
+ command.arg("module").arg(module_name);
+
+ command
+}
+
+/// Create a temporary directory with full access permissions (rwxrwxrwt).
+pub fn new_tempdir() -> io::Result {
+ // Using `tempfile::TempDir` directly creates files on macOS within
+ // "/var/folders", which provides us with restricted permissions (rwxr-xr-x)
+ tempfile::tempdir_in("/tmp")
+}
diff --git a/tests/testsuite/directory.rs b/tests/testsuite/directory.rs
new file mode 100644
index 000000000..8835b8440
--- /dev/null
+++ b/tests/testsuite/directory.rs
@@ -0,0 +1,158 @@
+use ansi_term::Color;
+use dirs::home_dir;
+use git2::Repository;
+use std::fs;
+use std::io;
+use std::path::Path;
+use tempfile::TempDir;
+
+use crate::common;
+
+#[test]
+fn home_directory() -> io::Result<()> {
+ let output = common::render_module("dir").arg("--path=~").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("~"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn directory_in_home() -> io::Result<()> {
+ let dir = home_dir().unwrap().join("starship/engine");
+ fs::create_dir_all(&dir)?;
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("~/starship/engine"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn truncated_directory_in_home() -> io::Result<()> {
+ let dir = home_dir().unwrap().join("starship/engine/schematics");
+ fs::create_dir_all(&dir)?;
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!(
+ "in {} ",
+ Color::Cyan.bold().paint("starship/engine/schematics")
+ );
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+fn root_directory() -> io::Result<()> {
+ let output = common::render_module("dir").arg("--path=/").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("/"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+fn directory_in_root() -> io::Result<()> {
+ let output = common::render_module("dir").arg("--path=/tmp").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("/tmp"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn truncated_directory_in_root() -> io::Result<()> {
+ let dir = Path::new("/tmp/starship/thrusters/rocket");
+ fs::create_dir_all(&dir)?;
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!(
+ "in {} ",
+ Color::Cyan.bold().paint("starship/thrusters/rocket")
+ );
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn git_repo_root() -> io::Result<()> {
+ // TODO: Investigate why git repo related tests fail when the tempdir is within /tmp/...
+ // Temporarily making the tempdir within $HOME
+ // #[ignore] can be removed after this TODO is addressed
+ let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
+ let repo_dir = tmp_dir.path().join("rocket-controls");
+ fs::create_dir(&repo_dir)?;
+ Repository::init(&repo_dir).unwrap();
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(repo_dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("rocket-controls"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn directory_in_git_repo() -> io::Result<()> {
+ let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
+ let repo_dir = tmp_dir.path().join("rocket-controls");
+ let dir = repo_dir.join("src");
+ fs::create_dir_all(&dir)?;
+ Repository::init(&repo_dir).unwrap();
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("rocket-controls/src"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn truncated_directory_in_git_repo() -> io::Result<()> {
+ let tmp_dir = TempDir::new_in(dirs::home_dir().unwrap())?;
+ let repo_dir = tmp_dir.path().join("rocket-controls");
+ let dir = repo_dir.join("src/meters/fuel-gauge");
+ fs::create_dir_all(&dir)?;
+ Repository::init(&repo_dir).unwrap();
+
+ let output = common::render_module("dir")
+ .arg("--path")
+ .arg(dir)
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("in {} ", Color::Cyan.bold().paint("src/meters/fuel-gauge"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/golang.rs b/tests/testsuite/golang.rs
new file mode 100644
index 000000000..6419eefb7
--- /dev/null
+++ b/tests/testsuite/golang.rs
@@ -0,0 +1,140 @@
+use ansi_term::Color;
+use std::fs::{self, File};
+use std::io;
+
+use crate::common;
+
+#[test]
+fn folder_without_go_files() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = "";
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_go_file() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("main.go"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_go_mod() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("go.mod"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_go_sum() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("go.sum"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_godeps() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ let godeps = dir.path().join("Godeps");
+ fs::create_dir_all(&godeps)?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_glide_yaml() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("glide.yaml"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_gopkg_yml() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("Gopkg.yml"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_gopkg_lock() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("Gopkg.lock"))?;
+
+ let output = common::render_module("golang")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Cyan.bold().paint("🐹 v1.10"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/line_break.rs b/tests/testsuite/line_break.rs
new file mode 100644
index 000000000..5806ca11d
--- /dev/null
+++ b/tests/testsuite/line_break.rs
@@ -0,0 +1,13 @@
+use std::io;
+
+use crate::common;
+
+#[test]
+fn line_break_module() -> io::Result<()> {
+ let output = common::render_module("line_break").output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = "\n";
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs
new file mode 100644
index 000000000..1705ae3ae
--- /dev/null
+++ b/tests/testsuite/main.rs
@@ -0,0 +1,8 @@
+mod character;
+mod common;
+mod directory;
+mod golang;
+mod line_break;
+mod nodejs;
+mod python;
+mod username;
diff --git a/tests/testsuite/nodejs.rs b/tests/testsuite/nodejs.rs
new file mode 100644
index 000000000..33b0df2af
--- /dev/null
+++ b/tests/testsuite/nodejs.rs
@@ -0,0 +1,72 @@
+use ansi_term::Color;
+use std::fs::{self, File};
+use std::io;
+
+use crate::common;
+
+#[test]
+fn folder_without_node_files() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+
+ let output = common::render_module("nodejs")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = "";
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_package_json() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("package.json"))?;
+
+ let output = common::render_module("nodejs")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Green.bold().paint("⬢ v12.0.0"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_js_file() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("index.js"))?;
+
+ let output = common::render_module("nodejs")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Green.bold().paint("⬢ v12.0.0"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_node_modules() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ let node_modules = dir.path().join("node_modules");
+ fs::create_dir_all(&node_modules)?;
+
+ let output = common::render_module("nodejs")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Green.bold().paint("⬢ v12.0.0"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/testsuite/python.rs b/tests/testsuite/python.rs
new file mode 100644
index 000000000..7a68a916e
--- /dev/null
+++ b/tests/testsuite/python.rs
@@ -0,0 +1,73 @@
+use ansi_term::Color;
+use std::fs::File;
+use std::io;
+
+use crate::common;
+
+#[test]
+#[ignore]
+fn folder_with_python_version() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join(".python-version"))?;
+
+ let output = common::render_module("python")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 v3.6.8"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_requirements_txt() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("requirements.txt"))?;
+
+ let output = common::render_module("python")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 v3.6.8"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_pyproject_toml() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("pyproject.toml"))?;
+
+ let output = common::render_module("python")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 v3.6.8"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+#[ignore]
+fn folder_with_py_file() -> io::Result<()> {
+ let dir = common::new_tempdir()?;
+ File::create(dir.path().join("main.py"))?;
+
+ let output = common::render_module("python")
+ .arg("--path")
+ .arg(dir.path())
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("🐍 v3.6.8"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
diff --git a/tests/testsuite/username.rs b/tests/testsuite/username.rs
new file mode 100644
index 000000000..c046efef7
--- /dev/null
+++ b/tests/testsuite/username.rs
@@ -0,0 +1,64 @@
+use ansi_term::Color;
+use std::io;
+
+use crate::common;
+
+// TODO: Add tests for if root user (UID == 0)
+// Requires mocking
+
+#[test]
+fn no_username_shown() -> io::Result<()> {
+ let expected = "";
+
+ // No environment variables
+ let output = common::render_module("username").env_clear().output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ // LOGNAME == USER
+ let output = common::render_module("username")
+ .env_clear()
+ .env("LOGNAME", "astronaut")
+ .env("USER", "astronaut")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ // SSH connection w/o username
+ let output = common::render_module("username")
+ .env_clear()
+ .env("SSH_CONNECTION", "192.168.223.17 36673 192.168.223.229 22")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+ assert_eq!(expected, actual);
+
+ Ok(())
+}
+
+#[test]
+fn current_user_not_logname() -> io::Result<()> {
+ let output = common::render_module("username")
+ .env_clear()
+ .env("LOGNAME", "astronaut")
+ .env("USER", "cosmonaut")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("cosmonaut"));
+ assert_eq!(expected, actual);
+ Ok(())
+}
+
+#[test]
+fn ssh_connection() -> io::Result<()> {
+ let output = common::render_module("username")
+ .env_clear()
+ .env("USER", "astronaut")
+ .env("SSH_CONNECTION", "192.168.223.17 36673 192.168.223.229 22")
+ .output()?;
+ let actual = String::from_utf8(output.stdout).unwrap();
+
+ let expected = format!("via {} ", Color::Yellow.bold().paint("astronaut"));
+ assert_eq!(expected, actual);
+ Ok(())
+}