Refactor integration tests (#71)

- Create subcommands to be able to print modules independently
	- `starship prompt` will print the full prompt
	- `starship module <MODULE_NAME>` will print a specific module
		e.g. `starship module python`
	- Added `--path` flag to print the prompt or modules without being in a specific directory
	- Added `--status` flag to provide the status of the last command, instead of requiring it as an argument
- Refactored integration tests to be end-to-end tests, since there was no way in integration tests to set the environment variables for a specific command, which was required for the `username` module
- Moved e2e tests to `tests/testsuite` to allow for a single binary to be built
	- Tests will build/run faster
	- No more false positives for unused functions
- Added tests for `username`
- Removed codecov + tarpaulin 😢
This commit is contained in:
Matan Kushner 2019-06-06 13:18:00 +01:00 committed by GitHub
parent bb220bb5a0
commit 8239fbd12b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 678 additions and 519 deletions

3
.gitignore vendored
View file

@ -13,6 +13,3 @@ Cargo.lock
# Intellij IDE configuration # Intellij IDE configuration
.idea/ .idea/
# Cobertura coverage report
cobertura.xml

View file

@ -4,7 +4,6 @@
<p align="center">The cross-shell prompt for astronauts.</p> <p align="center">The cross-shell prompt for astronauts.</p>
<p align="center"> <p align="center">
<a href="https://dev.azure.com/starship-control/starship/_build"><img src="https://badgen.net/azure-pipelines/starship-control/starship/Starship%20Test%20Suite" alt="Azure Pipelines Build Status"></a> <a href="https://dev.azure.com/starship-control/starship/_build"><img src="https://badgen.net/azure-pipelines/starship-control/starship/Starship%20Test%20Suite" alt="Azure Pipelines Build Status"></a>
<a href="https://codecov.io/gh/starship/starship"><img src="https://badgen.net/codecov/c/github/starship/starship" alt="Codecov Coverage"></a>
<a href="#contributors"><img src="https://badgen.net/badge/all%20contributors/7/orange" alt="All Contributors"></a> <a href="#contributors"><img src="https://badgen.net/badge/all%20contributors/7/orange" alt="All Contributors"></a>
<a href="https://discord.gg/8Jzqu3T"><img src="https://badgen.net/badge/chat/on%20discord/7289da" alt="Chat on Discord"></a> <a href="https://discord.gg/8Jzqu3T"><img src="https://badgen.net/badge/chat/on%20discord/7289da" alt="Chat on Discord"></a>
</p> </p>

View file

@ -1,3 +1,3 @@
function fish_prompt function fish_prompt
starship $status starship prompt --status=$status
end end

View file

@ -1 +1 @@
PROMPT='$(starship $?)' PROMPT='$(starship prompt --status=$?)'

View file

@ -5,11 +5,11 @@ jobs:
vmImage: ubuntu-16.04 vmImage: ubuntu-16.04
steps: steps:
- script: ./integration_test - script: docker pull starshipcommand/starship-test
displayName: Run integration test within Docker displayName: Pull docker image
- script: bash <(curl -s https://codecov.io/bash) -t $(CODECOV_TOKEN) - script: ./integration_test
displayName: Report coverage to Codecov displayName: Run integration test suite
- script: | - script: |
docker login -u $(dockerUsername) -p $(dockerPassword) docker login -u $(dockerUsername) -p $(dockerPassword)

View file

@ -6,9 +6,6 @@ if ! (docker --version); then
exit 1 exit 1
fi fi
printf 'Pulling latest docker image'
docker pull starshipcommand/starship-test
printf 'Building test docker image:\n' printf 'Building test docker image:\n'
docker build -f tests/Dockerfile \ docker build -f tests/Dockerfile \
--tag starshipcommand/starship-test \ --tag starshipcommand/starship-test \
@ -16,6 +13,4 @@ docker build -f tests/Dockerfile \
. .
printf 'Running test suite:\n' printf 'Running test suite:\n'
# `seccomp=unconfined` is needed to allow tarpaulin to disable ASLR docker run --rm -v $(pwd):/starship starshipcommand/starship-test
# Details found here: https://github.com/xd009642/tarpaulin/issues/146
docker run --rm --security-opt seccomp=unconfined -v $(pwd):/starship starshipcommand/starship-test

View file

@ -15,11 +15,15 @@ pub struct Context<'a> {
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub fn new(arguments: ArgMatches) -> Context { pub fn new(arguments: ArgMatches) -> Context {
let current_dir = env::current_dir().expect("Unable to identify current directory."); // Retreive the "path" flag. If unavailable, use the current directory instead.
Context::new_with_dir(arguments, current_dir) 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<T>(arguments: ArgMatches, dir: T) -> Context pub fn new_with_dir<T>(arguments: ArgMatches, dir: T) -> Context
where where
T: Into<PathBuf>, T: Into<PathBuf>,

View file

@ -1,36 +1,77 @@
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
extern crate ansi_term;
extern crate battery;
extern crate dirs;
extern crate git2;
extern crate pretty_env_logger;
mod context; mod context;
mod module; mod module;
mod modules; mod modules;
mod print; mod print;
mod segment; mod segment;
use clap::{App, Arg}; use clap::{App, Arg, SubCommand};
fn main() { fn main() {
pretty_env_logger::init(); pretty_env_logger::init();
let args = App::new("Starship") let matches = App::new("Starship")
.about("The cross-shell prompt for astronauts. ✨🚀") .about("The cross-shell prompt for astronauts. ✨🚀")
// pull the version number from Cargo.toml // pull the version number from Cargo.toml
.version(crate_version!()) .version(crate_version!())
// pull the authors from Cargo.toml // pull the authors from Cargo.toml
.author(crate_authors!()) .author(crate_authors!())
.after_help("https://github.com/matchai/starship") .after_help("https://github.com/matchai/starship")
.subcommand(
SubCommand::with_name("prompt")
.about("Prints the full starship prompt")
.arg( .arg(
Arg::with_name("status_code") Arg::with_name("status_code")
.short("s")
.long("status")
.value_name("STATUS_CODE")
.help("The status code of the previously run command") .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), .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(); .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());
}
_ => {}
}
} }

View file

@ -20,7 +20,7 @@ pub fn segment(context: &Context) -> Option<Module> {
let symbol = module.new_segment("symbol", PROMPT_CHAR); let symbol = module.new_segment("symbol", PROMPT_CHAR);
let arguments = &context.arguments; 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()); symbol.set_style(color_success.bold());
} else { } else {
symbol.set_style(color_failure.bold()); symbol.set_style(color_failure.bold());

View file

@ -46,3 +46,14 @@ pub fn prompt(args: ArgMatches) {
// Print all remaining modules // Print all remaining modules
printable.for_each(|module| write!(handle, "{}", module).unwrap()); 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);
}

View file

@ -1,9 +1,5 @@
FROM rust 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 # Install Node.js
ENV NODE_VERSION 12.0.0 ENV NODE_VERSION 12.0.0
ENV PATH /root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH ENV PATH /root/.nvm/versions/node/v$NODE_VERSION/bin:$PATH
@ -54,5 +50,4 @@ RUN rm -rf /starship
RUN mkdir starship RUN mkdir starship
WORKDIR /starship WORKDIR /starship
# Instrument coverage tooling and run the full test suite CMD ["cargo", "test", "--", "--ignored"]
CMD ["cargo", "tarpaulin", "--ignored", "--out", "Xml"]

View file

@ -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);
}

