Phase 6: Kompatibilitaetsabnahme abschliessen und archivieren

This commit is contained in:
2026-09-07 12:34:06 +02:00
parent 54ee427c1c
commit 993c3e7638
21 changed files with 752 additions and 58 deletions

View File

@@ -206,6 +206,9 @@ fn ereignis_direktive(name: &str, src: &str) -> Vec<Ereignisschritt> {
ms.parse()
.unwrap_or_else(|_| panic!("{name}: ungültige Zeit {ms:?}")),
));
} else if let Some(size) = teil.strip_prefix("resize:") {
let (cols, rows) = groesse_lesen(name, size);
out.push(Ereignisschritt::Ereignis(Ereignis::Groesse { cols, rows }));
} else if let Some(mouse) = teil.strip_prefix("mouse:") {
let fields: Vec<_> = mouse.split(',').map(str::trim).collect();
let [kind, button, shift, row, col] = fields.as_slice() else {
@@ -516,15 +519,22 @@ fn assert_output_matches(file: &str, want: &str, got: &str) {
(Some(w), Some(g)) => {
for (z, (wz, gz)) in w.lines().zip(g.lines()).enumerate() {
if wz != gz {
// Je Zelle zwei Hexziffern → Spalte aus dem Byteoffset.
let spalte = wz
// Der Snapshot lässt Fortsetzungszellen breiter Zeichen aus.
let index = wz
.chars()
.zip(gz.chars())
.position(|(a, b)| a != b)
.map(|i| i / 2 + 1)
.unwrap_or(0);
let paar =
|s: &str| s.chars().skip((spalte - 1) * 2).take(2).collect::<String>();
.map(|i| i / 2)
.unwrap_or_else(|| wz.len().min(gz.len()) / 2);
let prefix: String = want_text
.lines()
.nth(z)
.unwrap_or("")
.chars()
.take(index)
.collect();
let spalte = ratatui::text::Line::raw(prefix).width() + 1;
let paar = |s: &str| s.chars().skip(index * 2).take(2).collect::<String>();
panic!(
"{file}: Farbabweichung in Zeile {}, Spalte {spalte}:\n \
Soll: {}\n Ist: {}",
@@ -596,9 +606,9 @@ fn uhr_direktive_wird_gelesen() {
fn ereignisfolge_liefert_taste_maus_und_zeit_in_reihenfolge() {
let steps = ereignis_direktive(
"form.frm",
"' tb-events: key:%o | mouse:down,1,0,5,7 | time:250ms | key:<ENTER>",
"' tb-events: key:%o | mouse:down,1,0,5,7 | time:250ms | key:<ENTER> | resize:100x30",
);
assert_eq!(steps.len(), 4);
assert_eq!(steps.len(), 5);
assert!(
matches!(&steps[0], Ereignisschritt::Ereignis(tb_runtime::host::Ereignis::Taste(key, shift)) if key == "o" && *shift == 4)
);
@@ -609,6 +619,13 @@ fn ereignisfolge_liefert_taste_maus_und_zeit_in_reihenfolge() {
assert!(
matches!(&steps[3], Ereignisschritt::Ereignis(tb_runtime::host::Ereignis::Taste(key, _)) if key == tb_runtime::host::taste::ENTER)
);
assert!(matches!(
steps[4],
Ereignisschritt::Ereignis(tb_runtime::host::Ereignis::Groesse {
cols: 100,
rows: 30
})
));
}
#[test]
@@ -786,6 +803,38 @@ fn farbabweichung_nennt_zeile_spalte_soll_und_ist() {
assert!(m.contains("Zeile 1"), "{m}");
assert!(m.contains("Spalte 2"), "{m}");
assert!(m.contains("70") && m.contains("e1"), "{m}");
let kurz = format!("ab\n{marke}\n70\n");
let m = meldung(&want, &kurz);
assert!(m.contains("Spalte 2") && m.contains("Soll: 70"), "{m}");
let m = meldung(
&format!("中a\n{marke}\n7070\n"),
&format!("中a\n{marke}\n70e1\n"),
);
assert!(m.contains("Spalte 3") && m.contains("Ist: e1"), "{m}");
}
#[test]
fn release_formular_vergleicht_zeichen_und_attribute_unabhaengig() {
let path = compat_dir().join("release-formular.frm");
let want = std::fs::read_to_string(path.with_extension("out")).unwrap();
let got = run_corpus_file(&path, None);
assert_output_matches("release-formular.frm", &want, &got);
assert_eq!(got, run_corpus_file(&path, None));
let falscher_text = want.replacen("Click", "Falsch", 1);
assert!(meldung(&falscher_text, &got).contains("Abweichung in Zeile 1"));
let (text, attr) = want
.split_once(tb_runtime::snapshot::ATTRIBUT_MARKE)
.unwrap();
let falsche_farbe = format!(
"{text}{}{}",
tb_runtime::snapshot::ATTRIBUT_MARKE,
attr.replacen("e1", "71", 1)
);
let m = meldung(&falsche_farbe, &got);
assert!(
m.contains("Farbabweichung") && m.contains("Spalte 1"),
"{m}"
);
}
#[test]