From 4d7b86f27821dc73282f75c8a4619c3d6db4c8e4 Mon Sep 17 00:00:00 2001 From: Herlon Aguiar Date: Wed, 20 Apr 2022 06:54:00 +0200 Subject: [PATCH] nu-cli: added tests for file completions (#5232) * nu-cli: added tests for file completions * test adding extra sort * Feature/refactor completion options (#5228) * Copy completion filter to custom completions * Remove filter function from completer This function was a no-op for FileCompletion and CommandCompletion. Flag- and VariableCompletion just filters with `starts_with` which happens in both completers anyway and should therefore also be a no-op. The remaining use case in CustomCompletion was moved into the CustomCompletion source file. Filtering should probably happen immediately while fetching completions to avoid unnecessary memory allocations. * Add get_sort_by() to Completer trait * Remove CompletionOptions from Completer::fetch() * Fix clippy lints * Apply Completer changes to DotNuCompletion * add os to $nu based on rust's understanding (#5243) * add os to $nu based on rust's understanding * add a few more constants Co-authored-by: Richard Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> --- Cargo.lock | 2 + crates/nu-cli/Cargo.toml | 4 + .../src/completions/file_completions.rs | 1 + crates/nu-cli/src/lib.rs | 2 +- crates/nu-cli/tests/test_completions.rs | 84 +++++++++++++++++++ crates/nu-test-support/src/fs.rs | 2 +- tests/fixtures/completions/.hidden_file | 0 .../completions/.hidden_folder/.gitkeep | 0 tests/fixtures/completions/another/newfile | 0 tests/fixtures/completions/nushell | 0 tests/fixtures/completions/test_a/myfile | 0 tests/fixtures/completions/test_b/testfile | 0 12 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 crates/nu-cli/tests/test_completions.rs create mode 100644 tests/fixtures/completions/.hidden_file create mode 100644 tests/fixtures/completions/.hidden_folder/.gitkeep create mode 100644 tests/fixtures/completions/another/newfile create mode 100644 tests/fixtures/completions/nushell create mode 100644 tests/fixtures/completions/test_a/myfile create mode 100644 tests/fixtures/completions/test_b/testfile diff --git a/Cargo.lock b/Cargo.lock index 9dc4bd1f9b..ed1859c7eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2289,10 +2289,12 @@ dependencies = [ "miette 4.5.0", "nu-ansi-term", "nu-color-config", + "nu-command", "nu-engine", "nu-parser", "nu-path", "nu-protocol", + "nu-test-support", "nu-utils", "reedline", "thiserror", diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 8610b3bc06..7d9dfb6e3b 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -6,6 +6,10 @@ license = "MIT" name = "nu-cli" version = "0.61.1" +[dev-dependencies] +nu-test-support = { path="../nu-test-support", version = "0.61.1" } +nu-command = { path = "../nu-command", version = "0.61.1" } + [dependencies] nu-engine = { path = "../nu-engine", version = "0.61.1" } nu-path = { path = "../nu-path", version = "0.61.1" } diff --git a/crates/nu-cli/src/completions/file_completions.rs b/crates/nu-cli/src/completions/file_completions.rs index b6ed7c2e22..f6452c8c1e 100644 --- a/crates/nu-cli/src/completions/file_completions.rs +++ b/crates/nu-cli/src/completions/file_completions.rs @@ -60,6 +60,7 @@ impl Completer for FileCompletion { // Sort items let mut sorted_items = items; + sorted_items.sort_by(|a, b| a.value.cmp(&b.value)); sorted_items.sort_by(|a, b| { let a_distance = levenshtein_distance(&prefix_str, &a.value); let b_distance = levenshtein_distance(&prefix_str, &b.value); diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs index 4ff922b7d7..3871cd8c2e 100644 --- a/crates/nu-cli/src/lib.rs +++ b/crates/nu-cli/src/lib.rs @@ -15,7 +15,7 @@ mod util; mod validation; pub use commands::evaluate_commands; -pub use completions::NuCompleter; +pub use completions::{FileCompletion, NuCompleter}; pub use config_files::eval_config_contents; pub use errors::CliError; pub use eval_file::evaluate_file; diff --git a/crates/nu-cli/tests/test_completions.rs b/crates/nu-cli/tests/test_completions.rs new file mode 100644 index 0000000000..83fc6e7770 --- /dev/null +++ b/crates/nu-cli/tests/test_completions.rs @@ -0,0 +1,84 @@ +use std::path::PathBuf; + +use nu_cli::NuCompleter; +use nu_command::create_default_context; +use nu_protocol::engine::{EngineState, Stack}; +use nu_test_support::fs; +use reedline::{Completer, Suggestion}; +const SEP: char = std::path::MAIN_SEPARATOR; + +#[test] +fn file_completions() { + // Create a new engine + let (dir, dir_str, engine) = new_engine(); + + let stack = Stack::new(); + + // Instatiate a new completer + let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack.clone()); + + // Test completions for the current folder + let target_dir = format!("cd {}", dir_str); + let suggestions = completer.complete(&target_dir, target_dir.len()); + + // Create the expected values + let expected_paths: Vec = vec![ + file(dir.clone().join("nushell")), + folder(dir.clone().join("test_a")), + folder(dir.clone().join("test_b")), + folder(dir.clone().join("another")), + file(dir.clone().join(".hidden_file")), + folder(dir.clone().join(".hidden_folder")), + ]; + + // Match the results + match_suggestions(expected_paths, suggestions); + + // Test completions for the completions/another folder + let target_dir = format!("cd {}", folder(dir.clone().join("another"))); + let suggestions = completer.complete(&target_dir, target_dir.len()); + + // Create the expected values + let expected_paths: Vec = vec![file(dir.clone().join("another").join("newfile"))]; + + // Match the results + match_suggestions(expected_paths, suggestions); +} + +// creates a new engine with the current path into the completions fixtures folder +fn new_engine() -> (PathBuf, String, EngineState) { + // Target folder inside assets + let dir = fs::fixtures().join("completions"); + let mut dir_str = dir + .clone() + .into_os_string() + .into_string() + .unwrap_or("".to_string()); + dir_str.push(SEP); + + // Create a default engine + (dir.clone(), dir_str, create_default_context(dir)) +} + +// match a list of suggestions with the expected values +fn match_suggestions(expected: Vec, suggestions: Vec) { + expected.iter().zip(suggestions).for_each(|it| { + assert_eq!(it.0, &it.1.value); + }); +} + +// append the separator to the converted path +fn folder(path: PathBuf) -> String { + let mut converted_path = file(path); + converted_path.push(SEP); + + converted_path +} + +// convert a given path to string +fn file(path: PathBuf) -> String { + path.clone() + .into_os_string() + .into_string() + .unwrap_or("".to_string()) +} diff --git a/crates/nu-test-support/src/fs.rs b/crates/nu-test-support/src/fs.rs index bf7d87df77..dbdd2168d5 100644 --- a/crates/nu-test-support/src/fs.rs +++ b/crates/nu-test-support/src/fs.rs @@ -258,7 +258,7 @@ pub fn binaries() -> PathBuf { } pub fn fixtures() -> PathBuf { - root().join("tests/fixtures") + root().join("tests").join("fixtures") } pub fn assets() -> PathBuf { diff --git a/tests/fixtures/completions/.hidden_file b/tests/fixtures/completions/.hidden_file new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/completions/.hidden_folder/.gitkeep b/tests/fixtures/completions/.hidden_folder/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/completions/another/newfile b/tests/fixtures/completions/another/newfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/completions/nushell b/tests/fixtures/completions/nushell new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/completions/test_a/myfile b/tests/fixtures/completions/test_a/myfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/completions/test_b/testfile b/tests/fixtures/completions/test_b/testfile new file mode 100644 index 0000000000..e69de29bb2