#![allow(
clippy::indexing_slicing,
clippy::unwrap_in_result,
reason = "unwraps and indexing are allowed anywhere in tests"
)]
use std::assert_matches;
use super::{Code, Warning};
use crate::{
json,
schema::{self, v211, Integrity},
warning, FromSchema as _,
};
const VALID: &str = r#"{
"currency": "EUR",
"elements": [
{"price_components": [{"price": 0.25, "step_size": 1, "type": "ENERGY"}]}
],
"id": "ID",
"last_updated": "2024-01-01T00:00:00Z"
}"#;
fn build_tariff<'buf>(doc: &json::Document<'buf>) -> v211::Tariff<'buf> {
v211::build_tariff(doc).ignore_warnings()
}
fn currency<'a, 'buf>(tariff: &'a v211::Tariff<'buf>) -> &'a schema::Str<'buf> {
let Integrity::Ok(currency) = &tariff.currency else {
panic!("the currency should be built: {:?}", tariff.currency);
};
currency
}
fn all_warnings(warnings: &warning::Set<Warning>) -> Vec<&Warning> {
warnings.path_map().into_values().flatten().collect()
}
fn lower(value: &str) -> crate::Verdict<Code, Warning> {
let src = VALID.replace(r#""currency": "EUR""#, value);
let doc = json::parse(src.as_str().into()).unwrap();
let tariff = build_tariff(&doc);
Code::from_schema(currency(&tariff))
}
#[test]
fn valid_uppercase_code_lowers_cleanly() {
let doc = json::parse(VALID.into()).unwrap();
let tariff = build_tariff(&doc);
let (code, warnings) = Code::from_schema(currency(&tariff)).unwrap().into_parts();
assert_eq!(code.into_str(), "EUR");
assert!(all_warnings(&warnings).is_empty());
}
#[test]
fn lowercase_code_warns_but_lowers() {
let (code, warnings) = lower(r#""currency": "eur""#).unwrap().into_parts();
assert_eq!(code.into_str(), "EUR");
assert_matches!(all_warnings(&warnings)[..], [Warning::PreferUpperCase]);
}
#[test]
fn wrong_length_is_rejected() {
let err_set = lower(r#""currency": "EU""#).unwrap_err();
let (error, _warnings) = err_set.into_parts();
let (error, _element) = error.into_parts();
assert_matches!(error, Warning::InvalidLength);
}
#[test]
fn unknown_code_is_rejected() {
let err_set = lower(r#""currency": "ZZZ""#).unwrap_err();
let (error, _warnings) = err_set.into_parts();
let (error, _element) = error.into_parts();
assert_matches!(error, Warning::InvalidCode);
}
#[test]
fn xts_code_warns() {
let (code, warnings) = lower(r#""currency": "XTS""#).unwrap().into_parts();
assert_eq!(code.into_str(), "XTS");
assert_matches!(all_warnings(&warnings)[..], [Warning::InvalidCodeXTS]);
}
#[test]
fn no_currency_xxx_warns() {
let (code, warnings) = lower(r#""currency": "XXX""#).unwrap().into_parts();
assert_eq!(code.into_str(), "XXX");
assert_matches!(all_warnings(&warnings)[..], [Warning::InvalidCodeXXX]);
}
#[test]
fn escape_sequence_is_rejected() {
let err_set = lower(r#""currency": "E\tR""#).unwrap_err();
let (error, _warnings) = err_set.into_parts();
let (error, _element) = error.into_parts();
assert_matches!(error, Warning::ContainsEscapeCodes);
}