View file

@ -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<T>(module: &str, path: T) -> String
where
T: Into<PathBuf>,
{
render_module_with_status(module, path.into(), "0")
}
pub fn render_module_with_status<T>(module: &str, path: T, status: &str) -> String
where
T: Into<PathBuf>,
{
// 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()
}

View file

@ -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(())
}

View file

@ -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(())
}

View file

@ -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(())
}

View file

@ -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(())
}

View file

@ -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(())
}

22
tests/testsuite/common.rs Normal file
View file

@ -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<tempfile::TempDir> {
// Using `tempfile::TempDir` directly creates files on macOS within
// "/var/folders", which provides us with restricted permissions (rwxr-xr-x)
tempfile::tempdir_in("/tmp")
}

View file

@ -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(())
}

140
tests/testsuite/golang.rs Normal file
View file

@ -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(())
}

View file

@ -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(())
}

8
tests/testsuite/main.rs Normal file
View file

@ -0,0 +1,8 @@
mod character;
mod common;
mod directory;
mod golang;
mod line_break;
mod nodejs;
mod python;
mod username;

72
tests/testsuite/nodejs.rs Normal file
View file

@ -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(())
}

View file

73
tests/testsuite/python.rs Normal file
View file

@ -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(())
}

View file

@ -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(())
}