use super::{elbow, empty, prose, rail, row, ruled, section};
use crate::paint_probe::frame::Window;
use crate::test_support::window::{click, seen};
use crate::ui::theme::{BRAND, INK, INK_WEAK, RAISED, RULE, State, accent, type_scale};
mod field;
mod hover;
mod knob;
fn fills(window: &Window, body: impl FnMut(&egui::Context)) -> Vec<(egui::Rect, egui::Color32)> {
crate::paint_probe::fills_of(&window.frame(Vec::new(), body))
}
#[test]
fn a_row_paints_its_words_in_its_ink_and_its_state_as_a_rule() {
let window = Window::sized(200.0, 100.0);
let body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| {
row(
ui,
"a conversation whose name is far too long for two hundred points",
INK_WEAK,
Some(accent(State::Attention)),
false,
0.0,
"a row",
);
});
};
let glyphs = seen(&window, body);
let run = glyphs.first().expect("the words reached the glass");
assert!(run.text.ends_with('…'), "elided: {:?}", run.text);
assert_eq!(run.ink, INK_WEAK);
let rule = fills(&window, body)
.into_iter()
.find(|(rect, ink)| *ink == accent(State::Attention) && rect.width() <= RULE + 0.5);
assert!(rule.is_some(), "the attention rule stands at the edge");
}
#[test]
fn a_chosen_row_is_raised_and_wears_the_brand() {
let window = Window::sized(300.0, 100.0);
let body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| {
row(
ui,
"chosen",
INK,
Some(accent(State::Error)),
true,
0.0,
"chosen",
);
});
};
let fills = fills(&window, body);
assert!(fills.iter().any(|(_, ink)| *ink == RAISED), "raised");
assert!(fills.iter().any(|(_, ink)| *ink == BRAND), "the brand rule");
assert!(
!fills.iter().any(|(_, ink)| *ink == accent(State::Error)),
"and not the state's"
);
}
#[test]
fn a_row_rings_while_it_holds_the_keyboard_and_not_otherwise() {
let window = Window::sized(300.0, 100.0);
let mut body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| {
row(ui, "first", INK, None, false, 0.0, "first");
row(ui, "second", INK, None, false, 0.0, "second");
});
};
let ringed = |output: &egui::FullOutput| {
crate::paint_probe::strokes_of(output)
.into_iter()
.filter(|(_, ink)| *ink == BRAND)
.count()
};
assert_eq!(ringed(&window.frame(Vec::new(), &mut body)), 0, "at rest");
window.frame(
vec![crate::paint_probe::frame::press(egui::Key::Tab)],
&mut body,
);
let output = window.frame(Vec::new(), &mut body);
assert_eq!(ringed(&output), 1, "one row holds the keyboard");
let ring = crate::paint_probe::strokes_of(&output)
.into_iter()
.find(|(_, ink)| *ink == BRAND)
.map(|(rect, _)| rect)
.expect("the ring");
let first = seen(&window, &mut body)
.into_iter()
.find(|run| run.text == "first")
.expect("the first row");
assert!(
ring.contains_rect(first.laid),
"the ring is around the first row"
);
}
#[test]
fn a_row_takes_a_click_on_its_words() {
let window = Window::sized(300.0, 100.0);
let mut clicked = false;
click(&window, "take me", |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
clicked |= row(ui, "take me", INK, None, false, 0.0, "takes").clicked();
});
});
assert!(clicked);
}
#[test]
fn a_block_is_ruled_and_a_section_is_worded() {
let window = Window::sized(300.0, 300.0);
let body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| {
ruled(ui, BRAND, |ui| {
ui.label("first line");
ui.label("second line");
});
section(ui, "steps");
rail(ui, 4.0, 0.0, 10.0);
elbow(ui, 4.0, 0.0, 5.0, 12.0);
});
};
let glyphs = seen(&window, body);
let first = glyphs
.iter()
.find(|run| run.text == "first line")
.expect("first");
let second = glyphs
.iter()
.find(|run| run.text == "second line")
.expect("second");
let rule = fills(&window, body)
.into_iter()
.find(|(rect, ink)| *ink == BRAND && rect.width() <= RULE + 0.5)
.expect("the rule is on the glass");
assert!(rule.0.min.y <= first.laid.min.y + 1.0 && rule.0.max.y >= second.laid.max.y - 1.0);
let word = glyphs
.iter()
.find(|run| run.text == "steps")
.expect("the section's word");
assert_eq!(word.ink, INK_WEAK);
}
#[test]
fn prose_is_laid_at_the_leading_and_a_label_is_not() {
let window = Window::sized(200.0, 200.0);
let words = "a paragraph long enough that two hundred points cannot hold it on one line";
let body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| {
prose(ui, words, INK_WEAK);
ui.label(words);
});
};
let glyphs = seen(&window, body);
let (paragraph, label) = (&glyphs[0], &glyphs[1]);
assert_eq!(paragraph.ink, INK_WEAK);
assert!(
paragraph.laid.height() >= 2.0 * type_scale::LEADING - 1.0,
"{:?}",
paragraph.laid
);
assert!(
paragraph.laid.height() > label.laid.height() + type_scale::LEADING - type_scale::BODY,
"prose {:?} over label {:?}",
paragraph.laid,
label.laid
);
}
#[test]
fn an_empty_state_is_one_weak_sentence_that_wraps() {
let window = Window::sized(160.0, 200.0);
let sentence = "no conversations here yet — begin one in the box below";
let glyphs = seen(&window, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
empty(ui, sentence);
});
});
let run = glyphs.first().expect("the sentence reached the glass");
assert_eq!(run.ink, INK_WEAK);
assert!(run.laid.height() > 1.5 * type_scale::BODY, "{:?}", run.laid);
assert!(run.laid.max.x <= 160.0, "{:?}", run.laid);
}
#[test]
fn a_row_past_the_clip_paints_nothing() {
let window = Window::sized(300.0, 60.0);
let runs = seen(&window, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
for i in 0..30 {
row(ui, &format!("row {i}"), INK, None, false, 0.0, "a row");
}
});
});
});
assert!(runs.iter().any(|run| run.text == "row 0"), "{runs:?}");
assert!(!runs.iter().any(|run| run.text == "row 29"), "{runs:?}");
}