use assert_cmd::prelude::*;
use prview::git::git_cmd;
use std::ffi::OsString;
use std::fs;
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
fn run_git(repo: &Path, args: &[&str]) {
let status = git_cmd()
.args(["-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false"])
.args(args)
.current_dir(repo)
.status()
.expect("failed to run git command");
assert!(status.success(), "git command failed: {args:?}");
}
fn create_gate_fixture() -> TempDir {
let temp = tempfile::tempdir().expect("tempdir");
let repo = temp.path();
run_git(repo, &["init"]);
run_git(repo, &["config", "user.name", "Test User"]);
run_git(repo, &["config", "user.email", "test@example.com"]);
fs::write(repo.join("README.md"), "hello\n").expect("write file");
run_git(repo, &["add", "README.md"]);
run_git(repo, &["commit", "-m", "initial"]);
run_git(repo, &["branch", "-M", "main"]);
run_git(repo, &["checkout", "-b", "feature/gate-exit-codes"]);
fs::write(repo.join("README.md"), "hello\nworld\n").expect("update file");
run_git(repo, &["add", "README.md"]);
run_git(repo, &["commit", "-m", "change"]);
temp
}
fn path_without_semgrep(repo: &Path) -> OsString {
let bin_dir = repo.join(".test-bin");
fs::create_dir_all(&bin_dir).expect("create fixture bin dir");
let git_path = which::which("git").expect("git must be available for gate fixtures");
let git_file_name = git_path.file_name().expect("git path has file name");
fs::copy(&git_path, bin_dir.join(git_file_name)).expect("copy git into fixture PATH");
OsString::from(bin_dir)
}
fn prview_gate_command(repo: &Path) -> Command {
let mut command = Command::new(assert_cmd::cargo::cargo_bin!("prview"));
command
.current_dir(repo)
.env("PATH", path_without_semgrep(repo));
command
}
#[test]
fn gate_exits_zero_for_non_strict_conditional() {
let temp = create_gate_fixture();
prview_gate_command(temp.path())
.arg("gate")
.assert()
.code(0);
}
#[test]
fn gate_exits_two_for_strict_conditional() {
let temp = create_gate_fixture();
prview_gate_command(temp.path())
.args(["gate", "--strict"])
.assert()
.code(2);
}
#[test]
fn gate_exits_one_for_block_verdict() {
let temp = create_gate_fixture();
let repo = temp.path();
fs::write(
repo.join(".prview-policy.yml"),
"version: 1\nmode: block\ndefault_severity: block\n",
)
.expect("write policy");
run_git(repo, &["add", ".prview-policy.yml"]);
run_git(repo, &["commit", "-m", "block policy"]);
prview_gate_command(repo).arg("gate").assert().code(1);
}
#[test]
fn gate_exits_three_when_it_cannot_execute() {
let temp = tempfile::tempdir().expect("tempdir");
Command::new(assert_cmd::cargo::cargo_bin!("prview"))
.current_dir(temp.path())
.env("GIT_CEILING_DIRECTORIES", temp.path())
.arg("gate")
.assert()
.code(3);
}