197 lines
5.4 KiB
Rust
197 lines
5.4 KiB
Rust
//! Integration tests for the `chunkcat` command.
|
|
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use assert_cmd::Command;
|
|
use predicates::prelude::*;
|
|
use serde_json::Value;
|
|
use tempfile::{TempDir, tempdir};
|
|
|
|
const SAMPLE_RS: &str = "reading/sample.rs";
|
|
|
|
fn cargo_command() -> Command {
|
|
Command::cargo_bin("chunkcat").expect("binary")
|
|
}
|
|
|
|
fn fixture(path: &str) -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("..")
|
|
.join("..")
|
|
.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 display_path(path: &Path) -> String {
|
|
path.display().to_string()
|
|
}
|
|
|
|
#[test]
|
|
fn lists_chunk_inventory_in_text_mode() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg(fixture(SAMPLE_RS))
|
|
.arg("--max-lines")
|
|
.arg("8")
|
|
.arg("--overlap")
|
|
.arg("2")
|
|
.arg("--inventory")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("chunks=6"))
|
|
.stdout(predicate::str::contains("0 lines=1:8"))
|
|
.stdout(predicate::str::contains("5 lines=31:35"));
|
|
}
|
|
|
|
#[test]
|
|
fn renders_selected_chunk_with_line_numbers() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg(fixture(SAMPLE_RS))
|
|
.arg("--max-lines")
|
|
.arg("8")
|
|
.arg("--overlap")
|
|
.arg("2")
|
|
.arg("--chunk")
|
|
.arg("2")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("chunk=2 lines=13:20"))
|
|
.stdout(predicate::str::contains("13: pub enum Mode {"))
|
|
.stdout(predicate::str::contains("20: Mode::Safe"));
|
|
}
|
|
|
|
#[test]
|
|
fn emits_json_inventory_and_selected_chunk_payloads() {
|
|
let mut inventory = cargo_command();
|
|
let inventory_output = inventory
|
|
.arg("--json")
|
|
.arg(fixture(SAMPLE_RS))
|
|
.arg("--max-lines")
|
|
.arg("8")
|
|
.arg("--overlap")
|
|
.arg("2")
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.stdout
|
|
.clone();
|
|
let inventory_json = serde_json::from_slice::<Value>(&inventory_output).expect("inventory");
|
|
assert_eq!(inventory_json["path"], display_path(&fixture(SAMPLE_RS)));
|
|
assert_eq!(inventory_json["total_lines"], 35);
|
|
assert_eq!(inventory_json["chunks"][0]["start_line"], 1);
|
|
assert_eq!(inventory_json["chunks"][5]["end_line"], 35);
|
|
assert!(inventory_json["selected_chunk"].is_null());
|
|
|
|
let mut selected = cargo_command();
|
|
let selected_output = selected
|
|
.arg("--json")
|
|
.arg(fixture(SAMPLE_RS))
|
|
.arg("--max-lines")
|
|
.arg("8")
|
|
.arg("--overlap")
|
|
.arg("2")
|
|
.arg("--chunk")
|
|
.arg("4")
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.stdout
|
|
.clone();
|
|
let selected_json = serde_json::from_slice::<Value>(&selected_output).expect("selected");
|
|
assert_eq!(selected_json["selected_chunk"]["index"], 4);
|
|
assert_eq!(selected_json["selected_chunk"]["start_line"], 25);
|
|
assert_eq!(selected_json["selected_chunk"]["lines"][0]["number"], 25);
|
|
assert_eq!(
|
|
selected_json["selected_chunk"]["lines"][0]["text"],
|
|
" match mode {"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn supports_powershell_pipeline_for_path_input() {
|
|
let binary = assert_cmd::cargo::cargo_bin("chunkcat");
|
|
let input = fixture(SAMPLE_RS);
|
|
let script = format!(
|
|
"{} | & {} --json --max-lines 10 --chunk 1",
|
|
ps_quote(input.display()),
|
|
ps_quote(binary.display())
|
|
);
|
|
|
|
let mut command = pwsh_command(script);
|
|
command
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("\"selected_chunk\""))
|
|
.stdout(predicate::str::contains("\"index\":1"));
|
|
}
|
|
|
|
#[test]
|
|
fn utf8_bom_file_does_not_pollute_first_chunk_line() {
|
|
let (_dir, path) = temp_file("bom.txt", "\u{feff}alpha\nbeta\n");
|
|
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg(&path)
|
|
.arg("--max-lines")
|
|
.arg("2")
|
|
.arg("--chunk")
|
|
.arg("0")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("1: alpha"))
|
|
.stdout(predicate::str::contains("\u{feff}alpha").not());
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_utf8_file_reports_text_read_error() {
|
|
let (_dir, path) = temp_file("invalid-utf8.txt", [0x61, 0x80, 0x0A]);
|
|
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg(&path)
|
|
.arg("--max-lines")
|
|
.arg("2")
|
|
.arg("--chunk")
|
|
.arg("0")
|
|
.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains("looks like a binary file"))
|
|
.stderr(predicate::str::contains("invalid-utf8.txt"));
|
|
}
|
|
|
|
#[test]
|
|
fn help_includes_examples_and_pipeline_usage() {
|
|
let mut command = cargo_command();
|
|
command
|
|
.arg("--help")
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(
|
|
"chunkcat .\\fixtures\\reading\\sample.rs --max-lines 8",
|
|
))
|
|
.stdout(predicate::str::contains("--inventory"))
|
|
.stdout(predicate::str::contains("ConvertFrom-Json"))
|
|
.stdout(predicate::str::contains("--chunk"));
|
|
}
|