//! Tests for the test-only [`PathGlob`] matcher, which filters expected
//! "unexpected field" paths in golden test data.
//!
//! A glob is compared to a path piece by piece, where a piece is an object
//! member (`.name`) or an array index (`[n]`). A `*` piece matches any single
//! piece; all other pieces must match exactly, and the counts must be equal.

use super::test::PathGlob;
use super::Path;

fn path(s: &str) -> Path {
    Path(s.to_owned())
}

#[test]
fn glob_matches_root() {
    assert!(PathGlob::from("$").matches(&path("$")));
    assert!(!PathGlob::from("$").matches(&path("$.currency")));
}

#[test]
fn glob_matches_object_member() {
    assert!(PathGlob::from("$.currency").matches(&path("$.currency")));
    assert!(!PathGlob::from("$.currency").matches(&path("$.country")));
}

#[test]
fn glob_matches_array_index_in_brackets() {
    assert!(PathGlob::from("$[1]").matches(&path("$[1]")));
    assert!(!PathGlob::from("$[1]").matches(&path("$[2]")));
}

#[test]
fn wildcard_matches_any_single_piece() {
    // `*` matches an object member or an array index alike.
    assert!(PathGlob::from("$.*").matches(&path("$.currency")));
    assert!(PathGlob::from("$.*").matches(&path("$[1]")));
    // ...but the piece counts must still line up.
    assert!(!PathGlob::from("$.*").matches(&path("$")));
}

#[test]
fn wildcard_matches_within_a_deeper_path() {
    assert!(PathGlob::from("$.*.name").matches(&path("$[1].name")));
    assert!(PathGlob::from("$[1].*").matches(&path("$[1].name")));
    assert!(PathGlob::from("$.*.*").matches(&path("$[1].name")));
}

#[test]
fn glob_requires_equal_piece_count() {
    assert!(!PathGlob::from("$.elements").matches(&path("$.elements[0].type")));
    assert!(!PathGlob::from("$.elements[0].type.extra").matches(&path("$.elements[0].type")));
}

#[test]
fn lint_style_glob_mixes_wildcard_and_literal_index() {
    // The real golden-file form: a wildcard over the `elements` array plus a
    // literal index into `price_components`.
    let glob = PathGlob::from("$.elements.*.price_components[0].type");
    assert!(glob.matches(&path("$.elements[0].price_components[0].type")));
    assert!(glob.matches(&path("$.elements[3].price_components[0].type")));
    assert!(!glob.matches(&path("$.elements[3].price_components[1].type")));
}
