Add cli action and repl tests for search

pull/131/head
Chip Senkbeil 2 years ago
parent 00911c60c6
commit 4230a2810c
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -284,7 +284,12 @@ impl SearchQuerySubmatch {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[serde(
rename_all = "snake_case",
deny_unknown_fields,
tag = "type",
content = "value"
)]
pub enum SearchQueryMatchData {
/// Match represented as UTF-8 text
Text(String),

@ -7,6 +7,8 @@ const EXPECTED_TABLE: &str = indoc! {"
+------------------+------------------------------------------------------------------+
| kind | description |
+------------------+------------------------------------------------------------------+
| cancel_search | Supports canceling an active search against the filesystem |
+------------------+------------------------------------------------------------------+
| capabilities | Supports retrieving capabilities |
+------------------+------------------------------------------------------------------+
| copy | Supports copying files, directories, and symlinks |
@ -43,6 +45,8 @@ const EXPECTED_TABLE: &str = indoc! {"
+------------------+------------------------------------------------------------------+
| rename | Supports renaming files, directories, and symlinks |
+------------------+------------------------------------------------------------------+
| search | Supports searching filesystem using queries |
+------------------+------------------------------------------------------------------+
| system_info | Supports retrieving system information |
+------------------+------------------------------------------------------------------+
| unwatch | Supports unwatching filesystem for changes |

@ -13,5 +13,6 @@ mod metadata;
mod proc_spawn;
mod remove;
mod rename;
mod search;
mod system_info;
mod watch;

@ -0,0 +1,62 @@
use crate::cli::fixtures::*;
use assert_cmd::Command;
use assert_fs::prelude::*;
use indoc::indoc;
use predicates::Predicate;
use rstest::*;
use serde_json::json;
const SEARCH_RESULTS_REGEX: &str = indoc! {r"
.*?[\\/]file1.txt
1:some file text
.*?[\\/]file2.txt
3:textual
.*?[\\/]file3.txt
1:more content
"};
#[rstest]
fn should_search_filesystem_using_query(mut action_cmd: CtxCommand<Command>) {
let root = assert_fs::TempDir::new().unwrap();
root.child("file1.txt").write_str("some file text").unwrap();
root.child("file2.txt")
.write_str("lines\nof\ntextual\ninformation")
.unwrap();
root.child("file3.txt").write_str("more content").unwrap();
let query = json!({
"path": root.path().to_string_lossy(),
"target": "contents",
"condition": {"type": "regex", "value": "te[a-z]*\\b"},
});
let stdout_predicate_fn = predicates::function::function(|s: &[u8]| {
let s = std::str::from_utf8(s).unwrap();
// Split by empty line, sort, and then rejoin with empty line inbetween
let mut lines = s
.split("\n\n")
.map(|lines| lines.trim_end())
.collect::<Vec<_>>();
lines.sort_unstable();
// Put together sorted text lines
let full_text = lines.join("\n\n");
// Verify that it matches our search results regex
let regex_fn = predicates::str::is_match(SEARCH_RESULTS_REGEX).unwrap();
regex_fn.eval(&full_text)
});
// distant action system-info
action_cmd
.arg("search")
.arg(&serde_json::to_string(&query).unwrap())
.assert()
.success()
.stdout(stdout_predicate_fn)
.stderr("");
}

@ -13,5 +13,6 @@ mod metadata;
mod proc_spawn;
mod remove;
mod rename;
mod search;
mod system_info;
mod watch;

@ -0,0 +1,82 @@
use crate::cli::fixtures::*;
use assert_fs::prelude::*;
use rstest::*;
use serde_json::json;
#[rstest]
#[tokio::test]
async fn should_support_json_search_filesystem_using_query(mut json_repl: CtxCommand<Repl>) {
let root = assert_fs::TempDir::new().unwrap();
root.child("file1.txt").write_str("some file text").unwrap();
root.child("file2.txt")
.write_str("lines\nof\ntextual\ninformation")
.unwrap();
root.child("file3.txt").write_str("more content").unwrap();
let id = rand::random::<u64>().to_string();
let req = json!({
"id": id,
"payload": {
"type": "search",
"query": {
"path": root.path().to_string_lossy(),
"target": "contents",
"condition": {"type": "regex", "value": "ua"},
},
},
});
// Submit search request and get back started confirmation
let res = json_repl.write_and_read_json(req).await.unwrap().unwrap();
// Get id from started confirmation
assert_eq!(res["origin_id"], id);
assert_eq!(res["payload"]["type"], "search_started");
let search_id = res["payload"]["id"]
.as_u64()
.expect("id missing or not number");
// Get search results back
let res = json_repl.read_json_from_stdout().await.unwrap().unwrap();
assert_eq!(res["origin_id"], id);
assert_eq!(
res["payload"],
json!({
"type": "search_results",
"id": search_id,
"matches": [
{
"type": "contents",
"path": root.child("file2.txt").to_string_lossy(),
"lines": {
"type": "text",
"value": "textual\n",
},
"line_number": 3,
"absolute_offset": 9,
"submatches": [
{
"match": {
"type": "text",
"value": "ua",
},
"start": 4,
"end": 6,
}
],
},
]
})
);
// Get search completion confirmation
let res = json_repl.read_json_from_stdout().await.unwrap().unwrap();
assert_eq!(res["origin_id"], id);
assert_eq!(
res["payload"],
json!({
"type": "search_done",
"id": search_id,
})
);
}
Loading…
Cancel
Save