tawasuyu/llimphi
Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.
chore: refresco desde el monorepo — vello 0.9 / wgpu 29, 120 miembros
1//! El **pie de paginación** de la data-table (`detail-table`), montado.
2//!
3//! La aritmética —qué rango, qué botones, dónde van las elipsis— se prueba en
4//! el crate. Acá se prueba lo que sólo se ve montando: que las flechas de los
5//! extremos se **apaguen** en vez de desaparecer (si no, el pie cambia de ancho
6//! al llegar al final y los botones se te mueven bajo el dedo), que la página
7//! actual no sea clickeable, y que cada número lleve a **su** página.
8//!
9//! Sin GPU (CLAUDE.md §8).
10
11use llimphi_test::query::{Sel, Ui};
12use llimphi_ui::Role;
13use llimphi_ui::View;
14use llimphi_widget_detail_table::{pager_view, DetailPalette, Pagina};
15
16#[derive(Clone, Debug, PartialEq)]
17enum Msg {
18 Ir(usize),
19}
20
21fn pager(indice: usize, total_filas: usize) -> Ui<Msg> {
22 let v: View<Msg> = pager_view(
23 Pagina { indice, tamano: 20 },
24 total_filas,
25 Msg::Ir,
26 &DetailPalette::default(),
27 );
28 Ui::new(v, 500.0, 30.0)
29}
30
31#[test]
32fn las_flechas_de_los_extremos_se_apagan_pero_siguen_estando() {
33 let primera = pager(0, 137);
34 let anterior = primera.get("Página anterior");
35 assert!(!anterior.is_enabled(), "{}", primera.dump());
36 assert_eq!(anterior.click(), None);
37 assert_eq!(primera.get("Página siguiente").click(), Some(Msg::Ir(1)));
38
39 // En la última, al revés — y las dos siguen presentes: si desaparecieran,
40 // el pie cambiaría de ancho y los números se moverían bajo el cursor.
41 let ultima = pager(6, 137);
42 assert!(ultima.find("Página anterior").is_some());
43 assert!(!ultima.get("Página siguiente").is_enabled());
44 assert_eq!(ultima.get("Página anterior").click(), Some(Msg::Ir(5)));
45}
46
47#[test]
48fn cada_numero_lleva_a_su_pagina_y_la_actual_no_se_clickea() {
49 let ui = pager(0, 137);
50 // 137 filas de a 20 son 7 páginas.
51 assert_eq!(ui.get("Página 7").click(), Some(Msg::Ir(6)));
52 // La actual está marcada y no emite nada: clickear donde ya estás no debe
53 // disparar un re-render ni un fetch.
54 let actual = ui.get("Página 1");
55 assert_eq!(actual.is_checked(), Some(true));
56 assert_eq!(actual.click(), None);
57}
58
59#[test]
60fn el_rotulo_dice_que_filas_se_estan_viendo() {
61 assert!(pager(0, 137).find("1–20 de 137").is_some());
62 assert!(pager(6, 137).find("121–137 de 137").is_some(), "{}", pager(6, 137).dump());
63 // Sin filas no dice «1–0 de 0».
64 assert!(pager(0, 0).find("Sin filas").is_some());
65}
66
67#[test]
68fn con_muchas_paginas_hay_elipsis_y_los_extremos_siempre_estan() {
69 // 20 páginas, parado en el medio.
70 let ui = pager(10, 400);
71 assert!(ui.find("Página 1").is_some(), "{}", ui.dump());
72 assert!(ui.find("Página 20").is_some());
73 assert!(ui.find("Página 11").is_some(), "la actual tiene que verse");
74 // La tira no crece sin límite: con 20 páginas no hay 20 botones.
75 let botones = ui.find_all(Sel::new().role(Role::Button));
76 assert!(botones.len() <= 10, "la tira tiene {} botones", botones.len());
77}