Files
typikon/tests/elide.rs
T

96 lines
3.3 KiB
Rust
Raw Normal View History

//! Every title the program can print, at every width it can be asked to print
//! at. The seven-day view cuts titles to fit, and the titles are full of em
//! dashes: a cut taken at a byte index rather than a character one panics, and
//! did, at 80 columns.
use std::process::Command;
use typikon::calendars::Date;
use typikon::day::week;
use typikon::jurisdictions::{CALENDARS, JURISDICTIONS};
/// The same cut the seven-day view makes. Kept in step with `main.rs::elide`
/// by exercising the binary below as well.
fn elide(text: &str, width: usize) -> String {
if width == 0 {
return String::new();
}
if text.chars().count() <= width {
return text.to_string();
}
let cut: String = text.chars().take(width - 1).collect();
let midpoint = cut
.char_indices()
.nth(cut.chars().count() / 2)
.map_or(cut.len(), |(i, _)| i);
let head = match cut[midpoint..].find(' ') {
Some(_) => match cut.trim_end().rfind(' ') {
Some(i) => &cut[..i],
None => &cut,
},
None => &cut,
};
format!("{}\u{2026}", head.trim_end_matches([' ', ',', ';']))
}
#[test]
fn no_title_of_any_year_can_be_cut_at_any_width_without_panicking() {
let start = Date::from_ymd(2020, 1, 1).unwrap();
for jur in JURISDICTIONS.iter().chain(CALENDARS.iter()) {
for day in week(start, 366 * 11, jur) {
for width in 0..=120 {
let out = elide(day.title(), width);
assert!(
out.chars().count() <= width.max(1),
"{}: {width} gave {} chars",
day.date,
out.chars().count()
);
}
}
}
}
#[test]
fn a_cut_never_lands_inside_a_character() {
// Every movable feast title carries an em dash, which is where this broke.
for title in [
"The Radiant and Life-giving Resurrection of our Lord \u{2014} Holy Pascha",
"Holy Pentecost \u{2014} the Descent of the Holy Spirit",
"Clean Monday \u{2014} the first day of the Great Fast",
"Meatfare Sunday \u{2014} the Sunday of the Last Judgement",
"\u{2014}\u{2014}\u{2014}\u{2014}\u{2014}\u{2014}\u{2014}\u{2014}",
] {
for width in 0..=80 {
let out = elide(title, width);
assert!(out.is_char_boundary(0));
assert!(std::str::from_utf8(out.as_bytes()).is_ok());
}
}
}
#[test]
fn the_binary_survives_every_terminal_width() {
let binary = concat!(env!("CARGO_MANIFEST_DIR"), "/target/release/typikon");
if !std::path::Path::new(binary).exists() {
eprintln!("skipping: {binary} not built");
return;
}
for width in [1, 20, 40, 60, 76, 78, 80, 82, 88, 100, 120, 200] {
for jur in ["new", "rocor", "ruthenian", "goarch"] {
let out = Command::new(binary)
.args(["-j", jur, "--date", "2026-01-01", "--days", "365"])
.env("COLUMNS", width.to_string())
.env_remove("TYPIKON_JURISDICTION")
.output()
.expect("the binary runs");
assert!(
out.status.success(),
"COLUMNS={width} -j {jur}: exit {:?}\n{}",
out.status.code(),
String::from_utf8_lossy(&out.stderr)
);
}
}
}