#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::indexing_slicing,
reason = "Panicking is acceptable and often desired in tests."
)]
use super::*;
use csl_legacy::csl_json::CSL_TYPES;
use serde_json::json;
#[test]
fn structured_circa_csl_dates_convert_to_approximate_edtf() {
let structured: DateValue = csl_legacy::csl_json::DateVariable {
date_parts: Some(vec![vec![1988]]),
circa: Some(true),
..Default::default()
}
.into();
assert_eq!(structured.value, "1988~");
}
fn minimal_reference(ref_type: &str) -> csl_legacy::csl_json::Reference {
csl_legacy::csl_json::Reference {
id: format!("contract-{ref_type}"),
ref_type: ref_type.to_string(),
title: Some("Contract Test Title".to_string()),
issued: Some(csl_legacy::csl_json::DateVariable {
date_parts: Some(vec![vec![2024]]),
..Default::default()
}),
..Default::default()
}
}
#[test]
fn every_csl_1_0_2_type_has_an_expectation_table_entry() {
for csl_type in CSL_TYPES {
assert!(
CSL_TYPE_MAP.iter().any(|row| &row.csl_type == csl_type),
"CSL_TYPES entry `{csl_type}` has no entry in `CSL_TYPE_MAP`; \
every CSL 1.0.2 type must be covered"
);
}
assert_eq!(
CSL_TYPE_MAP.len(),
CSL_TYPES.len(),
"CSL_TYPE_MAP size has drifted from CSL_TYPES; add or remove \
an entry so the two stay in lockstep"
);
}
#[test]
fn every_csl_1_0_2_type_round_trips_through_ref_type() {
let failures: Vec<String> = CSL_TYPE_MAP
.iter()
.filter_map(|row| {
let legacy = minimal_reference(row.csl_type);
let actual = InputReference::from(legacy).ref_type();
(actual != row.citum_ref_type).then(|| {
format!(
"{}: expected `{}`, got `{actual}`",
row.csl_type, row.citum_ref_type
)
})
})
.collect();
assert!(
failures.is_empty(),
"CSL type round-trip mismatches (see docs/specs/CSL_TYPE_CONVERSION_CONTRACT.md):\n{}",
failures.join("\n")
);
}
#[test]
fn map_with_capitalized_export_genre_still_round_trips_as_map() {
let mut legacy = minimal_reference("map");
legacy.genre = Some("Map".to_string());
let converted = InputReference::from(legacy);
assert_eq!(converted.ref_type(), "map");
}
#[test]
fn manuscript_with_recognized_collection_note_override_converts_to_collection() {
let mut legacy = minimal_reference("manuscript");
legacy.note = Some("type: collection".to_string());
legacy.archive = Some("University of Georgia Library".to_string());
legacy.parse_note_field_hacks();
assert_eq!(legacy.ref_type, "collection");
let converted = InputReference::from(legacy);
assert_eq!(converted.ref_type(), "collection");
let crate::reference::ClassExtension::Monograph(monograph) = converted.extension() else {
panic!(
"expected the archival Monograph shape for a `collection` conversion, got `{}`",
converted.ref_type()
);
};
assert_eq!(
monograph.archive.as_deref(),
Some("University of Georgia Library"),
"archival fields must survive the collection conversion"
);
}
#[test]
fn book_volume_title_note_field_survives_as_monograph_metadata() {
let mut legacy = minimal_reference("book");
legacy.note = Some("volume-title: History of Science".to_string());
legacy.parse_note_field_hacks();
let converted = InputReference::from(legacy);
let crate::reference::ClassExtension::Monograph(monograph) = converted.extension() else {
panic!("book must convert to a Monograph");
};
assert_eq!(
monograph.volume_title.as_deref(),
Some("History of Science")
);
assert!(monograph.container.is_none());
}
#[test]
fn map_scale_and_dimensions_survive_as_monograph_metadata() {
let mut legacy = minimal_reference("map");
legacy.note = Some("dimensions: 128cm×84cm".to_string());
legacy.extra.insert("scale".to_string(), json!("1:25000"));
legacy.parse_note_field_hacks();
let converted = InputReference::from(legacy);
let crate::reference::ClassExtension::Monograph(monograph) = converted.extension() else {
panic!("map must convert to a Monograph");
};
assert_eq!(monograph.scale.as_deref(), Some("1:25000"));
assert_eq!(monograph.size.as_deref(), Some("128cm×84cm"));
}
#[test]
fn standalone_article_version_note_field_survives_on_preprint() {
let mut legacy = minimal_reference("article");
legacy.note = Some("version: 2".to_string());
legacy.parse_note_field_hacks();
let converted = InputReference::from(legacy);
assert_eq!(converted.ref_type(), "preprint");
let crate::reference::ClassExtension::Monograph(monograph) = converted.extension() else {
panic!("standalone article must convert to a preprint Monograph");
};
assert_eq!(monograph.version.as_deref(), Some("2"));
}