#[cfg(all(feature = "leptos-0-8", not(feature = "leptos")))]
extern crate leptos_0_8 as leptos;
#[cfg(feature = "leptos")]
extern crate leptos_0_9 as leptos;
use std::sync::Arc;
use leptos::prelude::*;
use leptos::text_prop::TextProp;
use mf2::leptos::{
CatalogPreload, RequestI18n, Setup, install, install_catalogs, provide_locale_in_zone,
reader_time_zone,
};
use mf2::{
Arg, ArgValue, Compiled, DateTime, DateTimeValue, Dir, FormatContext, Formatter, Function,
NoErrors, Registry, TimeZone, TrArgs, tr_args1,
};
static FUNCTIONS: [(&str, &dyn Function); 1] = [("datetime", &mf2::fn_datetime::DATETIME)];
static REGISTRY: Registry = Registry::new(&FUNCTIONS);
static LOCALES: &[(&str, Dir)] = &[("en", Dir::Ltr)];
const NEW_YEAR: i64 = 1_767_225_600_000;
const MESSAGE: &str = "{$when :datetime}";
fn installed() {
static ONCE: std::sync::Once = std::sync::Once::new();
ONCE.call_once(|| {
let compiled = mf2::compile_str(MESSAGE, "en").expect("the message compiles");
let hash = compiled.catalog.manifest_hash();
let bytes: &'static [u8] = Vec::leak(compiled.catalog.into_bytes());
install(
Setup::new(®ISTRY, &mf2::host_std::HOST, hash, "en", LOCALES)
.with_time_zone(zone("Asia/Tokyo")),
);
install_catalogs(&[("en", "en.test.mf2b", bytes)]).expect("the catalog loads");
});
}
fn zone(name: &str) -> TimeZone {
TimeZone::named(name).expect("a zone name")
}
fn when() -> TrArgs {
let value = DateTimeValue::instant(NEW_YEAR).expect("an instant");
tr_args1(Compiled::ID, ArgValue::from(value))
}
fn in_request<R>(reader: Option<&str>, body: impl FnOnce() -> R) -> R {
installed();
Owner::new().with(|| {
provide_locale_in_zone("en", reader.map(zone));
body()
})
}
fn formatted(source: &str, zone: TimeZone) -> String {
installed();
let compiled = mf2::compile_str(source, "en").expect("compiles");
let mut cx = FormatContext::new(&mf2::host_std::HOST);
cx.time_zone = zone;
let f = Formatter::new(&compiled.catalog, ®ISTRY, &cx);
let mut out = String::new();
let when = DateTime::from_epoch_ms(NEW_YEAR).expect("an instant");
f.write(
Compiled::ID,
&[Arg::DateTime(&when)],
&mut out,
&mut NoErrors,
);
out
}
fn in_zone(name: &str) -> String {
formatted(MESSAGE, zone(name))
}
#[test]
fn the_zones_this_test_uses_give_different_text() {
let texts = ["Asia/Tokyo", "America/New_York", "Asia/Kolkata", "UTC"].map(in_zone);
for (i, a) in texts.iter().enumerate() {
for b in texts.iter().skip(i + 1) {
assert_ne!(a, b);
}
}
}
#[test]
fn without_the_readers_zone_a_date_is_in_setups() {
assert_eq!(in_request(None, || when().to_html()), in_zone("Asia/Tokyo"));
}
#[test]
fn the_readers_zone_outranks_setups() {
let ny = in_request(Some("America/New_York"), || when().to_html());
assert_eq!(ny, in_zone("America/New_York"));
let kolkata = in_request(Some("Asia/Kolkata"), || when().to_html());
assert_eq!(kolkata, in_zone("Asia/Kolkata"));
}
fn for_new_york(source: &str) -> String {
installed();
let catalog = Arc::new(mf2::compile_str(source, "en").expect("compiles").catalog);
Owner::new().with(|| {
RequestI18n::new(catalog)
.with_time_zone(zone("America/New_York"))
.provide();
when().to_html()
})
}
#[test]
fn the_zone_a_message_names_outranks_the_readers() {
let named = "{$when :datetime timeZone=|Asia/Kolkata|}";
assert_eq!(for_new_york(named), in_zone("Asia/Kolkata"));
let input = "{$when :datetime timeZone=input}";
assert_eq!(for_new_york(input), formatted(input, TimeZone::UTC));
assert_eq!(for_new_york(input), in_zone("UTC"));
assert_eq!(for_new_york(MESSAGE), in_zone("America/New_York"));
}
#[test]
fn a_conversion_keeps_the_requests_zone_when_read_later() {
let text: TextProp = in_request(Some("America/New_York"), || when().into());
assert_eq!(text.get(), in_zone("America/New_York"));
}
#[test]
fn the_page_states_the_readers_zone_and_only_that() {
let link = |reader| in_request(reader, || view! { <CatalogPreload /> }.to_html());
let stated = link(Some("America/New_York"));
assert!(
stated.contains(r#"data-mf2-zone="America/New_York""#),
"{stated}"
);
assert!(stated.contains("en.test.mf2b"), "{stated}");
let silent = link(None);
assert!(!silent.contains("data-mf2-zone"), "{silent}");
}
#[test]
fn a_reader_zone_must_be_well_formed_and_known() {
installed();
assert!(reader_time_zone("America/New_York").is_some());
assert!(reader_time_zone("UTC").is_some());
for bad in [
"",
"Mars/Olympus_Mons",
"../etc/passwd",
"a b",
"é",
&"A".repeat(65),
] {
assert!(reader_time_zone(bad).is_none(), "{bad:?}");
}
}
#[test]
fn a_request_without_a_zone_formats_as_before() {
installed();
let catalog = Arc::new(mf2::compile_str(MESSAGE, "en").expect("compiles").catalog);
let html = Owner::new().with(|| {
RequestI18n::new(catalog).provide();
when().to_html()
});
assert_eq!(html, in_zone("Asia/Tokyo"));
}