#![cfg(all(feature = "desktop", not(alloc_frugal)))]
use rust_widgets::core::Rect;
use rust_widgets::signal::{CustomSignalHub, EventSignalBinder};
use rust_widgets::widget::capability::WidgetFactory;
use rust_widgets::widget::widget_trait::Widget;
use rust_widgets::widget::{Button, CheckBox, Slider};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
#[test]
fn one_call_wires_a_unit_event() {
let factory = WidgetFactory::new_with_defaults();
let hub = Arc::new(CustomSignalHub::new());
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let mut binder = EventSignalBinder::new(Arc::clone(&hub));
let wired = binder.forward_all(&button);
assert!(wired >= 4, "`button` publishes four events, so all four must be wired (got {wired})");
let calls = Arc::new(AtomicUsize::new(0));
let counter = Arc::clone(&calls);
factory
.connect_event("button", "clicked", &hub, move || {
counter.fetch_add(1, Ordering::SeqCst);
})
.expect("`button` publishes `clicked`");
assert_eq!(calls.load(Ordering::SeqCst), 0, "nothing may fire before the click");
button.clicked_signal().emit();
assert_eq!(
calls.load(Ordering::SeqCst),
1,
"a control wired by `forward_all` must reach the name its capability publishes"
);
}
#[test]
fn one_call_wires_a_payload_carrying_event() {
let factory = WidgetFactory::new_with_defaults();
let hub = Arc::new(CustomSignalHub::new());
let mut slider = Slider::new(Rect::new(0, 0, 200, 30));
let mut binder = EventSignalBinder::new(Arc::clone(&hub));
let wired = binder.forward_all(&slider);
assert!(
wired >= 4,
"`slider` publishes `value_changed`, `slider_moved`, `slider_pressed`, \
`slider_released` (got {wired})"
);
for (control, event) in [("slider", "value_changed"), ("slider", "slider_moved")] {
let calls = Arc::new(AtomicUsize::new(0));
let counter = Arc::clone(&calls);
factory
.connect_event(control, event, &hub, move || {
counter.fetch_add(1, Ordering::SeqCst);
})
.expect("`slider` publishes these");
assert_eq!(calls.load(Ordering::SeqCst), 0);
}
slider.set_value(42);
assert!(slider.value() == 42, "the control must have taken the value");
}
#[test]
fn every_published_event_of_a_converted_control_is_wired() {
let hub = Arc::new(CustomSignalHub::new());
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let checkbox = CheckBox::new(Rect::new(0, 0, 80, 30));
let slider = Slider::new(Rect::new(0, 0, 200, 30));
let mut binder = EventSignalBinder::new(Arc::clone(&hub));
binder.forward_all(&button);
binder.forward_all(&checkbox);
binder.forward_all(&slider);
for (name, wired) in [
("button.clicked", binder.event_is_wired(&button, "clicked")),
("button.pressed", binder.event_is_wired(&button, "pressed")),
("button.released", binder.event_is_wired(&button, "released")),
("button.state_changed", binder.event_is_wired(&button, "state_changed")),
("check_box.toggled", binder.event_is_wired(&checkbox, "toggled")),
("check_box.state_changed", binder.event_is_wired(&checkbox, "state_changed")),
("slider.value_changed", binder.event_is_wired(&slider, "value_changed")),
("slider.slider_moved", binder.event_is_wired(&slider, "slider_moved")),
("slider.slider_pressed", binder.event_is_wired(&slider, "slider_pressed")),
("slider.slider_released", binder.event_is_wired(&slider, "slider_released")),
] {
assert!(wired, "`{name}` must be wired after one `forward_all` call");
}
}
#[test]
fn an_unwired_event_reports_unwired_rather_than_succeeding() {
let factory = WidgetFactory::new_with_defaults();
let hub = Arc::new(CustomSignalHub::new());
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let binder = EventSignalBinder::new(Arc::clone(&hub));
factory
.connect_event("button", "clicked", &hub, || {})
.expect("`button` publishes `clicked`, so subscribing must be accepted");
assert!(
!binder.event_is_wired(&button, "clicked"),
"a valid name with no wire must report unwired — reporting `true` would claim an \
emission path that does not exist"
);
assert!(!binder.event_is_wired(&button, "value_changed"));
}
#[test]
fn the_wiring_query_reflects_the_wire_lifecycle() {
let hub = Arc::new(CustomSignalHub::new());
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let mut binder = EventSignalBinder::new(Arc::clone(&hub));
assert!(!binder.event_is_wired(&button, "clicked"), "nothing is wired yet");
assert!(binder.forward_one(&button, "clicked"), "`clicked` must be wireable by name");
assert!(binder.event_is_wired(&button, "clicked"), "the wire must be visible");
binder.unbind_all();
assert!(
!binder.event_is_wired(&button, "clicked"),
"releasing the wire must be reflected, or a dropped binder would still look connected"
);
}
#[test]
fn wiring_an_unknown_name_reports_false() {
let hub = Arc::new(CustomSignalHub::new());
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let mut binder = EventSignalBinder::new(hub);
assert!(
!binder.forward_one(&button, "definitely_not_an_event"),
"a name with no signal must not be reported as wired"
);
}
#[test]
fn a_detached_binder_reports_nothing_wired() {
let button = Button::new("Go".to_string(), Rect::new(0, 0, 80, 30));
let mut binder = EventSignalBinder::detached();
assert_eq!(binder.forward_all(&button), 0, "a detached binder wires nothing");
assert!(!binder.forward_one(&button, "clicked"));
assert!(binder.is_empty(), "a detached binder must not claim subscriptions it lacks");
assert!(
!binder.event_is_wired(&button, "clicked"),
"nothing was wired, so the query must say so"
);
}
#[test]
fn a_control_with_no_events_reports_zero() {
let hub = Arc::new(CustomSignalHub::new());
let label = rust_widgets::widget::Label::new("text".to_string(), Rect::new(0, 0, 40, 20));
let mut binder = EventSignalBinder::new(hub);
assert_eq!(binder.forward_all(&label), 0, "`label` publishes no events");
}