#![allow(
clippy::indexing_slicing,
reason = "unwraps and indexing are allowed anywhere in tests"
)]
use std::assert_matches;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use super::{Price, Warning};
use crate::{
json,
schema::{self, Integrity},
warning::{self, test::VerdictTestExt as _},
FromSchema as _, Verdict,
};
const TARIFF: &str = r#"{
"country_code": "NL",
"party_id": "ENE",
"currency": "EUR",
"id": "ID",
"last_updated": "2024-01-01T00:00:00Z",
"min_price": {PRICE},
"elements": [
{"price_components": [{"price": 0.25, "step_size": 1, "type": "ENERGY", "vat": 21}]}
]
}"#;
#[track_caller]
fn min_price(price: &str) -> (Verdict<Price, Warning>, warning::Set<schema::Warning>) {
let src = TARIFF.replace("{PRICE}", price);
let doc = json::parse(src.as_str().into()).unwrap();
let (tariff, schema_warnings) = schema::v221::build_tariff(&doc).into_parts();
let Integrity::Ok(Some(price)) = &tariff.min_price else {
panic!("min_price should be built: {:?}", tariff.min_price);
};
(Price::from_schema(price), schema_warnings)
}
#[test]
fn object_with_only_excl_vat_lowers() {
const PRICE: &str = r#"{ "excl_vat": 10.2 }"#;
let (verdict, _schema) = min_price(PRICE);
let price = verdict.unwrap().unwrap();
assert!(price.incl_vat.is_none());
assert_eq!(Decimal::from(price.excl_vat), dec!(10.2));
}
#[test]
fn object_with_excl_and_incl_vat_lowers() {
const PRICE: &str = r#"{ "excl_vat": 10.2, "incl_vat": 12.3 }"#;
let (verdict, _schema) = min_price(PRICE);
let price = verdict.unwrap().unwrap();
assert_eq!(Decimal::from(price.incl_vat.unwrap()), dec!(12.3));
assert_eq!(Decimal::from(price.excl_vat), dec!(10.2));
}
#[test]
fn bare_number_lowers_to_excl_vat() {
const PRICE: &str = "12.3";
let (verdict, schema_warnings) = min_price(PRICE);
let price = verdict.unwrap().unwrap();
assert!(price.incl_vat.is_none());
assert_eq!(Decimal::from(price.excl_vat), dec!(12.3));
let schema_warnings = schema_warnings.path_map();
assert_matches!(
*schema_warnings["$.min_price"],
[schema::Warning::TypeMismatch { .. }]
);
}
#[test]
fn object_without_excl_vat_is_rejected() {
const PRICE: &str = r#"{ "incl_vat": 12.3 }"#;
let (verdict, schema_warnings) = min_price(PRICE);
let error = verdict.unwrap_only_error();
assert_matches!(error.into_warning(), Warning::Rejected);
let schema_warnings = schema_warnings.path_map();
assert_matches!(
*schema_warnings["$.min_price"],
[schema::Warning::MissingField { name: "excl_vat" }]
);
}
#[test]
fn excl_vat_greater_than_incl_vat_warns() {
const PRICE: &str = r#"{ "excl_vat": 12.3, "incl_vat": 10.2 }"#;
let (verdict, _schema) = min_price(PRICE);
let (_price, warnings) = verdict.unwrap().into_parts();
let warnings = warnings.path_map();
assert_matches!(
*warnings["$.min_price"],
[Warning::ExclusiveVatGreaterThanInclusive]
);
}