test(core/rust/ui): pagination unit test

[no changelog]
mmilata/tt-pin-keyboard
Martin Milata 2 years ago
parent ab0eef5de0
commit 80655747d0

@ -49,3 +49,43 @@ where
}
}
}
#[cfg(test)]
mod tests {
use super::*;
impl Tracer for Vec<u8> {
fn int(&mut self, i: i64) {
self.string(&i.to_string());
}
fn bytes(&mut self, b: &[u8]) {
self.extend(b)
}
fn string(&mut self, s: &str) {
self.extend(s.as_bytes())
}
fn symbol(&mut self, name: &str) {
self.extend(name.as_bytes())
}
fn open(&mut self, name: &str) {
self.extend(b"<");
self.extend(name.as_bytes());
self.extend(b" ");
}
fn field(&mut self, name: &str, value: &dyn Trace) {
self.extend(name.as_bytes());
self.extend(b":");
value.trace(self);
self.extend(b" ");
}
fn close(&mut self) {
self.extend(b">")
}
}
}

@ -11,3 +11,11 @@ impl Component for Empty {
fn paint(&mut self) {}
}
#[cfg(feature = "ui_debug")]
impl crate::trace::Trace for Empty {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Empty");
t.close();
}
}

@ -150,16 +150,28 @@ impl<T> Dimensions for Paragraphs<T> {
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Paragraphs<T>
where
T: AsRef<[u8]>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Paragraphs");
for paragraph in &self.list {
paragraph.trace(t);
pub mod trace {
use super::*;
use crate::ui::component::text::layout::trace::TraceSink;
impl<T> crate::trace::Trace for Paragraphs<T>
where
T: AsRef<[u8]>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Paragraphs");
let mut char_offset = self.offset.chr;
for paragraph in self.list.iter().skip(self.offset.par).take(self.visible) {
paragraph.layout.layout_text(
&paragraph.content.as_ref()[char_offset..],
&mut paragraph.layout.initial_cursor(),
&mut TraceSink(t),
);
t.string("\n");
char_offset = 0;
}
t.close();
}
t.close();
}
}
@ -292,37 +304,3 @@ where
}
}
}
#[cfg(feature = "ui_debug")]
pub mod trace {
use crate::ui::component::text::layout::trace::TraceSink;
use super::*;
pub struct TraceText<'a, T>(pub &'a Paragraph<T>);
impl<'a, T> crate::trace::Trace for TraceText<'a, T>
where
T: AsRef<[u8]>,
{
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
self.0.layout.layout_text(
self.0.content.as_ref(),
&mut self.0.layout.initial_cursor(),
&mut TraceSink(d),
);
}
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Paragraph<T>
where
T: AsRef<[u8]>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Paragraph");
t.field("content", &trace::TraceText(self));
t.close();
}
}

