use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;
mod common;
use common::validators::assert_html_well_formed;
fn cli() -> Command {
Command::cargo_bin("bca").expect("binary builds")
}
fn fixture_path() -> String {
let manifest = env!("CARGO_MANIFEST_DIR");
let workspace = std::path::Path::new(manifest)
.parent()
.expect("manifest dir has parent");
workspace
.join("tests/repositories/DeepSpeech/stats.py")
.to_str()
.expect("path is utf-8")
.to_string()
}
#[test]
fn report_html_help_lists_format_top_and_strip_prefix() {
cli()
.args(["report", "--help"])
.assert()
.success()
.stdout(predicate::str::contains("html"))
.stdout(predicate::str::contains("markdown"))
.stdout(predicate::str::contains("--top"))
.stdout(predicate::str::contains("--strip-prefix"));
}
#[test]
fn report_html_to_stdout_is_well_formed() {
let output = cli()
.args(["--paths", &fixture_path(), "report", "html"])
.output()
.expect("invocation succeeds");
assert!(
output.status.success(),
"stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let body = String::from_utf8(output.stdout).expect("output is UTF-8");
assert!(body.contains("<!doctype html>"));
assert!(body.contains("<h1>Code Quality Metrics Summary</h1>"));
assert!(body.contains("<h2>Python</h2>"));
assert_html_well_formed(&body);
}
#[test]
fn report_html_to_file_is_well_formed() {
let dir = TempDir::new().expect("tempdir");
let out = dir.path().join("report.html");
cli()
.args([
"--paths",
&fixture_path(),
"report",
"html",
"--output",
out.to_str().expect("utf-8"),
])
.assert()
.success();
let body = std::fs::read_to_string(&out).expect("read report");
assert!(body.contains("<!doctype html>"));
assert!(body.contains("class=\"hotspot\""));
assert_html_well_formed(&body);
}
#[test]
fn report_html_top_zero_rejected() {
cli()
.args(["report", "html", "--top", "0", "--paths", &fixture_path()])
.assert()
.failure()
.stderr(predicate::str::contains("--top"));
}
#[test]
fn report_html_with_no_paths_is_well_formed() {
let output = cli()
.args(["report", "html"])
.output()
.expect("invocation succeeds");
assert!(output.status.success());
let body = String::from_utf8(output.stdout).expect("utf-8");
assert!(body.contains("<h1>Code Quality Metrics Summary</h1>"));
assert!(!body.contains("class=\"hotspot\""));
assert_html_well_formed(&body);
}
#[test]
fn report_html_is_deterministic_across_runs() {
let fp = fixture_path();
let outputs: Vec<Vec<u8>> = (0..3)
.map(|_| {
cli()
.args(["--paths", &fp, "report", "html"])
.output()
.expect("invocation")
.stdout
})
.collect();
assert!(
outputs.windows(2).all(|w| w[0] == w[1]),
"non-deterministic HTML report across 3 runs"
);
}
#[test]
fn report_html_strip_prefix_removes_path_prefix() {
let fp = fixture_path();
let prefix = {
let idx = fp
.find("DeepSpeech/")
.expect("fixture contains DeepSpeech/");
&fp[..idx]
};
let output = cli()
.args(["--paths", &fp, "report", "html", "--strip-prefix", prefix])
.output()
.expect("invocation");
assert!(output.status.success());
let body = String::from_utf8(output.stdout).expect("utf-8");
assert!(
body.contains("DeepSpeech/stats.py"),
"stripped path should appear in HTML report"
);
assert!(
!body.contains(&fp),
"full unstripped path should not appear: {fp}"
);
assert_html_well_formed(&body);
}