Files
MercuryToolbox/crates/recent/tests/recent_cli.rs
T

179 lines
5.0 KiB
Rust

//! Integration tests for the `recent` command.
use std::fs;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
use assert_cmd::Command;
use filetime::{FileTime, set_file_mtime};
use predicates::prelude::*;
use recent::{KindFilter, RecentOptions, collect_recent};
use tempfile::tempdir;
fn cargo_command() -> Command {
Command::cargo_bin("recent").expect("binary")
}
fn pwsh_command(script: impl AsRef<str>) -> Command {
let mut command = Command::new("pwsh");
command
.arg("-NoProfile")
.arg("-Command")
.arg(script.as_ref());
command
}
fn ps_quote(value: impl std::fmt::Display) -> String {
format!("'{}'", value.to_string().replace('\'', "''"))
}
fn touch(path: &std::path::Path, age: Duration) {
fs::write(path, path.display().to_string()).expect("write fixture");
let timestamp = FileTime::from_system_time(SystemTime::now() - age);
set_file_mtime(path, timestamp).expect("set mtime");
}
fn file_recent_options(root: PathBuf) -> RecentOptions {
RecentOptions {
roots: vec![root],
since: None,
exts: Vec::new(),
name_pattern: None,
kind: KindFilter::File,
limit: None,
}
}
#[test]
fn collect_recent_respects_gitignore() {
let root = tempdir().expect("tempdir");
fs::write(root.path().join(".gitignore"), "ignored.log\n").expect("gitignore");
touch(&root.path().join("visible.log"), Duration::from_secs(30));
touch(&root.path().join("ignored.log"), Duration::from_secs(10));
let entries = collect_recent(
&file_recent_options(root.path().to_path_buf()),
SystemTime::now(),
)
.expect("recent entries");
assert_eq!(entries.len(), 1);
assert!(entries[0].path.ends_with("visible.log"));
}
#[test]
fn filters_since_and_extension_in_json_output() {
let root = tempdir().expect("tempdir");
touch(
&root.path().join("old.rs"),
Duration::from_secs(60 * 60 * 24),
);
touch(&root.path().join("new.rs"), Duration::from_secs(30));
touch(&root.path().join("new.txt"), Duration::from_secs(30));
let mut command = cargo_command();
command
.arg("--root")
.arg(root.path())
.arg("--since")
.arg("1h")
.arg("--ext")
.arg("rs")
.arg("--json")
.assert()
.success()
.stdout(predicate::str::contains("\"path\"").and(predicate::str::contains("new.rs")))
.stdout(predicate::str::contains("old.rs").not())
.stdout(predicate::str::contains("new.txt").not());
}
#[test]
fn supports_powershell_root_pipeline() {
let root = tempdir().expect("tempdir");
touch(&root.path().join("one.rs"), Duration::from_secs(10));
touch(&root.path().join("two.rs"), Duration::from_secs(20));
let binary = assert_cmd::cargo::cargo_bin("recent");
let script = format!(
"{} | & {} --limit 1",
ps_quote(root.path().display()),
ps_quote(binary.display())
);
let mut command = pwsh_command(script);
command
.assert()
.success()
.stdout(predicate::str::contains("one.rs"));
}
#[test]
fn filters_by_basename_regex() {
let root = tempdir().expect("tempdir");
touch(&root.path().join("alpha.rs"), Duration::from_secs(10));
touch(&root.path().join("beta.rs"), Duration::from_secs(20));
touch(&root.path().join("gamma.txt"), Duration::from_secs(5));
let mut command = cargo_command();
command
.arg("--root")
.arg(root.path())
.arg("--name")
.arg("^(alpha|gamma)$")
.assert()
.success()
.stdout(predicate::str::contains("alpha.rs"))
.stdout(predicate::str::contains("gamma.txt"))
.stdout(predicate::str::contains("beta.rs").not())
.stdout(predicate::str::contains("delta").not());
}
#[test]
fn help_includes_name_filter_examples() {
let mut command = cargo_command();
command
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("--name"))
.stdout(predicate::str::contains(
"recent --root . --since 2h --ext rs --name",
))
.stdout(predicate::str::contains("ConvertFrom-Json"));
}
#[test]
fn basename_filter_keeps_directory_suffixes() {
let root = tempdir().expect("tempdir");
let dotted_dir = root.path().join("plugins.v1");
fs::create_dir_all(&dotted_dir).expect("directory");
let mut command = cargo_command();
command
.arg("--root")
.arg(root.path())
.arg("--kind")
.arg("dir")
.arg("--name")
.arg("^plugins\\.v1$")
.assert()
.success()
.stdout(predicate::str::contains("plugins.v1"));
}
#[test]
fn text_mode_emits_no_matches_hint() {
let root = tempdir().expect("tempdir");
touch(&root.path().join("alpha.rs"), Duration::from_secs(10));
let mut command = cargo_command();
command
.arg("--root")
.arg(root.path())
.arg("--name")
.arg("^beta$")
.assert()
.code(1)
.stdout(predicate::str::contains("no_matches=true"));
}