use aura_ui::core::InputEvent;
use aura_ui::view::prelude::*;
use aura_ui::view::test_context::TestWindow;
const COUNT: usize = 1_000;
fn height(index: usize) -> f32 {
20.0 + (index % 3) as f32 * 15.0
}
struct Feed {
state: ListState,
built: Vec<usize>,
}
impl View for Feed {
fn view(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
self.built.clear();
let built = &mut self.built;
let feed = list(&self.state, |index| {
built.push(index);
div()
.h(px(height(index)))
.id(format!("row-{index}"))
.on_click(|_, _| {})
.child(format!("mensaje {index}"))
.into_element()
})
.h(px(200.0))
.w_full();
div().size_full().child(feed).into_element()
}
}
fn feed() -> (TestWindow, Handle<Feed>) {
let (mut test, feed) = TestWindow::new(|_| Feed { state: ListState::new(COUNT, px(30.0)), built: Vec::new() });
test.run_until_parked();
(test, feed)
}
#[test]
fn builds_only_what_fits_and_learns_real_heights() {
let (test, feed) = feed();
test.read(feed, |feed| {
assert!(feed.built.len() < 20, "construyó {} de {COUNT}", feed.built.len());
assert_eq!(feed.state.measured_height(1), Some(35.0));
assert_eq!(feed.state.measured_height(500), None, "lo nunca visto sigue estimado");
});
}
#[test]
fn wheel_scroll_moves_the_anchor() {
let (mut test, feed) = feed();
test.window.handle_event(&InputEvent::Scroll {
position: Point::new(px(10.0), px(10.0)),
delta: Point::new(px(0.0), px(-1_000.0)),
});
test.window.draw(None);
test.run_until_parked();
test.read(feed, |feed| {
let first = feed.built[0];
assert!((25..40).contains(&first), "tras 1000 px el primero es {first}");
});
}
#[test]
fn inserting_above_keeps_the_visible_item_in_place() {
let (mut test, feed) = feed();
let state = test.read(feed, |feed| feed.state.clone());
state.scroll_to_item(100);
test.window.draw(None);
test.run_until_parked();
state.splice(0..0, 5);
test.window.draw(None);
test.run_until_parked();
test.read(feed, |feed| assert_eq!(feed.built[0], 105, "el mismo mensaje sigue arriba"));
}
#[test]
fn dragging_the_list_scrollbar_continues_when_visible_rows_change() {
let (mut test, feed) = feed();
test.simulate_drag((794.0, 10.0), (794.0, 190.0));
test.run_until_parked();
test.read(feed, |feed| {
assert!(feed.built[0] > 800, "el arrastre siguió hasta abajo; primero visible: {}", feed.built[0]);
});
}
#[test]
fn following_the_end_shows_new_items_until_the_wheel_goes_up() {
let (mut test, feed) = feed();
let state = test.read(feed, |feed| feed.state.clone());
state.follow_end();
test.window.draw(None);
test.run_until_parked();
test.read(feed, |feed| assert_eq!(feed.built.last(), Some(&(COUNT - 1)), "el final está a la vista"));
state.splice(COUNT..COUNT, 3);
test.window.draw(None);
test.run_until_parked();
test.read(feed, |feed| assert_eq!(feed.built.last(), Some(&(COUNT + 2)), "sigue lo que llega"));
test.window.handle_event(&InputEvent::Scroll {
position: Point::new(px(10.0), px(10.0)),
delta: Point::new(px(0.0), px(400.0)),
});
test.window.draw(None);
test.run_until_parked();
assert!(!state.is_following_end(), "subir suelta el final");
state.splice(COUNT + 3..COUNT + 3, 1);
test.window.draw(None);
test.run_until_parked();
test.read(feed, |feed| assert!(feed.built.last() < Some(&(COUNT + 3)), "no salta al nuevo"));
}
struct Clicks {
state: ListState,
clicked: std::rc::Rc<std::cell::RefCell<Vec<usize>>>,
}
impl View for Clicks {
fn view(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let clicked = self.clicked.clone();
let rows = list(&self.state, |index| {
let clicked = clicked.clone();
div().h(px(height(index))).w_full().on_click(move |_, _| clicked.borrow_mut().push(index)).into_element()
});
div().size_full().child(rows.h(px(200.0)).w_full()).into_element()
}
}
#[test]
fn following_the_end_keeps_short_content_at_the_bottom() {
let clicked = std::rc::Rc::default();
let shared = std::rc::Rc::clone(&clicked);
let (mut test, _) = TestWindow::new(move |_| {
let state = ListState::new(2, px(30.0));
state.follow_end();
Clicks { state, clicked: shared }
});
test.run_until_parked();
for y in [10.0, 150.0, 190.0] {
test.simulate_click(10.0, y);
test.run_until_parked();
}
assert_eq!(*clicked.borrow(), vec![0, 1]);
}