Skip to main content

assert_snap/
assert_impl.rs

1//! Implementation module containing core assertion comparison and unified diff display logic.
2
3use std::borrow::Cow;
4
5use crate::redaction::{RedactionRule, apply_redactions};
6
7/// Asserts that an actual value matches an expected snapshot value after applying redaction rules.
8///
9/// This function compares `actual` against `expected` after applying the provided
10/// `redaction_rules` to the actual value. If they don't match, it prints diagnostic information
11/// and panics.
12///
13/// # Arguments
14///
15/// * `actual` - The actual value produced by the code under test.
16/// * `expected` - The expected snapshot value to compare against.
17/// * `redaction_rules` - A slice of redaction rules to apply to `actual` before comparison.
18///   These are typically used to mask dynamic content like timestamps, IDs, or memory addresses.
19///
20/// # Panics
21///
22/// Panics if the redacted `actual` does not equal `expected`. When the `diff` feature
23/// is enabled, a unified diff is printed showing the differences.
24///
25#[track_caller]
26pub fn assert_snap(actual: &str, expected: &str, redaction_rules: &[RedactionRule]) {
27    println!("===== ACTUAL VALUE =====");
28    println!("{actual}\n");
29    let actual = apply_redactions(actual, redaction_rules);
30    if matches!(actual, Cow::Owned(_)) {
31        println!("===== REDACTED VALUE =====");
32        println!("{actual}\n");
33    }
34
35    if expected != actual {
36        println!("===== EXPECTED VALUE =====");
37        println!("{expected}\n");
38        #[cfg(feature = "diff")]
39        show_diff(&actual, expected);
40        panic!("===== ASSERTION Failed =====");
41    }
42    println!("===== ASSERTION PASSED =====");
43}
44
45/// Displays a unified diff between the expected snapshot string and the actual/redacted output.
46///
47/// Enabled when the `diff` feature flag is active.
48#[cfg(feature = "diff")]
49#[track_caller]
50fn show_diff(actual: &str, expected: &str) {
51    use similar::TextDiff;
52
53    println!("===== DIFF =====");
54    let diff = TextDiff::from_lines(expected, actual);
55    println!(
56        "{}",
57        diff.unified_diff()
58            .header("EXPECTED VALUE", "ACTUAL/REDACTED VALUE")
59            .missing_newline_hint(false)
60    );
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    #[test]
67    fn test_assert_impl() {
68        let real = "User(id=123, name=Alice)";
69        let expected = "User(id=REDACTED, name=Alice)";
70        let rules = [RedactionRule::new(r"id=\d+", "id=REDACTED", 0)];
71        assert_snap(real, expected, &rules);
72    }
73}