155 lines
5.6 KiB
Rust
155 lines
5.6 KiB
Rust
//! Unabhängige Review-Proben: zwei behobene Vertragslücken, Timer und Mindestmaße.
|
|
//! Ausführung über den temporären Cargo-Treiber aus review.md.
|
|
use tb_frontend::forms::{self, FormCatalog, ObjectClass};
|
|
use tb_runtime::{
|
|
host::{CaptureHost, Host},
|
|
screen::TextScreen,
|
|
};
|
|
use tb_ui::forms::{FormsModel, PropertyValue as V};
|
|
use tb_vm::interp::{RunEvent, Vm};
|
|
|
|
fn model(class: ObjectClass) -> FormsModel {
|
|
let mut c = FormCatalog::default();
|
|
c.add("Form1", ObjectClass::Form, None, false);
|
|
c.add("List1", class, Some("Form1"), false);
|
|
let mut m = FormsModel::new(c.objects, 80, 25);
|
|
m.set_initial(0, prop(ObjectClass::Form, "WIDTH"), V::Integer(40))
|
|
.unwrap();
|
|
m.set_initial(0, prop(ObjectClass::Form, "HEIGHT"), V::Integer(12))
|
|
.unwrap();
|
|
m
|
|
}
|
|
fn prop(class: ObjectClass, name: &str) -> u16 {
|
|
forms::property(class, name).unwrap().0
|
|
}
|
|
|
|
#[test]
|
|
fn sorted_nach_befuellen_ordnet_liste_und_erhaelt_auswahl() {
|
|
let mut results = vec![];
|
|
for class in [ObjectClass::ListBox, ObjectClass::ComboBox] {
|
|
let mut m = model(class);
|
|
m.add_item((1, None), "b".into(), None).unwrap();
|
|
m.add_item((1, None), "a".into(), None).unwrap();
|
|
m.set(1, prop(class, "LISTINDEX"), V::Integer(0)).unwrap();
|
|
m.set(1, prop(class, "SORTED"), V::Boolean(true)).unwrap();
|
|
m.add_item((1, None), "c".into(), None).unwrap();
|
|
let list: Vec<_> = (0..3)
|
|
.map(|i| m.get_indexed(1, prop(class, "LIST"), i).unwrap())
|
|
.collect();
|
|
println!(
|
|
"{class:?}: {list:?}; Auswahl={:?}",
|
|
m.get(1, prop(class, "LISTINDEX")).unwrap()
|
|
);
|
|
results.push((list, m.get(1, prop(class, "LISTINDEX")).unwrap()));
|
|
}
|
|
for (list, index) in results {
|
|
assert_eq!(
|
|
list,
|
|
vec![
|
|
V::String("a".into()),
|
|
V::String("b".into()),
|
|
V::String("c".into())
|
|
]
|
|
);
|
|
assert_eq!(index, V::Integer(1));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn combo_simple_zeigt_seine_listeneintraege() {
|
|
let class = ObjectClass::ComboBox;
|
|
let mut m = model(class);
|
|
for (name, value) in [
|
|
("STYLE", V::Integer(1)),
|
|
("WIDTH", V::Integer(15)),
|
|
("HEIGHT", V::Integer(5)),
|
|
("LEFT", V::Integer(2)),
|
|
("TOP", V::Integer(2)),
|
|
("TEXT", V::String("frei".into())),
|
|
] {
|
|
m.set_initial(1, prop(class, name), value).unwrap();
|
|
}
|
|
m.add_item((1, None), "apfel".into(), None).unwrap();
|
|
m.add_item((1, None), "birne".into(), None).unwrap();
|
|
m.show(0, false).unwrap();
|
|
let mut screen = TextScreen::new();
|
|
m.render(&mut screen);
|
|
let text = tb_runtime::snapshot::text(&screen);
|
|
println!("{text}");
|
|
assert!(
|
|
text.contains("frei"),
|
|
"Kontrolle: das Control muss sichtbar sein"
|
|
);
|
|
assert!(text.contains("apfel") && text.contains("birne"));
|
|
}
|
|
|
|
#[test]
|
|
fn timer_array_wird_beim_laden_an_aktueller_hostzeit_aktiviert() {
|
|
let mut c = FormCatalog::default();
|
|
c.add("Form1", ObjectClass::Form, None, false);
|
|
c.add("Timer1", ObjectClass::Timer, Some("Form1"), true);
|
|
let src="DIM SHARED s$\nForm1.Show\nTimer1(0).Interval=100\nSTOP\nLOAD Timer1(1)\nTimer1(0).Interval=0\nSTOP\nDOEVENTS\nEND\nSUB Timer1_Timer(Index AS INTEGER)\nSHARED s$\ns$=s$+LTRIM$(STR$(Index))\nEND SUB";
|
|
let mut vm = Vm::new(tb_vm::compile_source_with_forms("FORM1", src, &c).unwrap());
|
|
let mut h = CaptureHost::default();
|
|
assert!(matches!(vm.run(&mut h), RunEvent::Stopped { .. }));
|
|
h.uhr_setzen(1000);
|
|
assert!(matches!(vm.run(&mut h), RunEvent::Stopped { .. }));
|
|
assert_eq!(vm.forms.next_deadline(), Some(1100));
|
|
h.uhr_setzen(1100);
|
|
assert_eq!(vm.run(&mut h), RunEvent::Ended);
|
|
assert_eq!(h.jetzt_ms(), 1100);
|
|
}
|
|
|
|
#[test]
|
|
fn listen_bleiben_auch_bei_minimalmassen_im_controlrechteck() {
|
|
let mut failures = vec![];
|
|
for (class, width, height) in [
|
|
(ObjectClass::ComboBox, 15, 5),
|
|
(ObjectClass::ListBox, 6, 4),
|
|
(ObjectClass::ComboBox, 1, 5),
|
|
(ObjectClass::ListBox, 1, 4),
|
|
(ObjectClass::ListBox, 6, 1),
|
|
] {
|
|
let mut m = model(class);
|
|
for (name, value) in [
|
|
("WIDTH", width),
|
|
("HEIGHT", height),
|
|
("LEFT", 2),
|
|
("TOP", 2),
|
|
] {
|
|
m.set_initial(1, prop(class, name), V::Integer(value))
|
|
.unwrap();
|
|
}
|
|
if class == ObjectClass::ComboBox {
|
|
m.set_initial(1, prop(class, "STYLE"), V::Integer(1))
|
|
.unwrap();
|
|
}
|
|
m.add_item((1, None), "apfel".into(), None).unwrap();
|
|
m.set(1, prop(class, "VISIBLE"), V::Boolean(false)).unwrap();
|
|
m.show(0, false).unwrap();
|
|
let mut screen = TextScreen::new();
|
|
m.render(&mut screen);
|
|
let before = tb_runtime::snapshot::text(&screen);
|
|
m.set(1, prop(class, "VISIBLE"), V::Boolean(true)).unwrap();
|
|
m.render(&mut screen);
|
|
let after = tb_runtime::snapshot::text(&screen);
|
|
let mut outside = vec![];
|
|
for (row, (a, b)) in before.lines().zip(after.lines()).enumerate() {
|
|
for (col, (a, b)) in a.chars().zip(b.chars()).enumerate() {
|
|
if a != b
|
|
&& !(row >= 2
|
|
&& row < 2 + height as usize
|
|
&& col >= 2
|
|
&& col < 2 + width as usize)
|
|
{
|
|
outside.push((row + 1, col + 1, a, b));
|
|
}
|
|
}
|
|
}
|
|
if !outside.is_empty() {
|
|
failures.push(format!("{class:?} {width}x{height}: {outside:?}"));
|
|
}
|
|
}
|
|
assert!(failures.is_empty(), "{}", failures.join("\n"));
|
|
}
|