From 4034129dba433a56c58e9fab01dd8496cb0aec91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sun, 15 Dec 2019 11:15:06 -0500 Subject: [PATCH] This commit is the continuing phase of extracting functionality to subcrates. We extract test helpers and begin to change Nu shell's test organization along with it. --- Cargo.lock | 12 + Cargo.toml | 1 + crates/test-support/Cargo.toml | 16 + crates/test-support/src/fs.rs | 228 +++++ crates/test-support/src/lib.rs | 38 + crates/test-support/src/macros.rs | 159 ++++ crates/test-support/src/playground.rs | 152 ++++ src/lib.rs | 1 - src/utils.rs | 116 --- tests/command_config_test.rs | 115 --- tests/commands/append.rs | 17 + tests/{command_cd_tests.rs => commands/cd.rs} | 6 +- tests/commands/compact.rs | 52 ++ tests/{command_cp_tests.rs => commands/cp.rs} | 8 +- tests/commands/default.rs | 36 + tests/commands/edit.rs | 16 + .../enter.rs} | 12 +- tests/commands/first.rs | 70 ++ tests/commands/format.rs | 16 + .../{command_get_tests.rs => commands/get.rs} | 25 +- tests/commands/group_by.rs | 56 ++ tests/commands/histogram.rs | 32 + tests/commands/insert.rs | 16 + tests/commands/last.rs | 56 ++ tests/commands/lines.rs | 21 + tests/{command_ls_tests.rs => commands/ls.rs} | 19 +- .../mkdir.rs} | 10 +- tests/commands/mod.rs | 30 + tests/{command_mv_tests.rs => commands/mv.rs} | 11 +- tests/commands/nth.rs | 39 + .../open.rs} | 37 +- tests/commands/parse.rs | 17 + tests/commands/prepend.rs | 17 + tests/commands/range.rs | 47 + tests/commands/reverse.rs | 11 + tests/{command_rm_tests.rs => commands/rm.rs} | 27 +- tests/commands/save.rs | 47 + tests/commands/sort_by.rs | 23 + tests/commands/split_by.rs | 55 ++ tests/commands/split_column.rs | 20 + .../where_.rs} | 32 +- tests/commands/wrap.rs | 63 ++ tests/commands_test.rs | 564 ------------ tests/converting_formats/bson.rs | 18 + tests/converting_formats/csv.rs | 184 ++++ tests/converting_formats/json.rs | 103 +++ tests/converting_formats/mod.rs | 10 + tests/converting_formats/sqlite.rs | 19 + tests/converting_formats/ssv.rs | 98 +++ tests/converting_formats/toml.rs | 17 + tests/converting_formats/tsv.rs | 136 +++ tests/converting_formats/url.rs | 17 + tests/converting_formats/xlsx.rs | 17 + tests/converting_formats/yaml.rs | 17 + tests/external_tests.rs | 42 - tests/filters.rs | 43 + tests/filters_test.rs | 811 ------------------ tests/helpers/mod.rs | 450 ---------- tests/main.rs | 6 + .../core_inc.rs} | 6 +- .../core_str.rs} | 15 +- tests/plugins/mod.rs | 2 + tests/shell/mod.rs | 32 + tests/tests.rs | 135 --- 64 files changed, 2184 insertions(+), 2340 deletions(-) create mode 100644 crates/test-support/Cargo.toml create mode 100644 crates/test-support/src/fs.rs create mode 100644 crates/test-support/src/lib.rs create mode 100644 crates/test-support/src/macros.rs create mode 100644 crates/test-support/src/playground.rs delete mode 100644 tests/command_config_test.rs create mode 100644 tests/commands/append.rs rename tests/{command_cd_tests.rs => commands/cd.rs} (98%) create mode 100644 tests/commands/compact.rs rename tests/{command_cp_tests.rs => commands/cp.rs} (97%) create mode 100644 tests/commands/default.rs create mode 100644 tests/commands/edit.rs rename tests/{command_enter_test.rs => commands/enter.rs} (91%) create mode 100644 tests/commands/first.rs create mode 100644 tests/commands/format.rs rename tests/{command_get_tests.rs => commands/get.rs} (91%) create mode 100644 tests/commands/group_by.rs create mode 100644 tests/commands/histogram.rs create mode 100644 tests/commands/insert.rs create mode 100644 tests/commands/last.rs create mode 100644 tests/commands/lines.rs rename tests/{command_ls_tests.rs => commands/ls.rs} (78%) rename tests/{command_mkdir_tests.rs => commands/mkdir.rs} (87%) create mode 100644 tests/commands/mod.rs rename tests/{command_mv_tests.rs => commands/mv.rs} (96%) create mode 100644 tests/commands/nth.rs rename tests/{command_open_tests.rs => commands/open.rs} (92%) create mode 100644 tests/commands/parse.rs create mode 100644 tests/commands/prepend.rs create mode 100644 tests/commands/range.rs create mode 100644 tests/commands/reverse.rs rename tests/{command_rm_tests.rs => commands/rm.rs} (84%) create mode 100644 tests/commands/save.rs create mode 100644 tests/commands/sort_by.rs create mode 100644 tests/commands/split_by.rs create mode 100644 tests/commands/split_column.rs rename tests/{filter_where_tests.rs => commands/where_.rs} (73%) create mode 100644 tests/commands/wrap.rs delete mode 100644 tests/commands_test.rs create mode 100644 tests/converting_formats/bson.rs create mode 100644 tests/converting_formats/csv.rs create mode 100644 tests/converting_formats/json.rs create mode 100644 tests/converting_formats/mod.rs create mode 100644 tests/converting_formats/sqlite.rs create mode 100644 tests/converting_formats/ssv.rs create mode 100644 tests/converting_formats/toml.rs create mode 100644 tests/converting_formats/tsv.rs create mode 100644 tests/converting_formats/url.rs create mode 100644 tests/converting_formats/xlsx.rs create mode 100644 tests/converting_formats/yaml.rs delete mode 100644 tests/external_tests.rs create mode 100644 tests/filters.rs delete mode 100644 tests/filters_test.rs delete mode 100644 tests/helpers/mod.rs create mode 100644 tests/main.rs rename tests/{filter_inc_tests.rs => plugins/core_inc.rs} (96%) rename tests/{filter_str_tests.rs => plugins/core_str.rs} (92%) create mode 100644 tests/plugins/mod.rs create mode 100644 tests/shell/mod.rs delete mode 100644 tests/tests.rs diff --git a/Cargo.lock b/Cargo.lock index c206f920d..e848ec0c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2000,6 +2000,7 @@ dependencies = [ "tempfile", "term", "termcolor", + "test-support", "textwrap", "toml 0.5.5", "trash", @@ -3408,6 +3409,17 @@ dependencies = [ "wincolor", ] +[[package]] +name = "test-support" +version = "0.1.0" +dependencies = [ + "app_dirs", + "dunce", + "getset", + "glob", + "tempfile", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 24d388781..20c1564cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,6 +158,7 @@ features = ["bundled", "blob"] [dev-dependencies] pretty_assertions = "0.6.1" +test-support = { version = "0.1.0", path = "./crates/test-support" } [build-dependencies] toml = "0.5.5" diff --git a/crates/test-support/Cargo.toml b/crates/test-support/Cargo.toml new file mode 100644 index 000000000..11371088f --- /dev/null +++ b/crates/test-support/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "test-support" +version = "0.1.0" +authors = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] +edition = "2018" +description = "A source string characterizer for Nushell" +license = "MIT" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +app_dirs = "1.2.1" +dunce = "1.0.0" +getset = "0.0.9" +glob = "0.3.0" +tempfile = "3.1.0" diff --git a/crates/test-support/src/fs.rs b/crates/test-support/src/fs.rs new file mode 100644 index 000000000..dbb3cc993 --- /dev/null +++ b/crates/test-support/src/fs.rs @@ -0,0 +1,228 @@ +use std::io::Read; +use std::ops::Div; +use std::path::{Path, PathBuf}; + +pub struct AbsoluteFile { + inner: PathBuf, +} + +impl AbsoluteFile { + pub fn new(path: impl AsRef) -> AbsoluteFile { + let path = path.as_ref(); + + if !path.is_absolute() { + panic!( + "AbsoluteFile::new must take an absolute path :: {}", + path.display() + ) + } else if path.is_dir() { + // At the moment, this is not an invariant, but rather a way to catch bugs + // in tests. + panic!( + "AbsoluteFile::new must not take a directory :: {}", + path.display() + ) + } else { + AbsoluteFile { + inner: path.to_path_buf(), + } + } + } + + pub fn dir(&self) -> AbsolutePath { + AbsolutePath::new(self.inner.parent().unwrap()) + } +} + +impl From for PathBuf { + fn from(file: AbsoluteFile) -> Self { + file.inner + } +} + +pub struct AbsolutePath { + inner: PathBuf, +} + +impl AbsolutePath { + pub fn new(path: impl AsRef) -> AbsolutePath { + let path = path.as_ref(); + + if path.is_absolute() { + AbsolutePath { + inner: path.to_path_buf(), + } + } else { + panic!("AbsolutePath::new must take an absolute path") + } + } +} + +impl Div<&str> for &AbsolutePath { + type Output = AbsolutePath; + + fn div(self, rhs: &str) -> Self::Output { + let parts = rhs.split('/'); + let mut result = self.inner.clone(); + + for part in parts { + result = result.join(part); + } + + AbsolutePath::new(result) + } +} + +impl AsRef for AbsolutePath { + fn as_ref(&self) -> &Path { + self.inner.as_path() + } +} + +pub struct RelativePath { + inner: PathBuf, +} + +impl RelativePath { + pub fn new(path: impl Into) -> RelativePath { + let path = path.into(); + + if path.is_relative() { + RelativePath { inner: path } + } else { + panic!("RelativePath::new must take a relative path") + } + } +} + +impl> Div for &RelativePath { + type Output = RelativePath; + + fn div(self, rhs: T) -> Self::Output { + let parts = rhs.as_ref().split('/'); + let mut result = self.inner.clone(); + + for part in parts { + result = result.join(part); + } + + RelativePath::new(result) + } +} +pub trait DisplayPath { + fn display_path(&self) -> String; +} + +impl DisplayPath for AbsolutePath { + fn display_path(&self) -> String { + self.inner.display().to_string() + } +} + +impl DisplayPath for PathBuf { + fn display_path(&self) -> String { + self.display().to_string() + } +} + +impl DisplayPath for str { + fn display_path(&self) -> String { + self.to_string() + } +} + +impl DisplayPath for &str { + fn display_path(&self) -> String { + self.to_string() + } +} + +impl DisplayPath for String { + fn display_path(&self) -> String { + self.clone() + } +} + +impl DisplayPath for &String { + fn display_path(&self) -> String { + self.to_string() + } +} +pub enum Stub<'a> { + FileWithContent(&'a str, &'a str), + FileWithContentToBeTrimmed(&'a str, &'a str), + EmptyFile(&'a str), +} + +pub fn file_contents(full_path: impl AsRef) -> String { + let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file"); + let mut contents = String::new(); + file.read_to_string(&mut contents) + .expect("can not read file"); + contents +} + +pub fn file_contents_binary(full_path: impl AsRef) -> Vec { + let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file"); + let mut contents = Vec::new(); + file.read_to_end(&mut contents).expect("can not read file"); + contents +} + +pub fn line_ending() -> String { + #[cfg(windows)] + { + String::from("\r\n") + } + + #[cfg(not(windows))] + { + String::from("\n") + } +} + +pub fn delete_file_at(full_path: impl AsRef) { + let full_path = full_path.as_ref(); + + if full_path.exists() { + std::fs::remove_file(full_path).expect("can not delete file"); + } +} + +pub fn create_file_at(full_path: impl AsRef) -> Result<(), std::io::Error> { + let full_path = full_path.as_ref(); + + if let Some(parent) = full_path.parent() { + panic!(format!("{:?} exists", parent.display())); + } + + std::fs::write(full_path, "fake data".as_bytes()) +} + +pub fn copy_file_to(source: &str, destination: &str) { + std::fs::copy(source, destination).expect("can not copy file"); +} + +pub fn files_exist_at(files: Vec>, path: impl AsRef) -> bool { + files.iter().all(|f| { + let mut loc = PathBuf::from(path.as_ref()); + loc.push(f); + loc.exists() + }) +} + +pub fn delete_directory_at(full_path: &str) { + std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory"); +} + +pub fn executable_path() -> PathBuf { + let mut buf = PathBuf::new(); + buf.push("target"); + buf.push("debug"); + buf.push("nu"); + buf +} + +pub fn in_directory(str: impl AsRef) -> String { + str.as_ref().display().to_string() +} diff --git a/crates/test-support/src/lib.rs b/crates/test-support/src/lib.rs new file mode 100644 index 000000000..3642c8e72 --- /dev/null +++ b/crates/test-support/src/lib.rs @@ -0,0 +1,38 @@ +pub mod fs; +pub mod macros; +pub mod playground; + +pub fn pipeline(commands: &str) -> String { + commands + .lines() + .skip(1) + .map(|line| line.trim()) + .collect::>() + .join(" ") + .trim_end() + .to_string() +} + +#[cfg(tests)] +mod tests { + use super::pipeline; + + #[test] + fn constructs_a_pipeline() { + let actual = pipeline( + r#" + open los_tres_amigos.txt + | from-csv + | get rusty_luck + | str --to-int + | sum + | echo "$it" + "#, + ); + + assert_eq!( + actual, + r#"open los_tres_amigos.txt | from-csv | get rusty_luck | str --to-int | sum | echo "$it""# + ); + } +} diff --git a/crates/test-support/src/macros.rs b/crates/test-support/src/macros.rs new file mode 100644 index 000000000..d97ebbc89 --- /dev/null +++ b/crates/test-support/src/macros.rs @@ -0,0 +1,159 @@ +#[macro_export] +macro_rules! nu { + (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ + use $crate::fs::DisplayPath; + + let path = format!($path, $( + $part.display_path() + ),*); + + nu!($cwd, &path) + }}; + + (cwd: $cwd:expr, $path:expr) => {{ + nu!($cwd, $path) + }}; + + ($cwd:expr, $path:expr) => {{ + pub use std::error::Error; + pub use std::io::prelude::*; + pub use std::process::{Command, Stdio}; + + let commands = &*format!( + " + cd {} + {} + exit", + $crate::fs::in_directory($cwd), + $crate::fs::DisplayPath::display_path(&$path) + ); + + let mut process = match Command::new($crate::fs::executable_path()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + { + Ok(child) => child, + Err(why) => panic!("Can't run test {}", why.description()), + }; + + let stdin = process.stdin.as_mut().expect("couldn't open stdin"); + stdin + .write_all(commands.as_bytes()) + .expect("couldn't write to stdin"); + + + let output = process + .wait_with_output() + .expect("couldn't read from stdout"); + + let out = String::from_utf8_lossy(&output.stdout); + let out = out.replace("\r\n", ""); + let out = out.replace("\n", ""); + out + }}; +} + +#[macro_export] +macro_rules! nu_error { + (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ + use $crate::fs::DisplayPath; + + let path = format!($path, $( + $part.display_path() + ),*); + + nu_error!($cwd, &path) + }}; + + (cwd: $cwd:expr, $path:expr) => {{ + nu_error!($cwd, $path) + }}; + + ($cwd:expr, $path:expr) => {{ + pub use std::error::Error; + pub use std::io::prelude::*; + pub use std::process::{Command, Stdio}; + + let commands = &*format!( + " + cd {} + {} + exit", + $crate::fs::in_directory($cwd), + $crate::fs::DisplayPath::display_path(&$path) + ); + + let mut process = Command::new($crate::fs::executable_path()) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("couldn't run test"); + + let stdin = process.stdin.as_mut().expect("couldn't open stdin"); + stdin + .write_all(commands.as_bytes()) + .expect("couldn't write to stdin"); + + let output = process + .wait_with_output() + .expect("couldn't read from stderr"); + + let out = String::from_utf8_lossy(&output.stderr); + out.into_owned() + }}; +} + +#[macro_export] +macro_rules! nu_combined { + (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ + use $crate::fs::DisplayPath; + + let path = format!($path, $( + $part.display_path() + ),*); + + nu_combined!($cwd, &path) + }}; + + (cwd: $cwd:expr, $path:expr) => {{ + nu_combined!($cwd, $path) + }}; + + ($cwd:expr, $path:expr) => {{ + pub use std::error::Error; + pub use std::io::prelude::*; + pub use std::process::{Command, Stdio}; + + let commands = &*format!( + " + cd {} + {} + exit", + $crate::fs::in_directory($cwd), + $crate::fs::DisplayPath::display_path(&$path) + ); + + let mut process = Command::new($crate::fs::executable_path()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("couldn't run test"); + + let stdin = process.stdin.as_mut().expect("couldn't open stdin"); + stdin + .write_all(commands.as_bytes()) + .expect("couldn't write to stdin"); + + let output = process + .wait_with_output() + .expect("couldn't read from stdout/stderr"); + + let err = String::from_utf8_lossy(&output.stderr).into_owned(); + let out = String::from_utf8_lossy(&output.stdout).into_owned(); + let out = out.replace("\r\n", ""); + let out = out.replace("\n", ""); + (out, err) + }}; +} diff --git a/crates/test-support/src/playground.rs b/crates/test-support/src/playground.rs new file mode 100644 index 000000000..0ba57cad7 --- /dev/null +++ b/crates/test-support/src/playground.rs @@ -0,0 +1,152 @@ +use crate::fs::line_ending; +use crate::fs::Stub; + +use getset::Getters; +use glob::glob; +use std::path::{Path, PathBuf}; +use tempfile::{tempdir, TempDir}; + +pub struct Playground { + root: TempDir, + tests: String, + cwd: PathBuf, +} + +#[derive(Getters)] +#[get = "pub"] +pub struct Dirs { + pub root: PathBuf, + pub test: PathBuf, + pub fixtures: PathBuf, +} + +impl Dirs { + pub fn formats(&self) -> PathBuf { + PathBuf::from(self.fixtures.join("formats")) + } +} + +impl Playground { + pub fn root(&self) -> &Path { + self.root.path() + } + + pub fn back_to_playground(&mut self) -> &mut Self { + self.cwd = PathBuf::from(self.root()).join(self.tests.clone()); + self + } + + pub fn setup(topic: &str, block: impl FnOnce(Dirs, &mut Playground)) { + let root = tempdir().expect("Couldn't create a tempdir"); + let nuplay_dir = root.path().join(topic); + + if PathBuf::from(&nuplay_dir).exists() { + std::fs::remove_dir_all(PathBuf::from(&nuplay_dir)).expect("can not remove directory"); + } + + std::fs::create_dir(PathBuf::from(&nuplay_dir)).expect("can not create directory"); + + let mut playground = Playground { + root: root, + tests: topic.to_string(), + cwd: nuplay_dir, + }; + + let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let playground_root = playground.root.path(); + + let fixtures = project_root; + let fixtures = fixtures + .parent() + .expect("Couldn't find the fixtures directory") + .parent() + .expect("Couldn't find the fixtures directory") + .join("tests/fixtures"); + + let fixtures = dunce::canonicalize(fixtures.clone()).expect(&format!( + "Couldn't canonicalize fixtures path {}", + fixtures.display() + )); + + let test = + dunce::canonicalize(PathBuf::from(playground_root.join(topic))).expect(&format!( + "Couldn't canonicalize test path {}", + playground_root.join(topic).display() + )); + + let root = dunce::canonicalize(playground_root).expect(&format!( + "Couldn't canonicalize tests root path {}", + playground_root.display() + )); + + let dirs = Dirs { + root, + test, + fixtures, + }; + + block(dirs, &mut playground); + } + + pub fn mkdir(&mut self, directory: &str) -> &mut Self { + self.cwd.push(directory); + std::fs::create_dir_all(&self.cwd).expect("can not create directory"); + self.back_to_playground(); + self + } + + pub fn with_files(&mut self, files: Vec) -> &mut Self { + let endl = line_ending(); + + files + .iter() + .map(|f| { + let mut path = PathBuf::from(&self.cwd); + + let (file_name, contents) = match *f { + Stub::EmptyFile(name) => (name, "fake data".to_string()), + Stub::FileWithContent(name, content) => (name, content.to_string()), + Stub::FileWithContentToBeTrimmed(name, content) => ( + name, + content + .lines() + .skip(1) + .map(|line| line.trim()) + .collect::>() + .join(&endl), + ), + }; + + path.push(file_name); + + std::fs::write(PathBuf::from(path), contents.as_bytes()) + .expect("can not create file"); + }) + .for_each(drop); + self.back_to_playground(); + self + } + + pub fn within(&mut self, directory: &str) -> &mut Self { + self.cwd.push(directory); + std::fs::create_dir(&self.cwd).expect("can not create directory"); + self + } + + pub fn glob_vec(pattern: &str) -> Vec { + let glob = glob(pattern); + + match glob { + Ok(paths) => paths + .map(|path| { + if let Ok(path) = path { + path + } else { + unreachable!() + } + }) + .collect(), + Err(_) => panic!("Invalid pattern."), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index b77a284b4..f1506015c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,6 @@ pub use crate::data::dict::TaggedListBuilder; pub use crate::data::primitive; pub use crate::data::value; pub use crate::env::host::BasicHost; -pub use crate::utils::{AbsoluteFile, AbsolutePath, RelativePath}; pub use nu_parser::TokenTreeBuilder; pub use nu_value_ext::ValueExt; pub use num_traits::cast::ToPrimitive; diff --git a/src/utils.rs b/src/utils.rs index e7cad7f52..d25aaa0bf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,123 +1,7 @@ use nu_errors::ShellError; use nu_protocol::{UntaggedValue, Value}; -use nu_source::{b, DebugDocBuilder, PrettyDebug}; -use std::ops::Div; use std::path::{Component, Path, PathBuf}; -pub struct AbsoluteFile { - inner: PathBuf, -} - -impl AbsoluteFile { - pub fn new(path: impl AsRef) -> AbsoluteFile { - let path = path.as_ref(); - - if !path.is_absolute() { - panic!( - "AbsoluteFile::new must take an absolute path :: {}", - path.display() - ) - } else if path.is_dir() { - // At the moment, this is not an invariant, but rather a way to catch bugs - // in tests. - panic!( - "AbsoluteFile::new must not take a directory :: {}", - path.display() - ) - } else { - AbsoluteFile { - inner: path.to_path_buf(), - } - } - } - - pub fn dir(&self) -> AbsolutePath { - AbsolutePath::new(self.inner.parent().unwrap()) - } -} - -impl From for PathBuf { - fn from(file: AbsoluteFile) -> Self { - file.inner - } -} - -pub struct AbsolutePath { - inner: PathBuf, -} - -impl PrettyDebug for AbsolutePath { - fn pretty(&self) -> DebugDocBuilder { - b::primitive(self.inner.display()) - } -} - -impl AbsolutePath { - pub fn new(path: impl AsRef) -> AbsolutePath { - let path = path.as_ref(); - - if path.is_absolute() { - AbsolutePath { - inner: path.to_path_buf(), - } - } else { - panic!("AbsolutePath::new must take an absolute path") - } - } -} - -impl Div<&str> for &AbsolutePath { - type Output = AbsolutePath; - - fn div(self, rhs: &str) -> Self::Output { - let parts = rhs.split('/'); - let mut result = self.inner.clone(); - - for part in parts { - result = result.join(part); - } - - AbsolutePath::new(result) - } -} - -impl AsRef for AbsolutePath { - fn as_ref(&self) -> &Path { - self.inner.as_path() - } -} - -pub struct RelativePath { - inner: PathBuf, -} - -impl RelativePath { - pub fn new(path: impl Into) -> RelativePath { - let path = path.into(); - - if path.is_relative() { - RelativePath { inner: path } - } else { - panic!("RelativePath::new must take a relative path") - } - } -} - -impl> Div for &RelativePath { - type Output = RelativePath; - - fn div(self, rhs: T) -> Self::Output { - let parts = rhs.as_ref().split('/'); - let mut result = self.inner.clone(); - - for part in parts { - result = result.join(part); - } - - RelativePath::new(result) - } -} - pub enum TaggedValueIter<'a> { Empty, List(indexmap::map::Iter<'a, String, Value>), diff --git a/tests/command_config_test.rs b/tests/command_config_test.rs deleted file mode 100644 index 8a45be47c..000000000 --- a/tests/command_config_test.rs +++ /dev/null @@ -1,115 +0,0 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; - -use std::path::PathBuf; - -#[test] -fn has_default_configuration_file() { - let expected = "config.toml"; - - Playground::setup("config_test_1", |dirs, _| { - nu!(cwd: dirs.root(), "config"); - - assert_eq!( - dirs.config_path().join(expected), - nu::config_path().unwrap().join(expected) - ); - }) -} - -#[test] -fn shows_path_of_configuration_file() { - let expected = "config.toml"; - - Playground::setup("config_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - "config --path | echo $it" - ); - - assert_eq!(PathBuf::from(actual), dirs.config_path().join(expected)); - }); -} - -#[test] -fn use_different_configuration() { - Playground::setup("config_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "test_3.toml", - r#" - caballero_1 = "Andrés N. Robalino" - caballero_2 = "Jonathan Turner" - caballero_3 = "Yehuda katz" - "#, - )]); - - let actual = nu!( - cwd: dirs.root(), - "config --get caballero_1 --load {}/test_3.toml | echo $it", - dirs.test() - ); - - assert_eq!(actual, "Andrés N. Robalino"); - }); - - h::delete_file_at(nu::config_path().unwrap().join("test_3.toml")); -} - -#[test] -fn sets_configuration_value() { - Playground::setup("config_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "test_4.toml", - r#" - caballero_1 = "Andrés N. Robalino" - caballero_2 = "Jonathan Turner" - caballero_3 = "Yehuda katz" - "#, - )]); - - nu!( - cwd: dirs.test(), - "config --load test_4.toml --set [caballero_4 jonas]" - ); - - let actual = nu!( - cwd: dirs.root(), - r#"open "{}/test_4.toml" | get caballero_4 | echo $it"#, - dirs.config_path() - ); - - assert_eq!(actual, "jonas"); - }); - - h::delete_file_at(nu::config_path().unwrap().join("test_4.toml")); -} - -// #[test] -// fn removes_configuration_value() { -// Playground::setup("config_test_5", |dirs, sandbox| { -// sandbox.with_files(vec![FileWithContent( -// "test_5.toml", -// r#" -// caballeros = [1, 1, 1] -// podershell = [1, 1, 1] -// "#, -// )]); - -// nu!( -// cwd: dirs.test(), -// "config --load test_5.toml --remove podershell" -// ); - -// let actual = nu_error!( -// cwd: dirs.root(), -// r#"open "{}/test_5.toml" | get podershell | echo $it"#, -// dirs.config_path() -// ); - -// assert!(actual.contains("Unknown column")); -// }); - -// h::delete_file_at(nu::config_path().unwrap().join("test_5.toml")); -// } diff --git a/tests/commands/append.rs b/tests/commands/append.rs new file mode 100644 index 000000000..96ada1576 --- /dev/null +++ b/tests/commands/append.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn adds_a_row_to_the_end() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open fileA.txt + | lines + | append "testme" + | nth 3 + | echo $it + "# + )); + + assert_eq!(actual, "testme"); +} diff --git a/tests/command_cd_tests.rs b/tests/commands/cd.rs similarity index 98% rename from tests/command_cd_tests.rs rename to tests/commands/cd.rs index 1f67bf7fa..bc295d8f9 100644 --- a/tests/command_cd_tests.rs +++ b/tests/commands/cd.rs @@ -1,7 +1,7 @@ -mod helpers; - -use helpers::{Playground, Stub::*}; use std::path::PathBuf; +use test_support::fs::{Stub::EmptyFile, Stub::FileWithContent}; +use test_support::playground::Playground; +use test_support::{nu, nu_error}; #[test] fn filesystem_change_from_current_directory_using_relative_path() { diff --git a/tests/commands/compact.rs b/tests/commands/compact.rs new file mode 100644 index 000000000..6e90fc1cf --- /dev/null +++ b/tests/commands/compact.rs @@ -0,0 +1,52 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn discards_rows_where_given_column_is_empty() { + Playground::setup("compact_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.json", + r#" + { + "amigos": [ + {"name": "Yehuda", "rusty_luck": 1}, + {"name": "Jonathan", "rusty_luck": 1}, + {"name": "Andres", "rusty_luck": 1}, + {"name":"GorbyPuff"} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.json + | get amigos + | compact rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }); +} +#[test] +fn discards_empty_rows_by_default() { + Playground::setup("compact_test_2", |dirs, _| { + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + echo "[1,2,3,14,null]" + | from-json + | compact + | count + | echo $it + "# + )); + + assert_eq!(actual, "4"); + }); +} diff --git a/tests/command_cp_tests.rs b/tests/commands/cp.rs similarity index 97% rename from tests/command_cp_tests.rs rename to tests/commands/cp.rs index 804cfc016..4d6843998 100644 --- a/tests/command_cp_tests.rs +++ b/tests/commands/cp.rs @@ -1,9 +1,7 @@ -mod helpers; - -use nu::AbsoluteFile; - -use helpers::{files_exist_at, Playground, Stub::*}; use std::path::Path; +use test_support::fs::{files_exist_at, AbsoluteFile, Stub::EmptyFile}; +use test_support::playground::Playground; +use test_support::{nu, nu_error}; #[test] fn copies_a_file() { diff --git a/tests/commands/default.rs b/tests/commands/default.rs new file mode 100644 index 000000000..35f3fb52a --- /dev/null +++ b/tests/commands/default.rs @@ -0,0 +1,36 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn adds_row_data_if_column_missing() { + Playground::setup("default_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.json", + r#" + { + "amigos": [ + {"name": "Yehuda"}, + {"name": "Jonathan", "rusty_luck": 0}, + {"name": "Andres", "rusty_luck": 0}, + {"name":"GorbyPuff"} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.json + | get amigos + | default rusty_luck 1 + | where rusty_luck == 1 + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }); +} diff --git a/tests/commands/edit.rs b/tests/commands/edit.rs new file mode 100644 index 000000000..553c879b4 --- /dev/null +++ b/tests/commands/edit.rs @@ -0,0 +1,16 @@ +use test_support::{nu, pipeline}; + +#[test] +fn creates_a_new_table_with_the_new_row_given() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml + | edit dev-dependencies.pretty_assertions "7" + | get dev-dependencies.pretty_assertions + | echo $it + "# + )); + + assert_eq!(actual, "7"); +} diff --git a/tests/command_enter_test.rs b/tests/commands/enter.rs similarity index 91% rename from tests/command_enter_test.rs rename to tests/commands/enter.rs index fc4a437a2..8d401eb4f 100644 --- a/tests/command_enter_test.rs +++ b/tests/commands/enter.rs @@ -1,9 +1,7 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; - use std::path::Path; +use test_support::fs::{files_exist_at, Stub::EmptyFile}; +use test_support::playground::Playground; +use test_support::{nu, nu_error}; #[test] fn knows_the_filesystems_entered() { @@ -53,7 +51,7 @@ fn knows_the_filesystems_entered() { ); assert!(!red_pill_dir.exists()); - assert!(h::files_exist_at( + assert!(files_exist_at( vec![ Path::new("andres.nu"), Path::new("jonathan.nu"), @@ -63,7 +61,7 @@ fn knows_the_filesystems_entered() { )); assert!(!blue_pill_dir.exists()); - assert!(h::files_exist_at( + assert!(files_exist_at( vec![ Path::new("bash.nxt"), Path::new("korn.nxt"), diff --git a/tests/commands/first.rs b/tests/commands/first.rs new file mode 100644 index 000000000..a57cf074c --- /dev/null +++ b/tests/commands/first.rs @@ -0,0 +1,70 @@ +use test_support::fs::Stub::EmptyFile; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn gets_first_rows_by_amount() { + Playground::setup("first_test_1", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("los.txt"), + EmptyFile("tres.txt"), + EmptyFile("amigos.txt"), + EmptyFile("arepas.clu"), + ]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | first 3 + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn gets_all_rows_if_amount_higher_than_all_rows() { + Playground::setup("first_test_2", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("los.txt"), + EmptyFile("tres.txt"), + EmptyFile("amigos.txt"), + EmptyFile("arepas.clu"), + ]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | first 99 + | count + | echo $it + "# + )); + + assert_eq!(actual, "4"); + }) +} + +#[test] +fn gets_first_row_when_no_amount_given() { + Playground::setup("first_test_3", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | first + | count + | echo $it + "# + )); + + assert_eq!(actual, "1"); + }) +} diff --git a/tests/commands/format.rs b/tests/commands/format.rs new file mode 100644 index 000000000..e029f9039 --- /dev/null +++ b/tests/commands/format.rs @@ -0,0 +1,16 @@ +use test_support::{nu, pipeline}; + +#[test] +fn creates_the_resulting_string_from_the_given_fields() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml + | get package + | format "{name} has license {license}" + | echo $it + "# + )); + + assert_eq!(actual, "nu has license ISC"); +} diff --git a/tests/command_get_tests.rs b/tests/commands/get.rs similarity index 91% rename from tests/command_get_tests.rs rename to tests/commands/get.rs index d03c5ccac..8e3714dca 100644 --- a/tests/command_get_tests.rs +++ b/tests/commands/get.rs @@ -1,10 +1,9 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; +use test_support::fs::Stub::FileWithContent; +use test_support::playground::Playground; +use test_support::{nu, nu_error, pipeline}; #[test] -fn get() { +fn fetches_a_row() { Playground::setup("get_test_1", |dirs, sandbox| { sandbox.with_files(vec![FileWithContent( "sample.toml", @@ -14,7 +13,7 @@ fn get() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get nu_party_venue @@ -41,7 +40,7 @@ fn fetches_by_index() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get package.authors.2 @@ -64,7 +63,7 @@ fn fetches_by_column_path() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get package.name @@ -89,7 +88,7 @@ fn column_paths_are_either_double_quoted_or_regular_unquoted_words_separated_by_ )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get package."9999" @@ -123,7 +122,7 @@ fn fetches_more_than_one_column_path() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get fortune_tellers.2.name fortune_tellers.0.name fortune_tellers.1.name @@ -148,7 +147,7 @@ fn errors_fetching_by_column_not_present() { )]); let actual = nu_error!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get taco @@ -173,7 +172,7 @@ fn errors_fetching_by_column_using_a_number() { )]); let actual = nu_error!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get spanish_lesson.9 @@ -196,7 +195,7 @@ fn errors_fetching_by_index_out_of_bounds() { )]); let actual = nu_error!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get spanish_lesson.sentence_words.3 diff --git a/tests/commands/group_by.rs b/tests/commands/group_by.rs new file mode 100644 index 000000000..4a83f4495 --- /dev/null +++ b/tests/commands/group_by.rs @@ -0,0 +1,56 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, nu_error, pipeline}; + +#[test] +fn groups() { + Playground::setup("group_by_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.csv", + r#" + first_name,last_name,rusty_at,type + Andrés,Robalino,10/11/2013,A + Jonathan,Turner,10/12/2013,B + Yehuda,Katz,10/11/2013,A + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.csv + | group-by rusty_at + | get "10/11/2013" + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }) +} + +#[test] +fn errors_if_given_unknown_column_name_is_missing() { + Playground::setup("group_by_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.csv", + r#" + first_name,last_name,rusty_at,type + Andrés,Robalino,10/11/2013,A + Jonathan,Turner,10/12/2013,B + Yehuda,Katz,10/11/2013,A + "#, + )]); + + let actual = nu_error!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.csv + | group-by ttype + "# + )); + + assert!(actual.contains("Unknown column")); + }) +} diff --git a/tests/commands/histogram.rs b/tests/commands/histogram.rs new file mode 100644 index 000000000..b9f44b72b --- /dev/null +++ b/tests/commands/histogram.rs @@ -0,0 +1,32 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn summarizes() { + Playground::setup("histogram_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.csv", + r#" + first_name,last_name,rusty_at + Andrés,Robalino,Ecuador + Jonathan,Turner,Estados Unidos + Yehuda,Katz,Estados Unidos + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.csv + | histogram rusty_at countries + | where rusty_at == "Ecuador" + | get countries + | echo $it + "# + )); + + assert_eq!(actual, "**************************************************"); + // 50% + }) +} diff --git a/tests/commands/insert.rs b/tests/commands/insert.rs new file mode 100644 index 000000000..3c7bda415 --- /dev/null +++ b/tests/commands/insert.rs @@ -0,0 +1,16 @@ +use test_support::{nu, pipeline}; + +#[test] +fn insert_plugin() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml + | insert dev-dependencies.newdep "1" + | get dev-dependencies.newdep + | echo $it + "# + )); + + assert_eq!(actual, "1"); +} diff --git a/tests/commands/last.rs b/tests/commands/last.rs new file mode 100644 index 000000000..0d5aa82f3 --- /dev/null +++ b/tests/commands/last.rs @@ -0,0 +1,56 @@ +use test_support::fs::Stub::EmptyFile; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn gets_the_last_row() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "ls | sort-by name | last 1 | get name | trim | echo $it" + ); + + assert_eq!(actual, "utf16.ini"); +} + +#[test] +fn gets_last_rows_by_amount() { + Playground::setup("last_test_1", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("los.txt"), + EmptyFile("tres.txt"), + EmptyFile("amigos.txt"), + EmptyFile("arepas.clu"), + ]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | last 3 + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn gets_last_row_when_no_amount_given() { + Playground::setup("last_test_2", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | last + | count + | echo $it + "# + )); + + assert_eq!(actual, "1"); + }) +} diff --git a/tests/commands/lines.rs b/tests/commands/lines.rs new file mode 100644 index 000000000..e09a710d0 --- /dev/null +++ b/tests/commands/lines.rs @@ -0,0 +1,21 @@ +use test_support::{nu, pipeline}; + +#[test] +fn lines() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml --raw + | lines + | skip-while $it != "[dependencies]" + | skip 1 + | first 1 + | split-column "=" + | get Column1 + | trim + | echo $it + "# + )); + + assert_eq!(actual, "rustyline"); +} diff --git a/tests/command_ls_tests.rs b/tests/commands/ls.rs similarity index 78% rename from tests/command_ls_tests.rs rename to tests/commands/ls.rs index a0ae959e1..91464b8ca 100644 --- a/tests/command_ls_tests.rs +++ b/tests/commands/ls.rs @@ -1,10 +1,9 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; +use test_support::fs::Stub::EmptyFile; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; #[test] -fn ls_lists_regular_files() { +fn lists_regular_files() { Playground::setup("ls_test_1", |dirs, sandbox| { sandbox.with_files(vec![ EmptyFile("yehuda.txt"), @@ -13,7 +12,7 @@ fn ls_lists_regular_files() { ]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" ls | count @@ -26,7 +25,7 @@ fn ls_lists_regular_files() { } #[test] -fn ls_lists_regular_files_using_asterisk_wildcard() { +fn lists_regular_files_using_asterisk_wildcard() { Playground::setup("ls_test_2", |dirs, sandbox| { sandbox.with_files(vec![ EmptyFile("los.txt"), @@ -36,7 +35,7 @@ fn ls_lists_regular_files_using_asterisk_wildcard() { ]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" ls *.txt | count @@ -49,7 +48,7 @@ fn ls_lists_regular_files_using_asterisk_wildcard() { } #[test] -fn ls_lists_regular_files_using_question_mark_wildcard() { +fn lists_regular_files_using_question_mark_wildcard() { Playground::setup("ls_test_3", |dirs, sandbox| { sandbox.with_files(vec![ EmptyFile("yehuda.10.txt"), @@ -59,7 +58,7 @@ fn ls_lists_regular_files_using_question_mark_wildcard() { ]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" ls *.??.txt | count diff --git a/tests/command_mkdir_tests.rs b/tests/commands/mkdir.rs similarity index 87% rename from tests/command_mkdir_tests.rs rename to tests/commands/mkdir.rs index 40ad0a9ce..86ceed3bb 100644 --- a/tests/command_mkdir_tests.rs +++ b/tests/commands/mkdir.rs @@ -1,9 +1,7 @@ -mod helpers; - -use helpers as h; -use helpers::Playground; - use std::path::Path; +use test_support::fs::files_exist_at; +use test_support::nu; +use test_support::playground::Playground; #[test] fn creates_directory() { @@ -27,7 +25,7 @@ fn accepts_and_creates_directories() { "mkdir dir_1 dir_2 dir_3" ); - assert!(h::files_exist_at( + assert!(files_exist_at( vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")], dirs.test() )); diff --git a/tests/commands/mod.rs b/tests/commands/mod.rs new file mode 100644 index 000000000..badd7628f --- /dev/null +++ b/tests/commands/mod.rs @@ -0,0 +1,30 @@ +mod append; +mod cd; +mod compact; +mod cp; +mod default; +mod edit; +mod enter; +mod first; +mod format; +mod get; +mod group_by; +mod histogram; +mod insert; +mod last; +mod lines; +mod ls; +mod mkdir; +mod mv; +mod open; +mod parse; +mod prepend; +mod range; +mod reverse; +mod rm; +mod save; +mod sort_by; +mod split_by; +mod split_column; +mod where_; +mod wrap; diff --git a/tests/command_mv_tests.rs b/tests/commands/mv.rs similarity index 96% rename from tests/command_mv_tests.rs rename to tests/commands/mv.rs index 1d01e2332..eb7d0f024 100644 --- a/tests/command_mv_tests.rs +++ b/tests/commands/mv.rs @@ -1,7 +1,6 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; +use test_support::fs::{files_exist_at, Stub::EmptyFile}; +use test_support::nu; +use test_support::playground::Playground; #[test] fn moves_a_file() { @@ -148,7 +147,7 @@ fn moves_using_path_with_wildcard() { nu!(cwd: work_dir, "mv ../originals/*.ini ../expected"); - assert!(h::files_exist_at( + assert!(files_exist_at( vec!["yehuda.ini", "jonathan.ini", "sample.ini", "andres.ini",], expected )); @@ -175,7 +174,7 @@ fn moves_using_a_glob() { nu!(cwd: work_dir, "mv ../meals/* ../expected"); assert!(meal_dir.exists()); - assert!(h::files_exist_at( + assert!(files_exist_at( vec!["arepa.txt", "empanada.txt", "taquiza.txt",], expected )); diff --git a/tests/commands/nth.rs b/tests/commands/nth.rs new file mode 100644 index 000000000..6880c0648 --- /dev/null +++ b/tests/commands/nth.rs @@ -0,0 +1,39 @@ +#[test] +fn selects_a_row() { + Playground::setup("nth_test_1", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | sort-by name + | nth 0 + | get name + | echo $it + "# + )); + + assert_eq!(actual, "arepas.txt"); + }); +} + +#[test] +fn selects_many_rows() { + Playground::setup("nth_test_2", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | get name + | nth 1 0 + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }); +} \ No newline at end of file diff --git a/tests/command_open_tests.rs b/tests/commands/open.rs similarity index 92% rename from tests/command_open_tests.rs rename to tests/commands/open.rs index 547690c76..137f7f260 100644 --- a/tests/command_open_tests.rs +++ b/tests/commands/open.rs @@ -1,10 +1,9 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, nu_error, pipeline}; #[test] -fn recognizes_csv() { +fn parses_csv() { Playground::setup("open_test_1", |dirs, sandbox| { sandbox.with_files(vec![FileWithContentToBeTrimmed( "nu.zion.csv", @@ -17,7 +16,7 @@ fn recognizes_csv() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open nu.zion.csv | where author == "Andres N. Robalino" @@ -56,7 +55,7 @@ fn recognizes_csv() { // #[test] -fn open_can_parse_bson_1() { +fn parses_bson() { let actual = nu!( cwd: "tests/fixtures/formats", "open sample.bson | get root | nth 0 | get b | echo $it" @@ -66,9 +65,9 @@ fn open_can_parse_bson_1() { } #[test] -fn open_can_parse_bson_2() { +fn parses_more_bson_complexity() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.bson | get root @@ -132,9 +131,9 @@ fn open_can_parse_bson_2() { // ━━━┷━━━━━━ #[test] -fn open_can_parse_sqlite() { +fn parses_sqlite() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | get table_values @@ -147,7 +146,7 @@ fn open_can_parse_sqlite() { } #[test] -fn open_can_parse_toml() { +fn parses_toml() { let actual = nu!( cwd: "tests/fixtures/formats", "open cargo_sample.toml | get package.edition | echo $it" @@ -157,9 +156,9 @@ fn open_can_parse_toml() { } #[test] -fn open_can_parse_tsv() { +fn parses_tsv() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open caco3_plastics.tsv | first 1 @@ -172,9 +171,9 @@ fn open_can_parse_tsv() { } #[test] -fn open_can_parse_json() { +fn parses_json() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sgml_description.json | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee @@ -186,7 +185,7 @@ fn open_can_parse_json() { } #[test] -fn open_can_parse_xml() { +fn parses_xml() { let actual = nu!( cwd: "tests/fixtures/formats", "open jonathan.xml | get rss.channel | get item | get link | echo $it" @@ -199,7 +198,7 @@ fn open_can_parse_xml() { } #[test] -fn open_can_parse_ini() { +fn parses_ini() { let actual = nu!( cwd: "tests/fixtures/formats", "open sample.ini | get SectionOne.integer | echo $it" @@ -209,7 +208,7 @@ fn open_can_parse_ini() { } #[test] -fn open_can_parse_utf16_ini() { +fn parses_utf16_ini() { let actual = nu!( cwd: "tests/fixtures/formats", "open utf16.ini | get '.ShellClassInfo' | get IconIndex | echo $it" diff --git a/tests/commands/parse.rs b/tests/commands/parse.rs new file mode 100644 index 000000000..5246c0dc7 --- /dev/null +++ b/tests/commands/parse.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn extracts_fields_from_the_given_the_pattern() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open fileA.txt + | parse "{Name}={Value}" + | nth 1 + | get Value + | echo $it + "# + )); + + assert_eq!(actual, "StupidLongName"); +} diff --git a/tests/commands/prepend.rs b/tests/commands/prepend.rs new file mode 100644 index 000000000..46c881a5f --- /dev/null +++ b/tests/commands/prepend.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn adds_a_row_to_the_beginning() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open fileA.txt + | lines + | prepend "testme" + | nth 0 + | echo $it + "# + )); + + assert_eq!(actual, "testme"); +} diff --git a/tests/commands/range.rs b/tests/commands/range.rs new file mode 100644 index 000000000..cf4fa79ba --- /dev/null +++ b/tests/commands/range.rs @@ -0,0 +1,47 @@ +use test_support::fs::Stub::EmptyFile; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn selects_a_row() { + Playground::setup("range_test_1", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("tests.txt")]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | sort-by name + | range 0..0 + | get name + | echo $it + "# + )); + + assert_eq!(actual, "notes.txt"); + }); +} + +#[test] +fn selects_some_rows() { + Playground::setup("range_test_2", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("notes.txt"), + EmptyFile("tests.txt"), + EmptyFile("persons.txt"), + ]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | get name + | range 1..2 + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }); +} diff --git a/tests/commands/reverse.rs b/tests/commands/reverse.rs new file mode 100644 index 000000000..0f0bd9f07 --- /dev/null +++ b/tests/commands/reverse.rs @@ -0,0 +1,11 @@ +use test_support::nu; + +#[test] +fn can_get_reverse_first() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "ls | sort-by name | reverse | first 1 | get name | trim | echo $it" + ); + + assert_eq!(actual, "utf16.ini"); +} diff --git a/tests/command_rm_tests.rs b/tests/commands/rm.rs similarity index 84% rename from tests/command_rm_tests.rs rename to tests/commands/rm.rs index 9317b586a..17f924430 100644 --- a/tests/command_rm_tests.rs +++ b/tests/commands/rm.rs @@ -1,10 +1,9 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; +use test_support::fs::{files_exist_at, Stub::EmptyFile}; +use test_support::playground::Playground; +use test_support::{nu, nu_error}; #[test] -fn rm_removes_a_file() { +fn removes_a_file() { Playground::setup("rm_test_1", |dirs, sandbox| { sandbox.with_files(vec![EmptyFile("i_will_be_deleted.txt")]); @@ -20,7 +19,7 @@ fn rm_removes_a_file() { } #[test] -fn rm_removes_files_with_wildcard() { +fn removes_files_with_wildcard() { Playground::setup("rm_test_2", |dirs, sandbox| { sandbox .within("src") @@ -44,7 +43,7 @@ fn rm_removes_files_with_wildcard() { r#"rm "src/*/*/*.rs""# ); - assert!(!h::files_exist_at( + assert!(!files_exist_at( vec![ "src/parser/parse/token_tree.rs", "src/parser/hir/baseline_parse.rs", @@ -61,7 +60,7 @@ fn rm_removes_files_with_wildcard() { } #[test] -fn rm_removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { +fn removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { Playground::setup("rm_test_3", |dirs, sandbox| { sandbox .within("src") @@ -85,7 +84,7 @@ fn rm_removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { "rm src/* --recursive" ); - assert!(!h::files_exist_at( + assert!(!files_exist_at( vec!["src/parser/parse", "src/parser/hir"], dirs.test() )); @@ -93,7 +92,7 @@ fn rm_removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { } #[test] -fn rm_removes_directory_contents_without_recursive_flag_if_empty() { +fn removes_directory_contents_without_recursive_flag_if_empty() { Playground::setup("rm_test_4", |dirs, _| { nu!( cwd: dirs.root(), @@ -105,7 +104,7 @@ fn rm_removes_directory_contents_without_recursive_flag_if_empty() { } #[test] -fn rm_removes_directory_contents_with_recursive_flag() { +fn removes_directory_contents_with_recursive_flag() { Playground::setup("rm_test_5", |dirs, sandbox| { sandbox.with_files(vec![ EmptyFile("yehuda.txt"), @@ -123,7 +122,7 @@ fn rm_removes_directory_contents_with_recursive_flag() { } #[test] -fn rm_errors_if_attempting_to_delete_a_directory_with_content_without_recursive_flag() { +fn errors_if_attempting_to_delete_a_directory_with_content_without_recursive_flag() { Playground::setup("rm_test_6", |dirs, sandbox| { sandbox.with_files(vec![EmptyFile("some_empty_file.txt")]); @@ -138,7 +137,7 @@ fn rm_errors_if_attempting_to_delete_a_directory_with_content_without_recursive_ } #[test] -fn rm_errors_if_attempting_to_delete_single_dot_as_argument() { +fn errors_if_attempting_to_delete_single_dot_as_argument() { Playground::setup("rm_test_7", |dirs, _| { let actual = nu_error!( cwd: dirs.root(), @@ -150,7 +149,7 @@ fn rm_errors_if_attempting_to_delete_single_dot_as_argument() { } #[test] -fn rm_errors_if_attempting_to_delete_two_dot_as_argument() { +fn errors_if_attempting_to_delete_two_dot_as_argument() { Playground::setup("rm_test_8", |dirs, _| { let actual = nu_error!( cwd: dirs.root(), diff --git a/tests/commands/save.rs b/tests/commands/save.rs new file mode 100644 index 000000000..fc1bd6864 --- /dev/null +++ b/tests/commands/save.rs @@ -0,0 +1,47 @@ +use test_support::fs::{file_contents, Stub::FileWithContent}; +use test_support::nu; +use test_support::playground::Playground; + +#[test] +fn figures_out_intelligently_where_to_write_out_with_metadata() { + Playground::setup("save_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContent( + "cargo_sample.toml", + r#" + [package] + name = "nu" + version = "0.1.1" + authors = ["Yehuda Katz "] + description = "A shell for the GitHub era" + license = "ISC" + edition = "2018" + "#, + )]); + + let subject_file = dirs.test().join("cargo_sample.toml"); + + nu!( + cwd: dirs.root(), + "open save_test_1/cargo_sample.toml | save" + ); + + let actual = file_contents(&subject_file); + assert!(actual.contains("0.1.1")); + }) +} + +#[test] +fn writes_out_csv() { + Playground::setup("save_test_2", |dirs, _| { + let expected_file = dirs.test().join("cargo_sample.csv"); + + nu!( + cwd: dirs.root(), + "open {}/cargo_sample.toml | get package | save save_test_2/cargo_sample.csv", + dirs.formats() + ); + + let actual = file_contents(expected_file); + assert!(actual.contains("[Table],A shell for the GitHub era,2018,ISC,nu,0.1.1")); + }) +} diff --git a/tests/commands/sort_by.rs b/tests/commands/sort_by.rs new file mode 100644 index 000000000..86225ee35 --- /dev/null +++ b/tests/commands/sort_by.rs @@ -0,0 +1,23 @@ +use test_support::{nu, pipeline}; + +#[test] +fn by_column() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml --raw + | lines + | skip 1 + | first 4 + | split-column "=" + | sort-by Column1 + | skip 1 + | first 1 + | get Column1 + | trim + | echo $it + "# + )); + + assert_eq!(actual, "description"); +} diff --git a/tests/commands/split_by.rs b/tests/commands/split_by.rs new file mode 100644 index 000000000..87da1f5e2 --- /dev/null +++ b/tests/commands/split_by.rs @@ -0,0 +1,55 @@ +use test_support::fs::Stub::{EmptyFile, FileWithContentToBeTrimmed}; +use test_support::playground::Playground; +use test_support::{nu, nu_error, pipeline}; + +#[test] +fn splits() { + Playground::setup("split_by_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.csv", + r#" + first_name,last_name,rusty_at,type + Andrés,Robalino,10/11/2013,A + Jonathan,Turner,10/12/2013,B + Yehuda,Katz,10/11/2013,A + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.csv + | group-by rusty_at + | split-by type + | get A."10/11/2013" + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }) +} + +#[test] +fn errors_if_no_table_given_as_input() { + Playground::setup("split_by_test_2", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("los.txt"), + EmptyFile("tres.txt"), + EmptyFile("amigos.txt"), + EmptyFile("arepas.clu"), + ]); + + let actual = nu_error!( + cwd: dirs.test(), pipeline( + r#" + ls + | get name + | split-by type + "# + )); + + assert!(actual.contains("Expected table from pipeline")); + }) +} diff --git a/tests/commands/split_column.rs b/tests/commands/split_column.rs new file mode 100644 index 000000000..d95672661 --- /dev/null +++ b/tests/commands/split_column.rs @@ -0,0 +1,20 @@ +use test_support::{nu, pipeline}; + +#[test] +fn by_column() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml --raw + | lines + | skip 1 + | first 1 + | split-column "=" + | get Column1 + | trim + | echo $it + "# + )); + + assert_eq!(actual, "name"); +} diff --git a/tests/filter_where_tests.rs b/tests/commands/where_.rs similarity index 73% rename from tests/filter_where_tests.rs rename to tests/commands/where_.rs index e802607d8..a1a0d68b1 100644 --- a/tests/filter_where_tests.rs +++ b/tests/commands/where_.rs @@ -1,11 +1,19 @@ -mod helpers; - -use helpers as h; +use test_support::{nu, pipeline}; #[test] -fn test_compare() { +fn filters_by_unit_size_comparison() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", + "ls | where size > 1kb | sort-by size | get name | first 1 | trim | echo $it" + ); + + assert_eq!(actual, "cargo_sample.toml"); +} + +#[test] +fn binary_operator_comparisons() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == ints @@ -20,7 +28,7 @@ fn test_compare() { assert_eq!(actual, "4253"); let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == ints @@ -35,7 +43,7 @@ fn test_compare() { assert_eq!(actual, "4253"); let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == ints @@ -50,7 +58,7 @@ fn test_compare() { assert_eq!(actual, "1"); let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == ints @@ -65,7 +73,7 @@ fn test_compare() { assert_eq!(actual, "1"); let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == ints @@ -81,9 +89,9 @@ fn test_compare() { } #[test] -fn test_contains() { +fn contains_operator() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == strings @@ -97,7 +105,7 @@ fn test_contains() { assert_eq!(actual, "4"); let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open sample.db | where table_name == strings diff --git a/tests/commands/wrap.rs b/tests/commands/wrap.rs new file mode 100644 index 000000000..032fa6541 --- /dev/null +++ b/tests/commands/wrap.rs @@ -0,0 +1,63 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn wrap_rows_into_a_row() { + Playground::setup("embed_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name,last_name + Andrés,Robalino + Jonathan,Turner + Yehuda,Katz + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from-csv + | wrap caballeros + | get caballeros + | nth 0 + | get last_name + | echo $it + "# + )); + + assert_eq!(actual, "Robalino"); + }) +} + +#[test] +fn wrap_rows_into_a_table() { + Playground::setup("embed_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name,last_name + Andrés,Robalino + Jonathan,Turner + Yehuda,Katz + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from-csv + | get last_name + | wrap caballero + | nth 2 + | get caballero + | echo $it + "# + )); + + assert_eq!(actual, "Katz"); + }) +} diff --git a/tests/commands_test.rs b/tests/commands_test.rs deleted file mode 100644 index 7b607830a..000000000 --- a/tests/commands_test.rs +++ /dev/null @@ -1,564 +0,0 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; - -#[test] -fn nth_selects_a_row() { - Playground::setup("nth_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | sort-by name - | nth 0 - | get name - | echo $it - "# - )); - - assert_eq!(actual, "arepas.txt"); - }); -} - -#[test] -fn nth_selects_many_rows() { - Playground::setup("nth_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | get name - | nth 1 0 - | count - | echo $it - "# - )); - - assert_eq!(actual, "2"); - }); -} -#[test] -fn default_row_data_if_column_missing() { - Playground::setup("default_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.json", - r#" - { - "amigos": [ - {"name": "Yehuda"}, - {"name": "Jonathan", "rusty_luck": 0}, - {"name": "Andres", "rusty_luck": 0}, - {"name":"GorbyPuff"} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_amigos.json - | get amigos - | default rusty_luck 1 - | where rusty_luck == 1 - | count - | echo $it - "# - )); - - assert_eq!(actual, "2"); - }); -} -#[test] -fn compact_rows_where_given_column_is_empty() { - Playground::setup("compact_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.json", - r#" - { - "amigos": [ - {"name": "Yehuda", "rusty_luck": 1}, - {"name": "Jonathan", "rusty_luck": 1}, - {"name": "Andres", "rusty_luck": 1}, - {"name":"GorbyPuff"} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_amigos.json - | get amigos - | compact rusty_luck - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }); -} -#[test] -fn compact_empty_rows_by_default() { - Playground::setup("compact_test_2", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - echo "[1,2,3,14,null]" - | from-json - | compact - | count - | echo $it - "# - )); - - assert_eq!(actual, "4"); - }); -} -#[test] -fn group_by() { - Playground::setup("group_by_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.csv - | group-by rusty_at - | get "10/11/2013" - | count - | echo $it - "# - )); - - assert_eq!(actual, "2"); - }) -} - -#[test] -fn histogram() { - Playground::setup("histogram_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at - Andrés,Robalino,Ecuador - Jonathan,Turner,Estados Unidos - Yehuda,Katz,Estados Unidos - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.csv - | histogram rusty_at countries - | where rusty_at == "Ecuador" - | get countries - | echo $it - "# - )); - - assert_eq!(actual, "**************************************************"); - // 50% - }) -} - -#[test] -fn group_by_errors_if_unknown_column_name() { - Playground::setup("group_by_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu_error!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.csv - | group-by ttype - "# - )); - - assert!(actual.contains("Unknown column")); - }) -} - -#[test] -fn range_selects_a_row() { - Playground::setup("range_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("tests.txt")]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | sort-by name - | range 0..0 - | get name - | echo $it - "# - )); - - assert_eq!(actual, "notes.txt"); - }); -} - -#[test] -fn range_selects_some_rows() { - Playground::setup("range_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("notes.txt"), - EmptyFile("tests.txt"), - EmptyFile("persons.txt"), - ]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | get name - | range 1..2 - | count - | echo $it - "# - )); - - assert_eq!(actual, "2"); - }); -} - -#[test] -fn split_by() { - Playground::setup("split_by_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.csv", - r#" - first_name,last_name,rusty_at,type - Andrés,Robalino,10/11/2013,A - Jonathan,Turner,10/12/2013,B - Yehuda,Katz,10/11/2013,A - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.csv - | group-by rusty_at - | split-by type - | get A."10/11/2013" - | count - | echo $it - "# - )); - - assert_eq!(actual, "2"); - }) -} - -#[test] -fn split_by_errors_if_no_table_given_as_input() { - Playground::setup("split_by_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu_error!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | get name - | split-by type - "# - )); - - assert!(actual.contains("Expected table from pipeline")); - }) -} - -#[test] -fn first_gets_first_rows_by_amount() { - Playground::setup("first_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | first 3 - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn first_gets_all_rows_if_amount_higher_than_all_rows() { - Playground::setup("first_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | first 99 - | count - | echo $it - "# - )); - - assert_eq!(actual, "4"); - }) -} - -#[test] -fn first_gets_first_row_when_no_amount_given() { - Playground::setup("first_test_3", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | first - | count - | echo $it - "# - )); - - assert_eq!(actual, "1"); - }) -} - -#[test] -fn last_gets_last_rows_by_amount() { - Playground::setup("last_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ - EmptyFile("los.txt"), - EmptyFile("tres.txt"), - EmptyFile("amigos.txt"), - EmptyFile("arepas.clu"), - ]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | last 3 - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn last_gets_last_row_when_no_amount_given() { - Playground::setup("last_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - ls - | last - | count - | echo $it - "# - )); - - assert_eq!(actual, "1"); - }) -} - -#[test] -fn get() { - Playground::setup("get_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - nu_party_venue = "zion" - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open sample.toml - | get nu_party_venue - | echo $it - "# - )); - - assert_eq!(actual, "zion"); - }) -} - -#[test] -fn get_more_than_one_member() { - Playground::setup("get_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "sample.toml", - r#" - [[fortune_tellers]] - name = "Andrés N. Robalino" - arepas = 1 - broken_builds = 0 - - [[fortune_tellers]] - name = "Jonathan Turner" - arepas = 1 - broken_builds = 1 - - [[fortune_tellers]] - name = "Yehuda Katz" - arepas = 1 - broken_builds = 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open sample.toml - | get fortune_tellers - | get arepas broken_builds - | where $it == 1 - | count - | echo $it - "# - )); - - assert_eq!(actual, "5"); - }) -} - -#[test] -fn lines() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip-while $it != "[dependencies]" - | skip 1 - | first 1 - | split-column "=" - | get Column1 - | trim - | echo $it - "# - )); - - assert_eq!(actual, "rustyline"); -} - -#[test] -fn save_figures_out_intelligently_where_to_write_out_with_metadata() { - Playground::setup("save_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( - "cargo_sample.toml", - r#" - [package] - name = "nu" - version = "0.1.1" - authors = ["Yehuda Katz "] - description = "A shell for the GitHub era" - license = "ISC" - edition = "2018" - "#, - )]); - - let subject_file = dirs.test().join("cargo_sample.toml"); - - nu!( - cwd: dirs.root(), - "open save_test_1/cargo_sample.toml | save" - ); - - let actual = h::file_contents(&subject_file); - assert!(actual.contains("0.1.1")); - }) -} - -#[test] -fn it_arg_works_with_many_inputs_to_external_command() { - Playground::setup("it_arg_works_with_many_inputs", |dirs, sandbox| { - sandbox.with_files(vec![ - FileWithContent("file1", "text"), - FileWithContent("file2", " and more text"), - ]); - - let (stdout, stderr) = nu_combined!( - cwd: dirs.test(), h::pipeline( - r#" - echo hello world - | split-row " " - | ^echo $it - "# - )); - - #[cfg(windows)] - assert_eq!("hello world", stdout); - - #[cfg(not(windows))] - assert_eq!("helloworld", stdout); - - assert!(!stderr.contains("No such file or directory")); - }) -} - -#[test] -fn save_can_write_out_csv() { - Playground::setup("save_test_2", |dirs, _| { - let expected_file = dirs.test().join("cargo_sample.csv"); - - nu!( - cwd: dirs.root(), - "open {}/cargo_sample.toml | get package | save save_test_2/cargo_sample.csv", - dirs.formats() - ); - - let actual = h::file_contents(expected_file); - assert!(actual.contains("[Table],A shell for the GitHub era,2018,ISC,nu,0.1.1")); - }) -} diff --git a/tests/converting_formats/bson.rs b/tests/converting_formats/bson.rs new file mode 100644 index 000000000..5ed9515c4 --- /dev/null +++ b/tests/converting_formats/bson.rs @@ -0,0 +1,18 @@ +use test_support::{nu, pipeline}; + +#[test] +fn table_to_bson_and_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.bson + | to-bson + | from-bson + | get root + | get 1.b + | echo $it + "# + )); + + assert_eq!(actual, "whel"); +} diff --git a/tests/converting_formats/csv.rs b/tests/converting_formats/csv.rs new file mode 100644 index 000000000..56190f56d --- /dev/null +++ b/tests/converting_formats/csv.rs @@ -0,0 +1,184 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn table_to_csv_text_and_from_csv_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it" + ); + + assert_eq!(actual, "SPAIN"); +} + +#[test] +fn table_to_csv_text() { + Playground::setup("filter_to_csv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "csv_text_sample.txt", + r#" + importer,shipper,tariff_item,name,origin + Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain + Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open csv_text_sample.txt + | lines + | trim + | split-column "," a b c d origin + | last 1 + | to-csv + | lines + | nth 1 + | echo $it + "# + )); + + assert!(actual.contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); + }) +} + +#[test] +fn table_to_csv_text_skipping_headers_after_conversion() { + Playground::setup("filter_to_csv_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "csv_text_sample.txt", + r#" + importer,shipper,tariff_item,name,origin + Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain + Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open csv_text_sample.txt + | lines + | trim + | split-column "," a b c d origin + | last 1 + | to-csv --headerless + | echo $it + "# + )); + + assert!(actual.contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); + }) +} + +#[test] +fn from_csv_text_to_table() { + Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name,last_name,rusty_luck + Andrés,Robalino,1 + Jonathan,Turner,1 + Yehuda,Katz,1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from-csv + | get rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn from_csv_text_with_separator_to_table() { + Playground::setup("filter_from_csv_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name;last_name;rusty_luck + Andrés;Robalino;1 + Jonathan;Turner;1 + Yehuda;Katz;1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from-csv --separator ';' + | get rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn from_csv_text_with_tab_separator_to_table() { + Playground::setup("filter_from_csv_test_3", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_caballeros.txt", + r#" + first_name last_name rusty_luck + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_caballeros.txt + | from-csv --separator '\t' + | get rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn from_csv_text_skipping_headers_to_table() { + Playground::setup("filter_from_csv_test_4", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.txt", + r#" + Andrés,Robalino,1 + Jonathan,Turner,1 + Yehuda,Katz,1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.txt + | from-csv --headerless + | get Column3 + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} diff --git a/tests/converting_formats/json.rs b/tests/converting_formats/json.rs new file mode 100644 index 000000000..b1da5218a --- /dev/null +++ b/tests/converting_formats/json.rs @@ -0,0 +1,103 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn table_to_json_text_and_from_json_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sgml_description.json + | to-json + | from-json + | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee + | echo $it + "# + )); + + assert_eq!(actual, "markup"); +} + +#[test] +fn from_json_text_to_table() { + Playground::setup("filter_from_json_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "katz.txt", + r#" + { + "katz": [ + {"name": "Yehuda", "rusty_luck": 1}, + {"name": "Jonathan", "rusty_luck": 1}, + {"name": "Andres", "rusty_luck": 1}, + {"name":"GorbyPuff", "rusty_luck": 1} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), + "open katz.txt | from-json | get katz | get rusty_luck | count | echo $it" + ); + + assert_eq!(actual, "4"); + }) +} + +#[test] +fn from_json_text_recognizing_objects_independently_to_table() { + Playground::setup("filter_from_json_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "katz.txt", + r#" + {"name": "Yehuda", "rusty_luck": 1} + {"name": "Jonathan", "rusty_luck": 1} + {"name": "Andres", "rusty_luck": 1} + {"name":"GorbyPuff", "rusty_luck": 3} + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open katz.txt + | from-json --objects + | where name == "GorbyPuff" + | get rusty_luck + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn table_to_json_text() { + Playground::setup("filter_to_json_test", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "sample.txt", + r#" + JonAndrehudaTZ,3 + GorbyPuff,100 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open sample.txt + | lines + | split-column "," name luck + | pick name + | to-json + | from-json + | nth 0 + | get name + | echo $it + "# + )); + + assert_eq!(actual, "JonAndrehudaTZ"); + }) +} diff --git a/tests/converting_formats/mod.rs b/tests/converting_formats/mod.rs new file mode 100644 index 000000000..eff8d6855 --- /dev/null +++ b/tests/converting_formats/mod.rs @@ -0,0 +1,10 @@ +mod bson; +mod csv; +mod json; +mod sqlite; +mod ssv; +mod toml; +mod tsv; +mod url; +mod xlsx; +mod yaml; diff --git a/tests/converting_formats/sqlite.rs b/tests/converting_formats/sqlite.rs new file mode 100644 index 000000000..ee6a57b4a --- /dev/null +++ b/tests/converting_formats/sqlite.rs @@ -0,0 +1,19 @@ +use test_support::{nu, pipeline}; + +#[test] +fn table_to_sqlite_and_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.db + | to-sqlite + | from-sqlite + | get table_values + | nth 2 + | get x + | echo $it + "# + )); + + assert_eq!(actual, "hello"); +} diff --git a/tests/converting_formats/ssv.rs b/tests/converting_formats/ssv.rs new file mode 100644 index 000000000..e6f09afd9 --- /dev/null +++ b/tests/converting_formats/ssv.rs @@ -0,0 +1,98 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn from_ssv_text_to_table() { + Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + NAME LABELS SELECTOR IP PORT(S) + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from-ssv + | nth 0 + | get IP + | echo $it + "# + )); + + assert_eq!(actual, "172.30.78.158"); + }) +} + +#[test] +fn from_ssv_text_to_table_with_separator_specified() { + Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + NAME LABELS SELECTOR IP PORT(S) + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from-ssv --minimum-spaces 3 + | nth 0 + | get IP + | echo $it + "# + )); + + assert_eq!(actual, "172.30.78.158"); + }) +} + +#[test] +fn from_ssv_text_treating_first_line_as_data_with_flag() { + Playground::setup("filter_from_ssv_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "oc_get_svc.txt", + r#" + docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP + kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP + kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP + "#, + )]); + + let aligned_columns = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from-ssv --headerless --aligned-columns + | first + | get Column1 + | echo $it + "# + )); + + let separator_based = nu!( + cwd: dirs.test(), pipeline( + r#" + open oc_get_svc.txt + | from-ssv --headerless + | first + | get Column1 + | echo $it + "# + )); + + assert_eq!(aligned_columns, separator_based); + assert_eq!(separator_based, "docker-registry"); + }) +} diff --git a/tests/converting_formats/toml.rs b/tests/converting_formats/toml.rs new file mode 100644 index 000000000..b92aed37c --- /dev/null +++ b/tests/converting_formats/toml.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn table_to_toml_text_and_from_toml_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open cargo_sample.toml + | to-toml + | from-toml + | get package.name + | echo $it + "# + )); + + assert_eq!(actual, "nu"); +} diff --git a/tests/converting_formats/tsv.rs b/tests/converting_formats/tsv.rs new file mode 100644 index 000000000..24b181b89 --- /dev/null +++ b/tests/converting_formats/tsv.rs @@ -0,0 +1,136 @@ +use test_support::fs::Stub::FileWithContentToBeTrimmed; +use test_support::playground::Playground; +use test_support::{nu, pipeline}; + +#[test] +fn table_to_tsv_text_and_from_tsv_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "open caco3_plastics.tsv | to-tsv | from-tsv | first 1 | get origin | echo $it" + ); + + assert_eq!(actual, "SPAIN"); +} + +#[test] +fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() { + let actual = nu!( + cwd: "tests/fixtures/formats", + r"open caco3_plastics.tsv | to-tsv | from-csv --separator '\t' | first 1 | get origin | echo $it" + ); + + assert_eq!(actual, "SPAIN"); +} + +#[test] +fn table_to_tsv_text() { + Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "tsv_text_sample.txt", + r#" + importer shipper tariff_item name origin + Plasticos Rival Reverte 2509000000 Calcium carbonate Spain + Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open tsv_text_sample.txt + | lines + | split-column "\t" a b c d origin + | last 1 + | to-tsv + | lines + | nth 1 + | echo $it + "# + )); + + assert!(actual.contains("Colombia")); + }) +} + +#[test] +fn table_to_tsv_text_skipping_headers_after_conversion() { + Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "tsv_text_sample.txt", + r#" + importer shipper tariff_item name origin + Plasticos Rival Reverte 2509000000 Calcium carbonate Spain + Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open tsv_text_sample.txt + | lines + | split-column "\t" a b c d origin + | last 1 + | to-tsv --headerless + | echo $it + "# + )); + + assert!(actual.contains("Colombia")); + }) +} + +#[test] +fn from_tsv_text_to_table() { + Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.txt", + r#" + first Name Last Name rusty_luck + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.txt + | from-tsv + | get rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} + +#[test] +fn from_tsv_text_skipping_headers_to_table() { + Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.txt", + r#" + Andrés Robalino 1 + Jonathan Turner 1 + Yehuda Katz 1 + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + open los_tres_amigos.txt + | from-tsv --headerless + | get Column3 + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }) +} diff --git a/tests/converting_formats/url.rs b/tests/converting_formats/url.rs new file mode 100644 index 000000000..1cc49f000 --- /dev/null +++ b/tests/converting_formats/url.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn can_encode_and_decode_urlencoding() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample.url + | to-url + | from-url + | get cheese + | echo $it + "# + )); + + assert_eq!(actual, "comté"); +} diff --git a/tests/converting_formats/xlsx.rs b/tests/converting_formats/xlsx.rs new file mode 100644 index 000000000..973af0954 --- /dev/null +++ b/tests/converting_formats/xlsx.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn from_excel_file_to_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample_data.xlsx + | get SalesOrders + | nth 4 + | get Column2 + | echo $it + "# + )); + + assert_eq!(actual, "Gill"); +} diff --git a/tests/converting_formats/yaml.rs b/tests/converting_formats/yaml.rs new file mode 100644 index 000000000..2f8ad4037 --- /dev/null +++ b/tests/converting_formats/yaml.rs @@ -0,0 +1,17 @@ +use test_support::{nu, pipeline}; + +#[test] +fn table_to_yaml_text_and_from_yaml_text_back_into_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open appveyor.yml + | to-yaml + | from-yaml + | get environment.global.PROJECT_NAME + | echo $it + "# + )); + + assert_eq!(actual, "nushell"); +} diff --git a/tests/external_tests.rs b/tests/external_tests.rs deleted file mode 100644 index 6b3c3fac5..000000000 --- a/tests/external_tests.rs +++ /dev/null @@ -1,42 +0,0 @@ -mod helpers; - -use helpers::Playground; - -#[test] -fn external_command() { - let actual = nu!( - cwd: "tests/fixtures", - "echo 1" - ); - - assert!(actual.contains("1")); -} - -#[test] -fn spawn_external_process_with_home_in_arguments() { - Playground::setup("echo_tilde", |dirs, _| { - let actual = nu!( - cwd: dirs.test(), - r#" - sh -c "echo ~" - "# - ); - - assert!( - !actual.contains("~"), - format!("'{}' should not contain ~", actual) - ); - }) -} - -#[test] -fn spawn_external_process_with_tilde_in_arguments() { - let actual = nu!( - cwd: "tests/fixtures", - r#" - sh -c "echo 1~1" - "# - ); - - assert_eq!(actual, "1~1"); -} diff --git a/tests/filters.rs b/tests/filters.rs new file mode 100644 index 000000000..ecdeebc68 --- /dev/null +++ b/tests/filters.rs @@ -0,0 +1,43 @@ +// use test_support::{nu, pipeline}; +// use test_support::playground::Playground; +// use test_support::fs::Stub::FileWithContentToBeTrimmed; + +// #[test] +// fn can_sum() { +// let actual = nu!( +// cwd: "tests/fixtures/formats", h::pipeline( +// r#" +// open sgml_description.json +// | get glossary.GlossDiv.GlossList.GlossEntry.Sections +// | sum +// | echo $it +// "# +// )); + +// assert_eq!(actual, "203") +// } + +// #[test] +// fn can_average_numbers() { +// let actual = nu!( +// cwd: "tests/fixtures/formats", h::pipeline( +// r#" +// open sgml_description.json +// | get glossary.GlossDiv.GlossList.GlossEntry.Sections +// | average +// | echo $it +// "# +// )); + +// assert_eq!(actual, "101.5000000000000") +// } + +// #[test] +// fn can_average_bytes() { +// let actual = nu!( +// cwd: "tests/fixtures/formats", +// "ls | sort-by name | skip 1 | first 2 | get size | average | echo $it" +// ); + +// assert_eq!(actual, "1600.000000000000"); +// } diff --git a/tests/filters_test.rs b/tests/filters_test.rs deleted file mode 100644 index 4eaab8c89..000000000 --- a/tests/filters_test.rs +++ /dev/null @@ -1,811 +0,0 @@ -mod helpers; - -use helpers as h; -use helpers::{Playground, Stub::*}; - -#[test] -fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it" - ); - - assert_eq!(actual, "SPAIN"); -} - -#[test] -fn converts_structured_table_to_csv_text() { - Playground::setup("filter_to_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "csv_text_sample.txt", - r#" - importer,shipper,tariff_item,name,origin - Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain - Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open csv_text_sample.txt - | lines - | trim - | split-column "," a b c d origin - | last 1 - | to-csv - | lines - | nth 1 - | echo $it - "# - )); - - assert!(actual.contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); - }) -} - -#[test] -fn converts_structured_table_to_csv_text_skipping_headers_after_conversion() { - Playground::setup("filter_to_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "csv_text_sample.txt", - r#" - importer,shipper,tariff_item,name,origin - Plasticos Rival,Reverte,2509000000,Calcium carbonate,Spain - Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open csv_text_sample.txt - | lines - | trim - | split-column "," a b c d origin - | last 1 - | to-csv --headerless - | echo $it - "# - )); - - assert!(actual.contains("Tigre Ecuador,OMYA Andina,3824909999,Calcium carbonate,Colombia")); - }) -} - -#[test] -fn converts_from_csv_text_to_structured_table() { - Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name,rusty_luck - Andrés,Robalino,1 - Jonathan,Turner,1 - Yehuda,Katz,1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv - | get rusty_luck - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_from_csv_text_with_separator_to_structured_table() { - Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name;last_name;rusty_luck - Andrés;Robalino;1 - Jonathan;Turner;1 - Yehuda;Katz;1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv --separator ';' - | get rusty_luck - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_from_csv_text_with_tab_separator_to_structured_table() { - Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name last_name rusty_luck - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv --separator '\t' - | get rusty_luck - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_from_csv_text_skipping_headers_to_structured_table() { - Playground::setup("filter_from_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - Andrés,Robalino,1 - Jonathan,Turner,1 - Yehuda,Katz,1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_amigos.txt - | from-csv --headerless - | get Column3 - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn can_convert_table_to_json_text_and_from_json_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open sgml_description.json - | to-json - | from-json - | get glossary.GlossDiv.GlossList.GlossEntry.GlossSee - | echo $it - "# - )); - - assert_eq!(actual, "markup"); -} - -#[test] -fn converts_from_json_text_to_structured_table() { - Playground::setup("filter_from_json_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.txt", - r#" - { - "katz": [ - {"name": "Yehuda", "rusty_luck": 1}, - {"name": "Jonathan", "rusty_luck": 1}, - {"name": "Andres", "rusty_luck": 1}, - {"name":"GorbyPuff", "rusty_luck": 1} - ] - } - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), - "open katz.txt | from-json | get katz | get rusty_luck | count | echo $it" - ); - - assert_eq!(actual, "4"); - }) -} - -#[test] -fn converts_from_json_text_recognizing_objects_independendtly_to_structured_table() { - Playground::setup("filter_from_json_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "katz.txt", - r#" - {"name": "Yehuda", "rusty_luck": 1} - {"name": "Jonathan", "rusty_luck": 1} - {"name": "Andres", "rusty_luck": 1} - {"name":"GorbyPuff", "rusty_luck": 3} - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open katz.txt - | from-json --objects - | where name == "GorbyPuff" - | get rusty_luck - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_structured_table_to_json_text() { - Playground::setup("filter_to_json_test", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "sample.txt", - r#" - JonAndrehudaTZ,3 - GorbyPuff,100 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open sample.txt - | lines - | split-column "," name luck - | pick name - | to-json - | from-json - | nth 0 - | get name - | echo $it - "# - )); - - assert_eq!(actual, "JonAndrehudaTZ"); - }) -} - -#[test] -fn can_convert_table_to_tsv_text_and_from_tsv_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open caco3_plastics.tsv | to-tsv | from-tsv | first 1 | get origin | echo $it" - ); - - assert_eq!(actual, "SPAIN"); -} - -#[test] -fn can_convert_table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() { - let actual = nu!( - cwd: "tests/fixtures/formats", - r"open caco3_plastics.tsv | to-tsv | from-csv --separator '\t' | first 1 | get origin | echo $it" - ); - - assert_eq!(actual, "SPAIN"); -} - -#[test] -fn converts_structured_table_to_tsv_text() { - Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "tsv_text_sample.txt", - r#" - importer shipper tariff_item name origin - Plasticos Rival Reverte 2509000000 Calcium carbonate Spain - Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open tsv_text_sample.txt - | lines - | split-column "\t" a b c d origin - | last 1 - | to-tsv - | lines - | nth 1 - | echo $it - "# - )); - - assert!(actual.contains("Colombia")); - }) -} - -#[test] -fn converts_structured_table_to_tsv_text_skipping_headers_after_conversion() { - Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "tsv_text_sample.txt", - r#" - importer shipper tariff_item name origin - Plasticos Rival Reverte 2509000000 Calcium carbonate Spain - Tigre Ecuador OMYA Andina 3824909999 Calcium carbonate Colombia - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open tsv_text_sample.txt - | lines - | split-column "\t" a b c d origin - | last 1 - | to-tsv --headerless - | echo $it - "# - )); - - assert!(actual.contains("Colombia")); - }) -} - -#[test] -fn converts_from_tsv_text_to_structured_table() { - Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - first Name Last Name rusty_luck - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_amigos.txt - | from-tsv - | get rusty_luck - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_from_tsv_text_skipping_headers_to_structured_table() { - Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_amigos.txt", - r#" - Andrés Robalino 1 - Jonathan Turner 1 - Yehuda Katz 1 - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_amigos.txt - | from-tsv --headerless - | get Column3 - | count - | echo $it - "# - )); - - assert_eq!(actual, "3"); - }) -} - -#[test] -fn converts_from_ssv_text_to_structured_table() { - Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - NAME LABELS SELECTOR IP PORT(S) - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open oc_get_svc.txt - | from-ssv - | nth 0 - | get IP - | echo $it - "# - )); - - assert_eq!(actual, "172.30.78.158"); - }) -} - -#[test] -fn converts_from_ssv_text_to_structured_table_with_separator_specified() { - Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - NAME LABELS SELECTOR IP PORT(S) - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open oc_get_svc.txt - | from-ssv --minimum-spaces 3 - | nth 0 - | get IP - | echo $it - "# - )); - - assert_eq!(actual, "172.30.78.158"); - }) -} - -#[test] -fn converts_from_ssv_text_treating_first_line_as_data_with_flag() { - Playground::setup("filter_from_ssv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "oc_get_svc.txt", - r#" - docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP - kubernetes component=apiserver,provider=kubernetes 172.30.0.2 443/TCP - kubernetes-ro component=apiserver,provider=kubernetes 172.30.0.1 80/TCP - "#, - )]); - - let aligned_columns = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open oc_get_svc.txt - | from-ssv --headerless --aligned-columns - | first - | get Column1 - | echo $it - "# - )); - - let separator_based = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open oc_get_svc.txt - | from-ssv --headerless - | first - | get Column1 - | echo $it - "# - )); - - assert_eq!(aligned_columns, separator_based); - assert_eq!(separator_based, "docker-registry"); - }) -} - -#[test] -fn can_convert_table_to_bson_and_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open sample.bson - | to-bson - | from-bson - | get root - | get 1.b - | echo $it - "# - )); - - assert_eq!(actual, "whel"); -} - -#[test] -fn can_read_excel_file() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open sample_data.xlsx - | get SalesOrders - | nth 4 - | get Column2 - | echo $it - "# - )); - - assert_eq!(actual, "Gill"); -} - -#[test] -fn can_convert_table_to_sqlite_and_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open sample.db - | to-sqlite - | from-sqlite - | get table_values - | nth 2 - | get x - | echo $it - "# - )); - - assert_eq!(actual, "hello"); -} - -#[test] -fn can_convert_table_to_toml_text_and_from_toml_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml - | to-toml - | from-toml - | get package.name - | echo $it - "# - )); - - assert_eq!(actual, "nu"); -} - -#[test] -fn can_convert_table_to_yaml_text_and_from_yaml_text_back_into_table() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open appveyor.yml - | to-yaml - | from-yaml - | get environment.global.PROJECT_NAME - | echo $it - "# - )); - - assert_eq!(actual, "nushell"); -} - -#[test] -fn can_encode_and_decode_urlencoding() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open sample.url - | to-url - | from-url - | get cheese - | echo $it - "# - )); - - assert_eq!(actual, "comté"); -} - -#[test] -fn can_sort_by_column() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip 1 - | first 4 - | split-column "=" - | sort-by Column1 - | skip 1 - | first 1 - | get Column1 - | trim - | echo $it - "# - )); - - assert_eq!(actual, "description"); -} - -#[test] -fn can_split_by_column() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml --raw - | lines - | skip 1 - | first 1 - | split-column "=" - | get Column1 - | trim - | echo $it - "# - )); - - assert_eq!(actual, "name"); -} - -// #[test] -// fn can_sum() { -// let actual = nu!( -// cwd: "tests/fixtures/formats", h::pipeline( -// r#" -// open sgml_description.json -// | get glossary.GlossDiv.GlossList.GlossEntry.Sections -// | sum -// | echo $it -// "# -// )); - -// assert_eq!(actual, "203") -// } - -// #[test] -// fn can_average_numbers() { -// let actual = nu!( -// cwd: "tests/fixtures/formats", h::pipeline( -// r#" -// open sgml_description.json -// | get glossary.GlossDiv.GlossList.GlossEntry.Sections -// | average -// | echo $it -// "# -// )); - -// assert_eq!(actual, "101.5000000000000") -// } - -// #[test] -// fn can_average_bytes() { -// let actual = nu!( -// cwd: "tests/fixtures/formats", -// "ls | sort-by name | skip 1 | first 2 | get size | average | echo $it" -// ); - -// assert_eq!(actual, "1600.000000000000"); -// } - -#[test] -fn can_filter_by_unit_size_comparison() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | where size > 1kb | sort-by size | get name | first 1 | trim | echo $it" - ); - - assert_eq!(actual, "cargo_sample.toml"); -} - -#[test] -fn can_get_last() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | sort-by name | last 1 | get name | trim | echo $it" - ); - - assert_eq!(actual, "utf16.ini"); -} - -#[test] -fn can_get_reverse_first() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "ls | sort-by name | reverse | first 1 | get name | trim | echo $it" - ); - - assert_eq!(actual, "utf16.ini"); -} - -#[test] -fn wrap_rows_into_a_row() { - Playground::setup("embed_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name - Andrés,Robalino - Jonathan,Turner - Yehuda,Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv - | wrap caballeros - | get caballeros - | nth 0 - | get last_name - | echo $it - "# - )); - - assert_eq!(actual, "Robalino"); - }) -} - -#[test] -fn wrap_rows_into_a_table() { - Playground::setup("embed_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name - Andrés,Robalino - Jonathan,Turner - Yehuda,Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv - | get last_name - | wrap caballero - | nth 2 - | get caballero - | echo $it - "# - )); - - assert_eq!(actual, "Katz"); - }) -} - -#[test] -fn get() { - Playground::setup("get_test", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( - "los_tres_caballeros.txt", - r#" - first_name,last_name - Andrés,Robalino - Jonathan,Turner - Yehuda,Katz - "#, - )]); - - let actual = nu!( - cwd: dirs.test(), h::pipeline( - r#" - open los_tres_caballeros.txt - | from-csv - | nth 1 - | get last_name - | echo $it - "# - )); - - assert_eq!(actual, "Turner"); - }) -} diff --git a/tests/helpers/mod.rs b/tests/helpers/mod.rs deleted file mode 100644 index 0172fee71..000000000 --- a/tests/helpers/mod.rs +++ /dev/null @@ -1,450 +0,0 @@ -#![allow(dead_code)] - -use glob::glob; -pub use std::path::Path; -pub use std::path::PathBuf; - -use app_dirs::{get_app_root, AppDataType}; -use getset::Getters; -use nu_source::PrettyDebug; -use std::io::Read; -use tempfile::{tempdir, TempDir}; - -pub trait DisplayPath { - fn display_path(&self) -> String; -} - -impl DisplayPath for PathBuf { - fn display_path(&self) -> String { - self.display().to_string() - } -} - -impl DisplayPath for str { - fn display_path(&self) -> String { - self.to_string() - } -} - -impl DisplayPath for &str { - fn display_path(&self) -> String { - self.to_string() - } -} - -impl DisplayPath for String { - fn display_path(&self) -> String { - self.clone() - } -} - -impl DisplayPath for &String { - fn display_path(&self) -> String { - self.to_string() - } -} - -impl DisplayPath for nu::AbsolutePath { - fn display_path(&self) -> String { - self.display() - } -} - -#[macro_export] -macro_rules! nu { - (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ - use $crate::helpers::DisplayPath; - - let path = format!($path, $( - $part.display_path() - ),*); - - nu!($cwd, &path) - }}; - - (cwd: $cwd:expr, $path:expr) => {{ - nu!($cwd, $path) - }}; - - ($cwd:expr, $path:expr) => {{ - pub use std::error::Error; - pub use std::io::prelude::*; - pub use std::process::{Command, Stdio}; - - let commands = &*format!( - " - cd {} - {} - exit", - $crate::helpers::in_directory($cwd), - $crate::helpers::DisplayPath::display_path(&$path) - ); - - let mut process = match Command::new(helpers::executable_path()) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - { - Ok(child) => child, - Err(why) => panic!("Can't run test {}", why.description()), - }; - - let stdin = process.stdin.as_mut().expect("couldn't open stdin"); - stdin - .write_all(commands.as_bytes()) - .expect("couldn't write to stdin"); - - - let output = process - .wait_with_output() - .expect("couldn't read from stdout"); - - let out = String::from_utf8_lossy(&output.stdout); - let out = out.replace("\r\n", ""); - let out = out.replace("\n", ""); - out - }}; -} - -#[macro_export] -macro_rules! nu_error { - (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ - use $crate::helpers::DisplayPath; - - let path = format!($path, $( - $part.display_path() - ),*); - - nu_error!($cwd, &path) - }}; - - (cwd: $cwd:expr, $path:expr) => {{ - nu_error!($cwd, $path) - }}; - - ($cwd:expr, $path:expr) => {{ - pub use std::error::Error; - pub use std::io::prelude::*; - pub use std::process::{Command, Stdio}; - - let commands = &*format!( - " - cd {} - {} - exit", - $crate::helpers::in_directory($cwd), - $crate::helpers::DisplayPath::display_path(&$path) - ); - - let mut process = Command::new(helpers::executable_path()) - .stdin(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .expect("couldn't run test"); - - let stdin = process.stdin.as_mut().expect("couldn't open stdin"); - stdin - .write_all(commands.as_bytes()) - .expect("couldn't write to stdin"); - - let output = process - .wait_with_output() - .expect("couldn't read from stderr"); - - let out = String::from_utf8_lossy(&output.stderr); - out.into_owned() - }}; -} - -#[macro_export] -macro_rules! nu_combined { - (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ - use $crate::helpers::DisplayPath; - - let path = format!($path, $( - $part.display_path() - ),*); - - nu_combined!($cwd, &path) - }}; - - (cwd: $cwd:expr, $path:expr) => {{ - nu_combined!($cwd, $path) - }}; - - ($cwd:expr, $path:expr) => {{ - pub use std::error::Error; - pub use std::io::prelude::*; - pub use std::process::{Command, Stdio}; - - let commands = &*format!( - " - cd {} - {} - exit", - $crate::helpers::in_directory($cwd), - $crate::helpers::DisplayPath::display_path(&$path) - ); - - let mut process = Command::new(helpers::executable_path()) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .expect("couldn't run test"); - - let stdin = process.stdin.as_mut().expect("couldn't open stdin"); - stdin - .write_all(commands.as_bytes()) - .expect("couldn't write to stdin"); - - let output = process - .wait_with_output() - .expect("couldn't read from stdout/stderr"); - - let err = String::from_utf8_lossy(&output.stderr).into_owned(); - let out = String::from_utf8_lossy(&output.stdout).into_owned(); - let out = out.replace("\r\n", ""); - let out = out.replace("\n", ""); - (out, err) - }}; -} - -pub enum Stub<'a> { - FileWithContent(&'a str, &'a str), - FileWithContentToBeTrimmed(&'a str, &'a str), - EmptyFile(&'a str), -} - -pub struct Playground { - root: TempDir, - tests: String, - cwd: PathBuf, -} - -#[derive(Getters)] -#[get = "pub"] -pub struct Dirs { - pub root: PathBuf, - pub test: PathBuf, - pub fixtures: PathBuf, -} - -impl Dirs { - pub fn formats(&self) -> PathBuf { - PathBuf::from(self.fixtures.join("formats")) - } - - pub fn config_path(&self) -> PathBuf { - get_app_root(AppDataType::UserConfig, &nu::APP_INFO).unwrap() - } -} - -impl Playground { - pub fn root(&self) -> &Path { - self.root.path() - } - - pub fn back_to_playground(&mut self) -> &mut Self { - self.cwd = PathBuf::from(self.root()).join(self.tests.clone()); - self - } - - pub fn setup(topic: &str, block: impl FnOnce(Dirs, &mut Playground)) { - let root = tempdir().expect("Couldn't create a tempdir"); - let nuplay_dir = root.path().join(topic); - - if PathBuf::from(&nuplay_dir).exists() { - std::fs::remove_dir_all(PathBuf::from(&nuplay_dir)).expect("can not remove directory"); - } - - std::fs::create_dir(PathBuf::from(&nuplay_dir)).expect("can not create directory"); - - let mut playground = Playground { - root: root, - tests: topic.to_string(), - cwd: nuplay_dir, - }; - - let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let playground_root = playground.root.path(); - - let fixtures = project_root.join(file!()); - let fixtures = fixtures - .parent() - .expect("Couldn't find the fixtures directory") - .parent() - .expect("Couldn't find the fixtures directory") - .join("fixtures"); - - let fixtures = dunce::canonicalize(fixtures.clone()).expect(&format!( - "Couldn't canonicalize fixtures path {}", - fixtures.display() - )); - - let test = - dunce::canonicalize(PathBuf::from(playground_root.join(topic))).expect(&format!( - "Couldn't canonicalize test path {}", - playground_root.join(topic).display() - )); - - let root = dunce::canonicalize(playground_root).expect(&format!( - "Couldn't canonicalize tests root path {}", - playground_root.display() - )); - - let dirs = Dirs { - root, - test, - fixtures, - }; - - block(dirs, &mut playground); - } - - pub fn mkdir(&mut self, directory: &str) -> &mut Self { - self.cwd.push(directory); - std::fs::create_dir_all(&self.cwd).expect("can not create directory"); - self.back_to_playground(); - self - } - - pub fn with_files(&mut self, files: Vec) -> &mut Self { - let endl = line_ending(); - - files - .iter() - .map(|f| { - let mut path = PathBuf::from(&self.cwd); - - let (file_name, contents) = match *f { - Stub::EmptyFile(name) => (name, "fake data".to_string()), - Stub::FileWithContent(name, content) => (name, content.to_string()), - Stub::FileWithContentToBeTrimmed(name, content) => ( - name, - content - .lines() - .skip(1) - .map(|line| line.trim()) - .collect::>() - .join(&endl), - ), - }; - - path.push(file_name); - - std::fs::write(PathBuf::from(path), contents.as_bytes()) - .expect("can not create file"); - }) - .for_each(drop); - self.back_to_playground(); - self - } - - pub fn within(&mut self, directory: &str) -> &mut Self { - self.cwd.push(directory); - std::fs::create_dir(&self.cwd).expect("can not create directory"); - self - } - - pub fn glob_vec(pattern: &str) -> Vec { - let glob = glob(pattern); - - match glob { - Ok(paths) => paths - .map(|path| { - if let Ok(path) = path { - path - } else { - unreachable!() - } - }) - .collect(), - Err(_) => panic!("Invalid pattern."), - } - } -} - -pub fn file_contents(full_path: impl AsRef) -> String { - let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file"); - let mut contents = String::new(); - file.read_to_string(&mut contents) - .expect("can not read file"); - contents -} - -pub fn file_contents_binary(full_path: impl AsRef) -> Vec { - let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file"); - let mut contents = Vec::new(); - file.read_to_end(&mut contents).expect("can not read file"); - contents -} - -pub fn line_ending() -> String { - #[cfg(windows)] - { - String::from("\r\n") - } - - #[cfg(not(windows))] - { - String::from("\n") - } -} - -pub fn delete_file_at(full_path: impl AsRef) { - let full_path = full_path.as_ref(); - - if full_path.exists() { - std::fs::remove_file(full_path).expect("can not delete file"); - } -} - -pub fn create_file_at(full_path: impl AsRef) -> Result<(), std::io::Error> { - let full_path = full_path.as_ref(); - - if let Some(parent) = full_path.parent() { - panic!(format!("{:?} exists", parent.display())); - } - - std::fs::write(full_path, "fake data".as_bytes()) -} - -pub fn copy_file_to(source: &str, destination: &str) { - std::fs::copy(source, destination).expect("can not copy file"); -} - -pub fn files_exist_at(files: Vec>, path: impl AsRef) -> bool { - files.iter().all(|f| { - let mut loc = PathBuf::from(path.as_ref()); - loc.push(f); - loc.exists() - }) -} - -pub fn delete_directory_at(full_path: &str) { - std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory"); -} - -pub fn executable_path() -> PathBuf { - let mut buf = PathBuf::new(); - buf.push("target"); - buf.push("debug"); - buf.push("nu"); - buf -} - -pub fn in_directory(str: impl AsRef) -> String { - str.as_ref().display().to_string() -} - -pub fn pipeline(commands: &str) -> String { - commands - .lines() - .skip(1) - .map(|line| line.trim()) - .collect::>() - .join(" ") - .trim_end() - .to_string() -} diff --git a/tests/main.rs b/tests/main.rs new file mode 100644 index 000000000..14be7bacf --- /dev/null +++ b/tests/main.rs @@ -0,0 +1,6 @@ +extern crate test_support; + +mod commands; +mod converting_formats; +mod plugins; +mod shell; diff --git a/tests/filter_inc_tests.rs b/tests/plugins/core_inc.rs similarity index 96% rename from tests/filter_inc_tests.rs rename to tests/plugins/core_inc.rs index 658e24308..691ef37c4 100644 --- a/tests/filter_inc_tests.rs +++ b/tests/plugins/core_inc.rs @@ -1,6 +1,6 @@ -mod helpers; - -use helpers::{Playground, Stub::*}; +use test_support::fs::Stub::FileWithContent; +use test_support::playground::Playground; +use test_support::{nu, nu_error}; #[test] fn can_only_apply_one() { diff --git a/tests/filter_str_tests.rs b/tests/plugins/core_str.rs similarity index 92% rename from tests/filter_str_tests.rs rename to tests/plugins/core_str.rs index fde3c77ee..5bd915fae 100644 --- a/tests/filter_str_tests.rs +++ b/tests/plugins/core_str.rs @@ -1,7 +1,6 @@ -mod helpers; - -use h::{Playground, Stub::*}; -use helpers as h; +use test_support::fs::Stub::FileWithContent; +use test_support::playground::Playground; +use test_support::{nu, nu_error, pipeline}; #[test] fn can_only_apply_one() { @@ -77,7 +76,7 @@ fn upcases() { #[test] fn converts_to_int() { let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( + cwd: "tests/fixtures/formats", pipeline( r#" open caco3_plastics.csv | first 1 @@ -103,7 +102,7 @@ fn replaces() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | str package.name --replace wykittenshell @@ -128,7 +127,7 @@ fn find_and_replaces() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | str fortune.teller.phone --find-replace [KATZ "5289"] @@ -153,7 +152,7 @@ fn find_and_replaces_without_passing_field() { )]); let actual = nu!( - cwd: dirs.test(), h::pipeline( + cwd: dirs.test(), pipeline( r#" open sample.toml | get fortune.teller.phone diff --git a/tests/plugins/mod.rs b/tests/plugins/mod.rs new file mode 100644 index 000000000..bfb41ea20 --- /dev/null +++ b/tests/plugins/mod.rs @@ -0,0 +1,2 @@ +mod core_inc; +mod core_str; diff --git a/tests/shell/mod.rs b/tests/shell/mod.rs new file mode 100644 index 000000000..5cbb3fd27 --- /dev/null +++ b/tests/shell/mod.rs @@ -0,0 +1,32 @@ +mod pipeline { + use test_support::fs::Stub::FileWithContent; + use test_support::playground::Playground; + use test_support::{nu_combined, pipeline}; + + #[test] + fn it_arg_works_with_many_inputs_to_external_command() { + Playground::setup("it_arg_works_with_many_inputs", |dirs, sandbox| { + sandbox.with_files(vec![ + FileWithContent("file1", "text"), + FileWithContent("file2", " and more text"), + ]); + + let (stdout, stderr) = nu_combined!( + cwd: dirs.test(), pipeline( + r#" + echo hello world + | split-row " " + | ^echo $it + "# + )); + + #[cfg(windows)] + assert_eq!("hello world", stdout); + + #[cfg(not(windows))] + assert_eq!("helloworld", stdout); + + assert!(!stderr.contains("No such file or directory")); + }) + } +} diff --git a/tests/tests.rs b/tests/tests.rs deleted file mode 100644 index 8799f5077..000000000 --- a/tests/tests.rs +++ /dev/null @@ -1,135 +0,0 @@ -mod helpers; - -use helpers as h; - -#[test] -fn pipeline_helper() { - let actual = h::pipeline( - r#" - open los_tres_amigos.txt - | from-csv - | get rusty_luck - | str --to-int - | sum - | echo "$it" - "#, - ); - - assert_eq!( - actual, - r#"open los_tres_amigos.txt | from-csv | get rusty_luck | str --to-int | sum | echo "$it""# - ); -} - -#[test] -fn external_num() { - let actual = nu!( - cwd: "tests/fixtures/formats", - "open sgml_description.json | get glossary.GlossDiv.GlossList.GlossEntry.Height | echo $it" - ); - - assert_eq!(actual, "10"); -} - -#[test] -fn external_has_correct_quotes() { - let actual = nu!( - cwd: ".", - r#"echo "hello world""# - ); - - assert_eq!(actual, r#"hello world"#); -} - -#[test] -fn insert_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml - | insert dev-dependencies.newdep "1" - | get dev-dependencies.newdep - | echo $it - "# - )); - - assert_eq!(actual, "1"); -} - -#[test] -fn parse_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open fileA.txt - | parse "{Name}={Value}" - | nth 1 - | get Value - | echo $it - "# - )); - - assert_eq!(actual, "StupidLongName"); -} - -#[test] -fn format_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml - | get package - | format "{name} has license {license}" - | echo $it - "# - )); - - assert_eq!(actual, "nu has license ISC"); -} - -#[test] -fn prepend_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open fileA.txt - | lines - | prepend "testme" - | nth 0 - | echo $it - "# - )); - - assert_eq!(actual, "testme"); -} - -#[test] -fn append_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open fileA.txt - | lines - | append "testme" - | nth 3 - | echo $it - "# - )); - - assert_eq!(actual, "testme"); -} - -#[test] -fn edit_plugin() { - let actual = nu!( - cwd: "tests/fixtures/formats", h::pipeline( - r#" - open cargo_sample.toml - | edit dev-dependencies.pretty_assertions "7" - | get dev-dependencies.pretty_assertions - | echo $it - "# - )); - - assert_eq!(actual, "7"); -}