forked from Crockan/MercuryToolbox
185 lines
5.2 KiB
Rust
185 lines
5.2 KiB
Rust
//! Integration tests for the `hitsnip` command.
|
|
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
use std::str;
|
|
|
|
use assert_cmd::Command;
|
|
use predicates::prelude::*;
|
|
use tempfile::{TempDir, tempdir};
|
|
|
|
const SAMPLE_RS: &str = "reading/sample.rs";
|
|
|
|
fn cargo_command() -> Command {
|
|
Command::cargo_bin("hitsnip").expect("binary")
|
|
}
|
|
|
|
fn workspace_root() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("..")
|
|
.join("..")
|
|
.canonicalize()
|
|
.expect("workspace root")
|
|
}
|
|
|
|
fn fixture(path: &str) -> PathBuf {
|
|
workspace_root().join("fixtures").join(path)
|
|
}
|
|
|
|
fn temp_file(name: &str, contents: impl AsRef<[u8]>) -> (TempDir, PathBuf) {
|
|
let dir = tempdir().expect("tempdir");
|
|
let path = dir.path().join(name);
|
|
fs::write(&path, contents).expect("fixture");
|
|
(dir, path)
|
|
}
|
|
|
|
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 relative_to_workspace(path: &Path) -> String {
|
|
path.strip_prefix(workspace_root())
|
|
.expect("path within workspace")
|
|
.display()
|
|
.to_string()
|
|
}
|
|
|
|
#[test]
|
|
fn merges_rg_hits_into_compact_text_snippets() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.current_dir(workspace_root())
|
|
.arg("--context")
|
|
.arg("1")
|
|
.arg("--max-gap")
|
|
.arg("1")
|
|
.write_stdin(std::fs::read_to_string(fixture("hits/rg-output.txt")).expect("fixture"))
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(
|
|
"path=fixtures\\reading\\sample.rs lines=17:27 hits=3",
|
|
))
|
|
.stdout(predicate::str::contains("hit_lines=18,22,26"))
|
|
.stdout(predicate::str::contains("18: pub fn run"))
|
|
.stdout(predicate::str::contains(
|
|
"path=fixtures\\reading\\sample.cs lines=8:10 hits=1",
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn accepts_explicit_hit_arguments_and_emits_json() {
|
|
let sample = fixture(SAMPLE_RS);
|
|
let hit_a = format!("{}:18", sample.display());
|
|
let hit_b = format!("{}:26:9", sample.display());
|
|
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--json")
|
|
.arg("--context")
|
|
.arg("0")
|
|
.arg("--max-gap")
|
|
.arg("10")
|
|
.arg(&hit_a)
|
|
.arg(&hit_b)
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("\"start_line\":18"))
|
|
.stdout(predicate::str::contains("\"end_line\":26"))
|
|
.stdout(predicate::str::contains("\"hit_count\":2"))
|
|
.stdout(predicate::str::contains("\"hit_lines\":[18,26]"));
|
|
}
|
|
|
|
#[test]
|
|
fn supports_powershell_pipeline_for_hit_lines() {
|
|
let binary = assert_cmd::cargo::cargo_bin("hitsnip");
|
|
let sample = relative_to_workspace(&fixture(SAMPLE_RS));
|
|
let script = format!(
|
|
"{},{} | & {} --context 0 --max-gap 0 --json",
|
|
ps_quote(format!("{sample}:18")),
|
|
ps_quote(format!("{sample}:26")),
|
|
ps_quote(binary.display())
|
|
);
|
|
|
|
let mut command = pwsh_command(script);
|
|
command
|
|
.current_dir(workspace_root())
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(
|
|
"\"path\":\"fixtures\\\\reading\\\\sample.rs\"",
|
|
))
|
|
.stdout(predicate::str::contains("\"selected\"").not());
|
|
}
|
|
|
|
#[test]
|
|
fn utf8_bom_source_file_does_not_pollute_first_snippet_line() {
|
|
let (_dir, source) = temp_file("bom.rs", "\u{feff}fn main() {}\nfn helper() {}\n");
|
|
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--context")
|
|
.arg("0")
|
|
.arg(format!("{}:1", source.display()))
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("1: fn main() {}"))
|
|
.stdout(predicate::str::contains("\u{feff}fn main").not());
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_utf8_source_file_reports_read_error() {
|
|
let (_dir, source) = temp_file("invalid-utf8.rs", [0x66, 0x80, 0x0A]);
|
|
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--context")
|
|
.arg("0")
|
|
.arg(format!("{}:1", source.display()))
|
|
.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains("failed to read"))
|
|
.stderr(predicate::str::contains("invalid-utf8.rs"));
|
|
}
|
|
|
|
#[test]
|
|
fn help_includes_rg_and_powershell_examples() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--help")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("rg -nH"))
|
|
.stdout(predicate::str::contains("ConvertFrom-Json"))
|
|
.stdout(predicate::str::contains("--max-gap"));
|
|
}
|
|
|
|
#[test]
|
|
fn help_puts_rg_nh_before_pathless_rg_examples() {
|
|
let mut command = cargo_command();
|
|
let output = command
|
|
.arg("--help")
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.stdout
|
|
.clone();
|
|
let help = str::from_utf8(&output).expect("help is utf8");
|
|
let rg_nh = help.find("rg -nH").expect("rg -nH example");
|
|
let rg_n_pathless = help
|
|
.find("rg -n \"Mode::\"")
|
|
.expect("pathless rg -n example");
|
|
assert!(
|
|
rg_nh < rg_n_pathless,
|
|
"the safest rg -nH example should appear before pathless rg -n"
|
|
);
|
|
}
|