use super::*;
use crate::instrument::{Instrument, InstrumentCatalog, InstrumentStatus};
#[test]
fn a_check_serialises_flat_with_its_state_tag() {
let check = CurrencyCheck {
state: CurrencyState::Consolidated {
as_of: "02023R1542-20260813".to_owned(),
},
checked_on: "2026-09-11".to_owned(),
};
assert_eq!(
serde_json::to_value(&check).expect("serialise"),
serde_json::json!({
"state": "consolidated",
"asOf": "02023R1542-20260813",
"checkedOn": "2026-09-11",
})
);
}
#[test]
fn every_state_round_trips_through_its_wire_form() {
for state in [
CurrencyState::InForce,
CurrencyState::Consolidated {
as_of: "02024R1781-20240628".to_owned(),
},
CurrencyState::Repealed {
by: "32026R0248".to_owned(),
on: "2026-02-22".to_owned(),
},
] {
let check = CurrencyCheck {
state,
checked_on: "2026-09-11".to_owned(),
};
let json = serde_json::to_string(&check).expect("serialise");
let back: CurrencyCheck = serde_json::from_str(&json).expect("deserialise");
assert_eq!(back, check, "round-trip changed {json}");
}
}
#[test]
fn consolidated_is_still_law() {
assert!(CurrencyState::InForce.is_law());
assert!(
CurrencyState::Consolidated {
as_of: "02023R1542-20260813".to_owned(),
}
.is_law()
);
assert!(
!CurrencyState::Repealed {
by: "32026R0248".to_owned(),
on: "2026-02-22".to_owned(),
}
.is_law()
);
}
#[test]
fn only_a_consolidation_redirects_the_citation() {
assert_eq!(CurrencyState::InForce.cite_instead(), None);
assert_eq!(
CurrencyState::Consolidated {
as_of: "02023R1670-20250620".to_owned(),
}
.cite_instead(),
Some("02023R1670-20250620")
);
assert_eq!(
CurrencyState::Repealed {
by: "32026R0248".to_owned(),
on: "2026-02-22".to_owned(),
}
.cite_instead(),
None
);
}
#[test]
fn staleness_compares_iso_dates_lexicographically() {
let check = CurrencyCheck {
state: CurrencyState::InForce,
checked_on: "2026-09-11".to_owned(),
};
assert!(check.is_older_than("2026-09-12"));
assert!(check.is_older_than("2027-01-01"));
assert!(!check.is_older_than("2026-09-11"));
assert!(!check.is_older_than("2026-08-31"));
}
#[test]
fn an_adopted_act_carries_a_dated_currency_check_and_nothing_else_does() {
for instrument in InstrumentCatalog::new().all() {
let adopted = instrument.status == InstrumentStatus::Adopted;
assert_eq!(
instrument.currency.is_some(),
adopted,
"instrument '{}' is {:?} and its currency is {:?}",
instrument.id,
instrument.status,
instrument.currency
);
let Some(check) = &instrument.currency else {
continue;
};
let date = &check.checked_on;
assert!(
date.len() == 10
&& date.as_bytes()[4] == b'-'
&& date.as_bytes()[7] == b'-'
&& date.chars().filter(char::is_ascii_digit).count() == 8,
"instrument '{}' has checkedOn '{date}', which is not YYYY-MM-DD — \
the field is compared as a string and a stray format sorts wrongly \
rather than failing",
instrument.id
);
}
}
#[test]
fn a_consolidated_citation_names_a_consolidation_of_its_own_act() {
for instrument in InstrumentCatalog::new().all() {
let Some(as_of) = instrument
.currency
.as_ref()
.and_then(|c| c.state.cite_instead())
else {
continue;
};
let celex = instrument
.celex
.as_ref()
.expect("an adopted act carries a celex");
let (base, version) = as_of
.split_once('-')
.unwrap_or_else(|| panic!("'{}' asOf '{as_of}' has no version date", instrument.id));
assert_eq!(
base,
format!("0{}", &celex[1..]),
"instrument '{}' cites consolidation '{as_of}', which is not a \
consolidation of its own act '{celex}'",
instrument.id
);
assert!(
version.len() == 8 && version.chars().all(|c| c.is_ascii_digit()),
"instrument '{}' asOf '{as_of}' does not end in a YYYYMMDD version",
instrument.id
);
}
}
#[test]
fn a_repealed_act_keeps_its_citable_text_and_loses_its_currency() {
let repealed: Instrument = serde_json::from_str(
r#"{
"id": "ades-formats-2015-1506",
"title": "Commission Implementing Decision (EU) 2015/1506",
"celex": "32015D1506",
"kind": "implementing",
"status": "adopted",
"currency": {
"state": "repealed",
"by": "32026R0248",
"on": "2026-02-22",
"checkedOn": "2026-09-11"
},
"parent": "espr",
"passport": { "obligation": "notRequired" }
}"#,
)
.expect("the manifest wire shape deserialises");
assert!(
repealed.status.has_citable_text(),
"a repealed act still has a text to quote"
);
assert!(
!repealed.is_current_law(),
"a repealed act may not carry an obligation"
);
for instrument in InstrumentCatalog::new().all() {
if instrument.status != InstrumentStatus::Adopted {
continue;
}
assert!(
instrument.is_current_law(),
"instrument '{}' is adopted but not current law",
instrument.id
);
}
}
#[test]
fn an_adopted_act_with_no_recorded_check_is_not_current_law() {
let mut unchecked = InstrumentCatalog::new()
.get("battery-reg-2023-1542")
.expect("battery is embedded")
.clone();
assert!(unchecked.is_current_law());
unchecked.currency = None;
assert!(
!unchecked.is_current_law(),
"an unrecorded check must not read as a current one"
);
}
#[test]
fn the_staleness_query_reports_stale_and_never_checked_alike() {
let catalog = InstrumentCatalog::new();
assert!(
catalog.currency_checked_before("2026-09-11").is_empty(),
"the cutoff is exclusive, so a check made on it is not yet stale"
);
let stale = catalog.currency_checked_before("2026-09-12");
let adopted = catalog
.all()
.iter()
.filter(|i| i.status == InstrumentStatus::Adopted)
.count();
assert_eq!(
stale.len(),
adopted,
"every adopted act was checked before the cutoff"
);
let mut catalog = InstrumentCatalog::new();
let mut never = catalog.get("espr").expect("espr is embedded").clone();
never.id = "never-checked".to_owned();
never.currency = None;
catalog.register(never).expect("a fresh id");
assert!(
catalog
.currency_checked_before("1970-01-01")
.iter()
.any(|i| i.id == "never-checked"),
"an adopted act that was never checked must appear in every report"
);
}