179 lines
5.0 KiB
Rust
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"));
|
|
}
|