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.

This commit is contained in:
Andrés N. Robalino 2019-12-15 11:15:06 -05:00
parent 4b9ef5a9d0
commit 4034129dba
64 changed files with 2184 additions and 2340 deletions

12
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -0,0 +1,16 @@
[package]
name = "test-support"
version = "0.1.0"
authors = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner@gmail.com>", "Andrés N. Robalino <andres@androbtech.com>"]
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"

View File

@ -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<Path>) -> 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<AbsoluteFile> for PathBuf {
fn from(file: AbsoluteFile) -> Self {
file.inner
}
}
pub struct AbsolutePath {
inner: PathBuf,
}
impl AbsolutePath {
pub fn new(path: impl AsRef<Path>) -> 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<Path> for AbsolutePath {
fn as_ref(&self) -> &Path {
self.inner.as_path()
}
}
pub struct RelativePath {
inner: PathBuf,
}
impl RelativePath {
pub fn new(path: impl Into<PathBuf>) -> RelativePath {
let path = path.into();
if path.is_relative() {
RelativePath { inner: path }
} else {
panic!("RelativePath::new must take a relative path")
}
}
}
impl<T: AsRef<str>> Div<T> 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<Path>) -> 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<Path>) -> Vec<u8> {
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<Path>) {
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<Path>) -> 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<impl AsRef<Path>>, path: impl AsRef<Path>) -> 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<Path>) -> String {
str.as_ref().display().to_string()
}

View File

@ -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::<Vec<&str>>()
.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""#
);
}
}

View File

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

View File

@ -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<Stub>) -> &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::<Vec<&str>>()
.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<PathBuf> {
let glob = glob(pattern);
match glob {
Ok(paths) => paths
.map(|path| {
if let Ok(path) = path {
path
} else {
unreachable!()
}
})
.collect(),
Err(_) => panic!("Invalid pattern."),
}
}
}

View File

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

View File

@ -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<Path>) -> 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<AbsoluteFile> 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<Path>) -> 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<Path> for AbsolutePath {
fn as_ref(&self) -> &Path {
self.inner.as_path()
}
}
pub struct RelativePath {
inner: PathBuf,
}
impl RelativePath {
pub fn new(path: impl Into<PathBuf>) -> RelativePath {
let path = path.into();
if path.is_relative() {
RelativePath { inner: path }
} else {
panic!("RelativePath::new must take a relative path")
}
}
}
impl<T: AsRef<str>> Div<T> 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>),

View File

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

17
tests/commands/append.rs Normal file
View File

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

View File

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

52
tests/commands/compact.rs Normal file
View File

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

View File

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

36
tests/commands/default.rs Normal file
View File

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

16
tests/commands/edit.rs Normal file
View File

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

View File

@ -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"),

70
tests/commands/first.rs Normal file
View File

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

16
tests/commands/format.rs Normal file
View File

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

View File

@ -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

View File

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

View File

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

16
tests/commands/insert.rs Normal file
View File

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

56
tests/commands/last.rs Normal file
View File

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

21
tests/commands/lines.rs Normal file
View File

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

View File

@ -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

View File

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

30
tests/commands/mod.rs Normal file
View File

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

View File

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

39
tests/commands/nth.rs Normal file
View File

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

View File

@ -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"

17
tests/commands/parse.rs Normal file
View File

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

17
tests/commands/prepend.rs Normal file
View File

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

47
tests/commands/range.rs Normal file
View File

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

11
tests/commands/reverse.rs Normal file
View File

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

View File

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

47
tests/commands/save.rs Normal file
View File

@ -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 <wycats@gmail.com>"]
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"));
})
}

23
tests/commands/sort_by.rs Normal file
View File

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

View File

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

View File

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

View File

@ -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

63
tests/commands/wrap.rs Normal file
View File

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

View File

@ -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 <wycats@gmail.com>"]
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"));
})
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,10 @@
mod bson;
mod csv;
mod json;
mod sqlite;
mod ssv;
mod toml;
mod tsv;
mod url;
mod xlsx;
mod yaml;

View File

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

View File

@ -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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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");
})
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

43
tests/filters.rs Normal file
View File

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

View File

@ -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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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 <none> 172.30.0.2 443/TCP
kubernetes-ro component=apiserver,provider=kubernetes <none> 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");
})
}

View File

@ -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<Stub>) -> &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::<Vec<&str>>()
.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<PathBuf> {
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<Path>) -> 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<Path>) -> Vec<u8> {
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<Path>) {
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<Path>) -> 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<impl AsRef<Path>>, path: impl AsRef<Path>) -> 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<Path>) -> String {
str.as_ref().display().to_string()
}
pub fn pipeline(commands: &str) -> String {
commands
.lines()
.skip(1)
.map(|line| line.trim())
.collect::<Vec<&str>>()
.join(" ")
.trim_end()
.to_string()
}

6
tests/main.rs Normal file
View File

@ -0,0 +1,6 @@
extern crate test_support;
mod commands;
mod converting_formats;
mod plugins;
mod shell;

View File

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

View File

@ -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

2
tests/plugins/mod.rs Normal file
View File

@ -0,0 +1,2 @@
mod core_inc;
mod core_str;

32
tests/shell/mod.rs Normal file
View File

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

View File

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