@ -101,41 +101,6 @@ mod tests {
use super::*;
impl Tracer for Vec<u8> {
fn int(&mut self, i: i64) {
self.string(&i.to_string());
}
fn bytes(&mut self, b: &[u8]) {
self.extend(b)
}
fn string(&mut self, s: &str) {
self.extend(s.as_bytes())
}
fn symbol(&mut self, name: &str) {
self.extend(name.as_bytes())
}
fn open(&mut self, name: &str) {
self.extend(b"<");
self.extend(name.as_bytes());
self.extend(b" ");
}
fn field(&mut self, name: &str, value: &dyn Trace) {
self.extend(name.as_bytes());
self.extend(b":");
value.trace(self);
self.extend(b" ");
}
fn close(&mut self) {
self.extend(b">")
}
}
fn trace(val: &impl Trace) -> String {
let mut t = Vec::new();
val.trace(&mut t);

@ -170,6 +170,7 @@ where
t.field("active_page", &self.scrollbar.active_page);
t.field("page_count", &self.scrollbar.page_count);
t.field("content", &self.content);
t.field("buttons", &self.buttons);
t.close();
}
}
@ -307,3 +308,170 @@ impl PageLayout {
}
}
}
#[cfg(test)]
mod tests {
use crate::{
trace::Trace,
ui::{
component::{text::paragraphs::Paragraphs, Empty},
display,
geometry::Point,
model_tt::{event::TouchEvent, theme},
},
};
use super::*;
fn trace(val: &impl Trace) -> String {
let mut t = Vec::new();
val.trace(&mut t);
String::from_utf8(t).unwrap()
}
fn swipe(component: &mut impl Component, points: &[(i32, i32)]) {
let last = points.len().saturating_sub(1);
let mut first = true;
let mut ctx = EventCtx::new();
for (i, &(x, y)) in points.iter().enumerate() {
let p = Point::new(x, y);
let ev = if first {
TouchEvent::TouchStart(p)
} else if i == last {
TouchEvent::TouchEnd(p)
} else {
TouchEvent::TouchMove(p)
};
component.event(&mut ctx, Event::Touch(ev));
first = false;
}
}
fn swipe_up(component: &mut impl Component) {
swipe(component, &[(20, 100), (20, 60), (20, 20)])
}
fn swipe_down(component: &mut impl Component) {
swipe(component, &[(20, 20), (20, 60), (20, 100)])
}
#[test]
fn paragraphs_empty() {
let mut page = SwipePage::new(
display::screen(),
theme::BG,
|area| Paragraphs::<&[u8]>::new(area),
|_| Empty,
);
let expected =
"<SwipePage active_page:0 page_count:1 content:<Paragraphs > buttons:<Empty > >";
assert_eq!(trace(&page), expected);
swipe_up(&mut page);
assert_eq!(trace(&page), expected);
swipe_down(&mut page);
assert_eq!(trace(&page), expected);
}
#[test]
fn paragraphs_single() {
let mut page = SwipePage::new(
display::screen(),
theme::BG,
|area| {
Paragraphs::new(area)
.add::<theme::TTDefaultText>(
theme::FONT_NORMAL,
"This is the first paragraph and it should fit on the screen entirely.",
)
.add::<theme::TTDefaultText>(
theme::FONT_BOLD,
"Second, bold, paragraph should also fit on the screen whole I think.",
)
},
|_| Empty,
);
let expected = "<SwipePage active_page:0 page_count:1 content:<Paragraphs This is the first paragraph\nand it should fit on the\nscreen entirely.\nSecond, bold, paragraph\nshould also fit on the\nscreen whole I think.\n> buttons:<Empty > >";
assert_eq!(trace(&page), expected);
swipe_up(&mut page);
assert_eq!(trace(&page), expected);
swipe_down(&mut page);
assert_eq!(trace(&page), expected);
}
#[test]
fn paragraphs_one_long() {
let mut page = SwipePage::new(
display::screen(),
theme::BG,
|area| {
Paragraphs::new(area)
.add::<theme::TTDefaultText>(
theme::FONT_BOLD,
"This is somewhat long paragraph that goes on and on and on and on and on and will definitely not fit on just a single screen. You have to swipe a bit to see all the text it contains I guess. There's just so much letters in it.",
)
},
|_| Empty,
);
let expected1 = "<SwipePage active_page:0 page_count:2 content:<Paragraphs This is somewhat long\nparagraph that goes\non and on and on and\non and on and will\ndefinitely not fit on\njust a single screen.\nYou have to swipe a bit\nto see all the text it...\n> buttons:<Empty > >";
let expected2 = "<SwipePage active_page:1 page_count:2 content:<Paragraphs contains I guess.\nThere's just so much\nletters in it.\n> buttons:<Empty > >";
assert_eq!(trace(&page), expected1);
swipe_down(&mut page);
assert_eq!(trace(&page), expected1);
swipe_up(&mut page);
assert_eq!(trace(&page), expected2);
swipe_up(&mut page);
assert_eq!(trace(&page), expected2);
swipe_down(&mut page);
assert_eq!(trace(&page), expected1);
}
#[test]
fn paragraphs_three_long() {
let mut page = SwipePage::new(
display::screen(),
theme::BG,
|area| {
Paragraphs::new(area)
.add::<theme::TTDefaultText>(
theme::FONT_BOLD,
"This paragraph is using a bold font. It doesn't need to be all that long.",
)
.add::<theme::TTDefaultText>(
theme::FONT_MONO,
"And this one is using MONO. Monospace is nice for numbers, they have the same width and can be scanned quickly. Even if they span several pages or something.",
)
.add::<theme::TTDefaultText>(
theme::FONT_BOLD,
"Let's add another one for a good measure. This one should overflow all the way to the third page with a bit of luck.",
)
},
|_| Empty,
);
let expected1 = "<SwipePage active_page:0 page_count:3 content:<Paragraphs This paragraph is\nusing a bold font. It\ndoesn't need to be all\nthat long.\nAnd this one is\nusing MONO.\nMonospace is nice\nfor numbers, they...\n> buttons:<Empty > >";
let expected2 = "<SwipePage active_page:1 page_count:3 content:<Paragraphs have the same\nwidth and can be\nscanned quickly.\nEven if they span\nseveral pages or\nsomething.\nLet's add another one\nfor a good measure....\n> buttons:<Empty > >";
let expected3 = "<SwipePage active_page:2 page_count:3 content:<Paragraphs This one should\noverflow all the way to\nthe third page with a\nbit of luck.\n> buttons:<Empty > >";
assert_eq!(trace(&page), expected1);
swipe_down(&mut page);
assert_eq!(trace(&page), expected1);
swipe_up(&mut page);
assert_eq!(trace(&page), expected2);
swipe_up(&mut page);
assert_eq!(trace(&page), expected3);
swipe_up(&mut page);
assert_eq!(trace(&page), expected3);
swipe_down(&mut page);
assert_eq!(trace(&page), expected2);
swipe_down(&mut page);
assert_eq!(trace(&page), expected1);
swipe_down(&mut page);
assert_eq!(trace(&page), expected1);
}
}

@ -122,47 +122,12 @@ extern "C" fn ui_layout_new_confirm_action(
#[cfg(test)]
mod tests {
use crate::{
trace::{Trace, Tracer},
trace::Trace,
ui::model_tt::component::{Button, Dialog},
};
use super::*;
impl Tracer for Vec<u8> {
fn int(&mut self, i: i64) {
self.string(&i.to_string());
}
fn bytes(&mut self, b: &[u8]) {
self.extend(b);
}
fn string(&mut self, s: &str) {
self.extend(s.as_bytes());
}
fn symbol(&mut self, name: &str) {
self.extend(name.as_bytes());
}
fn open(&mut self, name: &str) {
self.extend(b"<");
self.extend(name.as_bytes());
self.extend(b" ");
}
fn field(&mut self, name: &str, value: &dyn Trace) {
self.extend(name.as_bytes());
self.extend(b":");
value.trace(self);
self.extend(b" ");
}
fn close(&mut self) {
self.extend(b">");
}
}
fn trace(val: &impl Trace) -> String {
let mut t = Vec::new();
val.trace(&mut t);

Loading…
Cancel
Save