#![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::Warning;
use crate::{
json,
schema::{self, Integrity},
FromSchema as _,
};
const TARIFF: &str = r#"{
"currency": "EUR",
"elements": [
{"price_components": [{"price": {PRICE}, "step_size": 1, "type": "ENERGY"}]}
],
"id": "ID",
"last_updated": "2024-01-01T00:00:00Z"
}"#;
fn price<'a, 'buf>(tariff: &'a schema::v211::Tariff<'buf>) -> &'a schema::Number<'buf> {
let Integrity::Ok(elements) = &tariff.elements else {
panic!("elements should be built: {:?}", tariff.elements);
};
let Integrity::Ok(element) = &elements[0] else {
panic!("the element should be built");
};
let Integrity::Ok(components) = &element.price_components else {
panic!("price_components should be built");
};
let Integrity::Ok(component) = &components[0] else {
panic!("the price component should be built");
};
let Integrity::Ok(price) = &component.price else {
panic!("price should be built: {:?}", component.price);
};
price
}
#[test]
fn string_encoded_number_lowers_to_decimal() {
let src = TARIFF.replace("{PRICE}", r#""3.14159""#);
let doc = json::parse(src.as_str().into()).unwrap();
let tariff = schema::v211::build_tariff(&doc).ignore_warnings();
let (number, warnings) = Decimal::from_schema(price(&tariff)).unwrap().into_parts();
assert_eq!(number, dec!(3.14159));
let warnings = warnings.path_map();
assert_matches!(
*warnings["$.elements[0].price_components[0].price"],
[Warning::ExcessivePrecision]
);
}
#[test]
fn string_encoded_non_numeric_is_rejected() {
let src = TARIFF.replace("{PRICE}", r#""3.14A1""#);
let doc = json::parse(src.as_str().into()).unwrap();
let tariff = schema::v211::build_tariff(&doc).ignore_warnings();
let err_set = Decimal::from_schema(price(&tariff)).unwrap_err();
let (error, warnings) = err_set.into_parts();
let (error, _element) = error.into_parts();
assert_matches!(error, Warning::Decimal(_));
assert!(warnings.path_map().is_empty());
}
#[test]
fn string_encoded_with_escapes_is_rejected() {
let src = TARIFF.replace("{PRICE}", r#""3.14\n159""#);
let doc = json::parse(src.as_str().into()).unwrap();
let tariff = schema::v211::build_tariff(&doc).ignore_warnings();
let err_set = Decimal::from_schema(price(&tariff)).unwrap_err();
let (error, warnings) = err_set.into_parts();
let (error, _element) = error.into_parts();
assert_matches!(error, Warning::ContainsEscapeCodes);
assert!(warnings.path_map().is_empty());
}