mitsuhiko / insta

A snapshot testing library for rust
https://insta.rs
Apache License 2.0
2.25k stars 101 forks source link

Deep match (double-asterisk) should recurse down into arrays #687

Open adamchalmers opened 1 week ago

adamchalmers commented 1 week ago

Background

I have a deeply recursive structure I am trying to snapshot test. The nodes in the tree have many arrays of other nodes, and many maps where the values are other nodes. It's not really feasible to determine the structure ahead of time. Some of the primitive/terminal/leaf nodes in this tree are f64s.

Problem

f64 math produces different results on different target triples, so I need to round the numbers before serializing them. I figured I'd use the rounded_redactions(n) feature and just round-redact all numbers in the tree. But there's no clear way to do this. Here's an example.

#[derive(serde::Serialize, serde::Deserialize)]
struct Node {
    data: f64,
    nodes: Vec<Node>,
}

#[test]
fn test_recurse() {
    // Build the test data
    let data = Node {
        data: f64::tan(1.0),
        nodes: vec![
            Node {
                data: f64::tan(2.0),
                nodes: vec![Node {
                    data: f64::tan(4.0),
                    nodes: vec![Node {
                        data: f64::tan(5.0),
                        nodes: vec![],
                    }],
                }],
            },
            Node {
                data: f64::tan(3.0),
                nodes: vec![],
            },
        ],
    };

    // Try redacting.
    insta::assert_yaml_snapshot!("data", data, {
        // Matches the root node, but none of its children.
        ".**" => insta::rounded_redaction(3),
        // Matches the children of root, but requires knowing the name of the key you want to redact.
        // ".**[].data" => insta::rounded_redaction(3),
    });
}

This redacts the root node, so tan(1.0) gets rounded, but none of its children do. I think this is because ** doesn't recurse down into a child if the child is an array. Only to child keys.

I can add another redaction for ".**[].data" and then it matches all the children (and the children of children). That's great, but it requires that I know the data key ahead of time. For some reason ".**[].*" doesn't work either, it fails to find any of the child data keys.

Is there any simple way to say "match every single child and element of array"?