use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;
static PASS_LINE_RE: Lazy<Regex> = Lazy::new(||
Regex::new(r"(?m)^PASSED [^\n]+\n?").unwrap());
static DOTS_RE: Lazy<Regex> = Lazy::new(||
Regex::new(r"(?m)^[\.FEsxX]{4,}\n?").unwrap());
static COLLECTED_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)^collected \d+ items?[^\n]*\n?").unwrap());
pub fn compress_pytest(raw: &str, exit_code: i32) -> String {
let cleaned = compactor::normalise(raw);
let s = COLLECTED_RE.replace_all(&cleaned, "");
if exit_code == 0 {
let out: Vec<&str> = s
.lines()
.filter(|l| l.starts_with("=") || l.contains(" passed"))
.collect();
return if out.is_empty() {
s.into_owned()
} else {
out.join("\n")
};
}
let s = PASS_LINE_RE.replace_all(&s, "");
let s = DOTS_RE.replace_all(&s, "");
compactor::collapse_blanks(&s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pytest_success_keeps_summary() {
let raw = "collected 5 items\nPASSED test_foo.py::test_a\nPASSED test_foo.py::test_b\n===== 5 passed in 0.12s =====\n";
let out = compress_pytest(raw, 0);
assert!(!out.contains("PASSED test_foo"), "{out}");
assert!(out.contains("5 passed"), "{out}");
}
#[test]
fn pytest_failure_strips_passing_keeps_failed() {
let raw = "PASSED test_foo.py::test_a\nFAILED test_foo.py::test_b - AssertionError\n===== 1 failed, 1 passed =====\n";
let out = compress_pytest(raw, 1);
assert!(!out.contains("PASSED test_foo"), "{out}");
assert!(out.contains("FAILED"), "{out}");
}
}