#![allow(clippy::unwrap_used, clippy::expect_used, clippy::missing_const_for_fn)]
use std::process::Command;
fn tokf() -> Command {
Command::new(env!("CARGO_BIN_EXE_tokf"))
}
#[test]
fn run_echo_hello() {
let output = tokf().args(["run", "echo", "hello"]).output().unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "hello");
}
#[test]
fn run_no_filter_passes_through() {
let output = tokf()
.args(["run", "--no-filter", "echo", "hello"])
.output()
.unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "hello");
}
#[test]
fn run_timing_shows_duration() {
let output = tokf()
.args(["run", "--timing", "echo", "hello"])
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.is_empty() || stderr.contains("[tokf]"),
"unexpected stderr: {stderr}"
);
}
#[test]
fn run_false_propagates_exit_code() {
let output = tokf()
.args(["run", "--no-mask-exit-code", "false"])
.output()
.unwrap();
assert!(!output.status.success());
assert_ne!(output.status.code(), Some(0));
}
#[test]
fn run_exit_code_42() {
let output = tokf()
.args(["run", "--no-mask-exit-code", "sh", "-c", "exit 42"])
.output()
.unwrap();
assert_eq!(output.status.code(), Some(42));
}
#[test]
fn run_verbose_shows_resolution_details() {
let output = tokf()
.args(["run", "--verbose", "echo", "hello"])
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("[tokf]"),
"expected verbose output on stderr, got: {stderr}"
);
}
#[test]
fn run_nonexistent_command_exits_with_error() {
let output = tokf()
.args(["run", "nonexistent_cmd_xyz_99"])
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("[tokf] error"),
"expected error on stderr, got: {stderr}"
);
}
#[test]
fn run_no_filter_preserves_failing_exit_code() {
let output = tokf()
.args([
"run",
"--no-mask-exit-code",
"--no-filter",
"sh",
"-c",
"exit 7",
])
.output()
.unwrap();
assert_eq!(output.status.code(), Some(7));
}
#[test]
fn run_timing_with_matched_filter() {
let dir = tempfile::TempDir::new().unwrap();
let filters_dir = dir.path().join(".tokf/filters");
std::fs::create_dir_all(&filters_dir).unwrap();
std::fs::write(
filters_dir.join("echo.toml"),
"command = \"echo\"\n[on_success]\noutput = \"filtered\"",
)
.unwrap();
let output = tokf()
.args(["run", "--timing", "echo", "hello"])
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("[tokf] filter took"),
"expected timing output when filter matched, got: {stderr}"
);
}
#[test]
fn run_embedded_filter_from_empty_dir() {
let dir = tempfile::TempDir::new().unwrap();
let output = tokf()
.args(["--verbose", "run", "git", "status"])
.current_dir(dir.path())
.output()
.unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("built-in") || stderr.contains("git/status"),
"expected verbose output indicating built-in filter was matched, got: {stderr}"
);
}
#[test]
fn mask_exit_code_returns_zero_on_failure() {
let output = tokf()
.args(["run", "sh", "-c", "echo failure-msg; exit 1"])
.output()
.unwrap();
assert!(output.status.success(), "should exit 0 by default");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("failure-msg"),
"output should contain command output, got: {stdout}"
);
assert!(
stdout.starts_with("Error: Exit code 1\n"),
"error line should be prepended, got: {stdout}"
);
}
#[test]
fn mask_exit_code_no_error_line_on_success() {
let output = tokf()
.args(["run", "echo", "success-msg"])
.output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("success-msg"),
"successful command should print to stdout, got: {stdout}"
);
assert!(
!stdout.contains("Error: Exit code"),
"successful command should not have error line, got: {stdout}"
);
}
#[test]
fn mask_exit_code_filtered_failure() {
let dir = tempfile::TempDir::new().unwrap();
let filters_dir = dir.path().join(".tokf/filters");
std::fs::create_dir_all(&filters_dir).unwrap();
std::fs::write(
filters_dir.join("sh.toml"),
"command = \"sh\"\n[on_failure]\noutput = \"FILTERED_FAIL\"",
)
.unwrap();
let output = tokf()
.args(["run", "sh", "-c", "echo raw; exit 1"])
.current_dir(dir.path())
.output()
.unwrap();
assert!(output.status.success(), "should exit 0 by default");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("FILTERED_FAIL"),
"filtered output should be present, got: {stdout}"
);
assert!(
stdout.starts_with("Error: Exit code 1\n"),
"error line should be prepended, got: {stdout}"
);
}
#[test]
fn mask_exit_code_signal_exit_code() {
let output = tokf()
.args(["run", "sh", "-c", "echo signal-msg; exit 130"])
.output()
.unwrap();
assert!(output.status.success(), "should exit 0 by default");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("signal-msg"),
"output should contain command output, got: {stdout}"
);
assert!(
stdout.starts_with("Error: Exit code 130\n"),
"should prepend signal exit code, got: {stdout}"
);
}
#[test]
fn mask_exit_code_empty_output_on_failure() {
let output = tokf().args(["run", "sh", "-c", "exit 1"]).output().unwrap();
assert!(output.status.success(), "should exit 0 by default");
let stdout = String::from_utf8_lossy(&output.stdout);
assert_eq!(
stdout.trim(),
"Error: Exit code 1",
"empty failure should only show exit code line, got: {stdout}"
);
}
#[test]
fn no_mask_exit_code_propagates_exit_code() {
let output = tokf()
.args([
"run",
"--no-mask-exit-code",
"sh",
"-c",
"echo hello; exit 42",
])
.output()
.unwrap();
assert_eq!(output.status.code(), Some(42));
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("hello"),
"output should contain command output, got: {stdout}"
);
assert!(
!stdout.contains("Error: Exit code"),
"should not have error line with --no-mask-exit-code, got: {stdout}"
);
}