cranpose-ui 0.1.164

UI primitives for Cranpose
Documentation
use std::cell::RefCell;

use cranpose_ui_graphics::Point;

use super::*;

fn rotary_event(kind: PointerEventKind, vertical: f32) -> PointerEvent {
    PointerEvent::rotary(
        kind,
        RotaryScrollEvent::new(vertical, 0.0, 42),
        Point { x: 0.0, y: 0.0 },
    )
}

#[test]
fn bubble_node_receives_bubble_events_only() {
    let seen = Rc::new(RefCell::new(Vec::new()));
    let sink = Rc::clone(&seen);
    let node = RotaryInputModifierNode::new(
        RotaryPass::Bubble,
        Rc::new(move |event: RotaryScrollEvent| {
            sink.borrow_mut().push(event.vertical_scroll_pixels);
            false
        }),
    );
    let dispatch = node.pointer_input_handler().expect("handler");

    dispatch(rotary_event(PointerEventKind::RotaryScrollPre, -1.0));
    dispatch(rotary_event(PointerEventKind::RotaryScroll, -2.0));
    dispatch(PointerEvent::new(
        PointerEventKind::Scroll,
        Point { x: 0.0, y: 0.0 },
        Point { x: 0.0, y: 0.0 },
    ));

    assert_eq!(*seen.borrow(), vec![-2.0]);
}

#[test]
fn pre_node_receives_capture_events_only() {
    let seen = Rc::new(RefCell::new(Vec::new()));
    let sink = Rc::clone(&seen);
    let node = RotaryInputModifierNode::new(
        RotaryPass::Pre,
        Rc::new(move |event: RotaryScrollEvent| {
            sink.borrow_mut().push(event.vertical_scroll_pixels);
            false
        }),
    );
    let dispatch = node.pointer_input_handler().expect("handler");

    dispatch(rotary_event(PointerEventKind::RotaryScrollPre, -1.0));
    dispatch(rotary_event(PointerEventKind::RotaryScroll, -2.0));

    assert_eq!(*seen.borrow(), vec![-1.0]);
}

#[test]
fn returning_true_consumes_the_event() {
    let node = RotaryInputModifierNode::new(RotaryPass::Bubble, Rc::new(|_| true));
    let dispatch = node.pointer_input_handler().expect("handler");

    let event = rotary_event(PointerEventKind::RotaryScroll, -8.0);
    dispatch(event.clone());

    assert!(event.is_consumed());
}

#[test]
fn returning_false_leaves_the_event_unconsumed() {
    let node = RotaryInputModifierNode::new(RotaryPass::Bubble, Rc::new(|_| false));
    let dispatch = node.pointer_input_handler().expect("handler");

    let event = rotary_event(PointerEventKind::RotaryScroll, -8.0);
    dispatch(event.clone());

    assert!(!event.is_consumed());
}

#[test]
fn an_already_consumed_event_never_reaches_the_handler() {
    let calls = Rc::new(Cell::new(0));
    let counter = Rc::clone(&calls);
    let node = RotaryInputModifierNode::new(
        RotaryPass::Bubble,
        Rc::new(move |_| {
            counter.set(counter.get() + 1);
            false
        }),
    );
    let dispatch = node.pointer_input_handler().expect("handler");

    let event = rotary_event(PointerEventKind::RotaryScroll, -8.0);
    event.consume();
    dispatch(event);

    assert_eq!(calls.get(), 0);
}

#[test]
fn handler_sees_the_full_rotary_payload() {
    let captured = Rc::new(Cell::new(None));
    let sink = Rc::clone(&captured);
    let node = RotaryInputModifierNode::new(
        RotaryPass::Bubble,
        Rc::new(move |event: RotaryScrollEvent| {
            sink.set(Some(event));
            true
        }),
    );
    let dispatch = node.pointer_input_handler().expect("handler");

    dispatch(PointerEvent::rotary(
        PointerEventKind::RotaryScroll,
        RotaryScrollEvent::new(-64.0, 32.0, 777),
        Point { x: 0.0, y: 0.0 },
    ));

    assert_eq!(
        captured.get(),
        Some(RotaryScrollEvent::new(-64.0, 32.0, 777))
    );
}

#[test]
fn element_reuses_the_node_across_recomposition() {
    let first = RotaryInputElement::new(RotaryPass::Bubble, Rc::new(|_| false));
    let second = RotaryInputElement::new(RotaryPass::Bubble, Rc::new(|_| true));
    assert_eq!(first, second);
    assert!(first.always_update());

    let mut node = first.create();
    second.update(&mut node);

    let event = rotary_event(PointerEventKind::RotaryScroll, -1.0);
    node.pointer_input_handler().expect("handler")(event.clone());

    assert!(event.is_consumed(), "updated handler should be in effect");
}

#[test]
fn pre_and_bubble_elements_are_distinct() {
    let pre = RotaryInputElement::new(RotaryPass::Pre, Rc::new(|_| false));
    let bubble = RotaryInputElement::new(RotaryPass::Bubble, Rc::new(|_| false));

    assert_ne!(pre, bubble);
}

#[test]
fn modifier_builders_add_pointer_input_elements() {
    let modifier = Modifier::empty()
        .on_pre_rotary_scroll_event(|_| false)
        .on_rotary_scroll_event(|_| true);

    assert_eq!(modifier.elements().len(), 2);
}