use crate::domain::finding::Finding;
use crate::domain::rule_id::RuleId;
use crate::gates::ki_record::{FILINGS, axis};
use crate::gates::paths::ki_records_judged;
use crate::gates::{GateCtx, GateResult, Violation, front_matter_values, read_text};
pub const CITES: &[RuleId] = &[RuleId::FiledRecordCarriesItsReport];
const RULE: RuleId = RuleId::FiledRecordCarriesItsReport;
pub fn run(ctx: &GateCtx, args: &[String]) -> GateResult {
let mut violations = Vec::new();
for record in ki_records_judged(ctx, args)? {
let text = read_text(ctx, &record)?;
if axis(&text, "filing", &FILINGS).as_deref() != Some("filed") {
continue;
}
let named = front_matter_values(&text, "upstream")
.iter()
.any(|value| !value.is_empty());
if !named {
violations.push(Violation::Finding(Finding::on_file(
RULE,
&record,
"a filed record names no upstream:",
)));
}
if !text.lines().any(|line| line == "## Report") {
violations.push(Violation::Finding(Finding::on_file(
RULE,
&record,
"a filed record carries no ## Report section",
)));
}
}
Ok(violations)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gates::tests_support::ki_fixture_filing;
fn run_on(filing: &str, upstream: &str, body: &str) -> Vec<String> {
let dir = ki_fixture_filing(filing, upstream, body);
let ctx = GateCtx::new(dir.path().to_str().unwrap());
run(&ctx, &[])
.unwrap()
.iter()
.map(ToString::to_string)
.collect()
}
#[test]
fn an_unfiled_record_needs_no_report() {
for filing in ["gathering", "ready", "deferred"] {
assert!(
run_on(filing, "https://example.invalid/issues", "# V\n").is_empty(),
"filing {filing:?}"
);
}
}
#[test]
fn a_filed_record_demands_the_report_section() {
let out = run_on("filed", "https://example.invalid/issues/123", "# V\n");
assert_eq!(out.len(), 1);
assert!(out[0].starts_with("FAIL known-issues:a-filed-record-carries-its-report "));
assert!(out[0].ends_with(": a filed record carries no ## Report section"));
}
#[test]
fn a_filed_record_demands_the_issue_it_was_filed_as() {
let out = run_on("filed", "", "# V\n## Report\n```text\nbody\n```\n");
assert_eq!(out.len(), 1);
assert!(out[0].ends_with(": a filed record names no upstream:"));
}
#[test]
fn a_filed_record_with_its_report_passes() {
assert!(
run_on(
"filed",
"https://example.invalid/issues/123",
"# V\n## Report\n```text\nbody\n```\n"
)
.is_empty()
);
}
}