use super::*;
#[test]
fn diff_pr_summary_markdown_reports_net_posture() {
let finding_changes = vec![DiffFindingChange {
change: "removed",
key: "panic|unwrap|src/lib.rs",
kind: "panic",
family: Some("unwrap"),
path: "src/lib.rs",
}];
let policy_changes = vec![DiffPolicyChange {
severity: "improvement",
allow_id: "allow-0001",
kind: "selector_precision_increased",
message: "allow-0001 selector precision increased",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
}];
let summary = render_diff_pr_summary_markdown(0, &finding_changes, &policy_changes);
assert!(summary.contains("**Net posture:** `improved`"));
assert!(summary.contains("| Current check failures | 0 |"));
assert!(summary.contains("| Removed source findings | 1 |"));
assert!(summary.contains("| Policy improvements | 1 |"));
assert!(summary.contains("keep the narrower posture"));
assert!(summary.contains("> Claim boundary: scanned source-tree/source syntax only;"));
assert!(summary.contains("cargo-allow did not invoke Cargo metadata"));
assert!(summary.contains("### Finding Improvements"));
assert!(summary.contains("| `removed` | `panic` | `unwrap` | `src/lib.rs` |"));
assert!(summary.contains("### Policy Improvements"));
assert!(summary.contains("| `allow-0001` | `selector_precision_increased` |"));
assert!(
!summary.contains("### Policy Failures"),
"improvement-only summaries should not create failure rows"
);
assert!(
!summary.contains("### Policy Review Required"),
"improvement-only summaries should not create review rows"
);
}
#[test]
fn diff_pr_summary_markdown_reports_evidence_health_rows() {
let summary = render_diff_pr_summary_markdown_with_evidence_health(1, 1, 2, &[], &[]);
assert!(summary.contains("**Net posture:** `worse`"));
assert!(summary.contains("| Current check failures | 1 |"));
assert!(summary.contains("| Broken evidence links | 1 |"));
assert!(summary.contains("| Weak evidence/link references | 2 |"));
assert!(summary.contains("**Evidence repair queues:**"));
assert!(
summary.contains("`cargo-allow worklist --item-kind broken_evidence_link --format json`")
);
assert!(
summary
.contains("`cargo-allow worklist --item-kind weak_evidence_reference --format json`")
);
}
#[test]
fn diff_posture_tables_escape_markdown_cells() {
let finding_changes = vec![DiffFindingChange {
change: "new",
key: "panic|unwrap|src/lib.rs",
kind: "panic|custom",
family: Some("unwrap`family"),
path: "src/lib.rs",
}];
let policy_changes = vec![DiffPolicyChange {
severity: "fail",
allow_id: "allow|0001",
kind: "scope_broadened",
message: "message with | pipe",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
}];
let findings = render_diff_finding_changes_markdown(&finding_changes);
let policy = render_diff_policy_changes_markdown(&policy_changes);
assert!(findings.contains("panic\\|custom"));
assert!(findings.contains("unwrap\\`family"));
assert!(policy.contains("allow\\|0001"));
assert!(policy.contains("message with \\| pipe"));
}
#[test]
fn diff_finding_markdown_groups_findings_by_change() {
let finding_changes = vec![
DiffFindingChange {
change: "removed",
key: "panic|unwrap|src/old.rs",
kind: "panic",
family: Some("unwrap"),
path: "src/old.rs",
},
DiffFindingChange {
change: "new",
key: "unsafe|unsafe_block|src/new.rs",
kind: "unsafe",
family: Some("unsafe_block"),
path: "src/new.rs",
},
];
let markdown = render_diff_finding_changes_markdown(&finding_changes);
let attention = markdown
.find("### Finding Attention")
.unwrap_or_else(|| std::panic::panic_any("expected attention section"));
let improvements = markdown
.find("### Finding Improvements")
.unwrap_or_else(|| std::panic::panic_any("expected improvement section"));
assert!(
attention < improvements,
"markdown finding sections should show attention before improvements"
);
assert!(markdown.contains("| `new` | `unsafe` | `unsafe_block` | `src/new.rs` |"));
assert!(markdown.contains("| `removed` | `panic` | `unwrap` | `src/old.rs` |"));
}
#[test]
fn diff_policy_markdown_groups_policy_changes_by_severity() {
let policy_changes = vec![
DiffPolicyChange {
severity: "review",
allow_id: "allow-review",
kind: "expiry_extended",
message: "allow-review expiry extended",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
},
DiffPolicyChange {
severity: "improvement",
allow_id: "allow-improved",
kind: "evidence_added",
message: "allow-improved evidence added",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
},
DiffPolicyChange {
severity: "fail",
allow_id: "allow-fail",
kind: "scope_broadened",
message: "allow-fail scope broadened",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
},
];
let markdown = render_diff_policy_changes_markdown(&policy_changes);
let failures = markdown
.find("### Policy Failures")
.unwrap_or_else(|| std::panic::panic_any("expected failure section"));
let review = markdown
.find("### Policy Review Required")
.unwrap_or_else(|| std::panic::panic_any("expected review section"));
let improvements = markdown
.find("### Policy Improvements")
.unwrap_or_else(|| std::panic::panic_any("expected improvement section"));
assert!(
failures < review && review < improvements,
"markdown policy sections should be ordered by reviewer severity"
);
assert!(markdown.contains("| `fail` | `allow-fail` | `scope_broadened` |"));
assert!(markdown.contains("| `review` | `allow-review` | `expiry_extended` |"));
assert!(markdown.contains("| `improvement` | `allow-improved` | `evidence_added` |"));
}
#[test]
fn diff_pr_summary_markdown_highlights_policy_review_required() {
let removed = vec!["test:old-proof".to_string()];
let policy_changes = vec![DiffPolicyChange {
severity: "review",
allow_id: "allow|0042",
kind: "evidence_removed",
message: "allow-0042 evidence removed from policy",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: Some(DiffEvidenceChange {
field: "evidence",
removed: &removed,
added: &[],
}),
metadata: None,
requirement: None,
policy_status: None,
}];
let summary = render_diff_pr_summary_markdown(0, &[], &policy_changes);
assert!(summary.contains("**Net posture:** `review-required`"));
assert!(summary.contains("### Policy Review Required"));
assert!(!summary.contains("### Policy Failures"));
assert!(
summary.contains("| Severity | Allow ID | Kind | Detail | Message |"),
"policy review rows should include structured details"
);
assert!(summary.contains("| `review` | `allow\\|0042` | `evidence_removed` |"));
assert!(summary.contains("evidence.evidence: removed: test:old-proof; added: none"));
assert!(summary.contains("allow-0042 evidence removed from policy"));
}
#[test]
fn diff_pr_summary_markdown_highlights_policy_failures_separately() {
let policy_changes = vec![
DiffPolicyChange {
severity: "fail",
allow_id: "allow-0001",
kind: "scope_broadened",
message: "allow-0001 scope broadened",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
},
DiffPolicyChange {
severity: "review",
allow_id: "allow-0002",
kind: "expiry_extended",
message: "allow-0002 expiry extended",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
},
];
let summary = render_diff_pr_summary_markdown(0, &[], &policy_changes);
assert!(summary.contains("**Net posture:** `worse`"));
assert!(summary.contains("### Policy Failures"));
assert!(summary.contains("| `fail` | `allow-0001` | `scope_broadened` |"));
assert!(summary.contains("### Policy Review Required"));
assert!(summary.contains("| `review` | `allow-0002` | `expiry_extended` |"));
}
#[test]
fn diff_pr_summary_markdown_highlights_new_findings() {
let finding_changes = vec![DiffFindingChange {
change: "new",
key: "panic|unwrap|src/lib.rs",
kind: "panic",
family: Some("unwrap"),
path: "src/lib.rs",
}];
let summary = render_diff_pr_summary_markdown(0, &finding_changes, &[]);
assert!(summary.contains("**Net posture:** `review-required`"));
assert!(summary.contains("### Finding Attention"));
assert!(summary.contains("| `new` | `panic` | `unwrap` | `src/lib.rs` |"));
assert!(
!summary.contains("### Finding Improvements"),
"new-only summaries should not create finding improvement rows"
);
}
#[test]
fn diff_pr_summary_markdown_reports_omitted_finding_highlights() {
let finding = DiffFindingChange {
change: "new",
key: "panic|unwrap|src/lib.rs",
kind: "panic",
family: Some("unwrap"),
path: "src/lib.rs",
};
let finding_changes = vec![finding; 9];
let summary = render_diff_pr_summary_markdown(0, &finding_changes, &[]);
assert!(summary.contains("1 additional new finding change omitted from this summary."));
}
#[test]
fn diff_pr_summary_markdown_reports_omitted_policy_highlights() {
let policy = DiffPolicyChange {
severity: "fail",
allow_id: "allow-0001",
kind: "scope_broadened",
message: "allow-0001 scope broadened",
exception_identity: None,
selector_identity: None,
selector_precision: None,
scope: None,
occurrence_limit: None,
lifecycle: None,
evidence: None,
metadata: None,
requirement: None,
policy_status: None,
};
let policy_changes = vec![policy; 10];
let summary = render_diff_pr_summary_markdown(0, &[], &policy_changes);
assert!(summary.contains("2 additional policy failures omitted from this summary."));
}