1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00
Files
egui/crates/egui_kittest/tests/popup.rs
2026-08-25 13:30:25 +02:00

231 lines
7.4 KiB
Rust

use egui::{Align, Layout, Popup};
use egui_kittest::Harness;
use kittest::Queryable as _;
#[test]
fn reopened_popup_resizes_for_wider_items() {
const POPUP_BUTTON: &str = "Dynamic popup";
const SHORT_ITEM: &str = "Short item";
const WIDE_ITEM: &str = "Newly added item with a much wider label";
#[derive(Default)]
struct State {
open: bool,
show_wide_item: bool,
}
let mut harness = Harness::builder()
.with_size(egui::Vec2::new(500.0, 300.0))
.build_ui_state(
|ui, state| {
let response = ui.button(POPUP_BUTTON);
if response.clicked() {
state.open = !state.open;
}
Popup::from_response(&response)
.open(state.open)
.layout(Layout::top_down_justified(Align::Min))
.show(|ui| {
_ = ui.selectable_label(false, SHORT_ITEM);
_ = ui.selectable_label(false, "Another short item");
if state.show_wide_item {
_ = ui.selectable_label(false, WIDE_ITEM);
}
});
},
State::default(),
);
harness.get_by_label(POPUP_BUTTON).click();
harness.run();
let initial_row_size = harness.get_by_label(SHORT_ITEM).rect().size();
harness.get_by_label(POPUP_BUTTON).click();
harness.run();
assert!(harness.query_by_label(SHORT_ITEM).is_none());
harness.state_mut().show_wide_item = true;
harness.run();
harness.get_by_label(POPUP_BUTTON).click();
harness.run();
let reopened_row_size = harness.get_by_label(SHORT_ITEM).rect().size();
let wide_row_size = harness.get_by_label(WIDE_ITEM).rect().size();
assert!(
reopened_row_size.x > initial_row_size.x,
"reopened row width ({}) did not grow beyond its initial width ({})",
reopened_row_size.x,
initial_row_size.x
);
assert!(
wide_row_size.y <= initial_row_size.y + 0.5,
"new row height ({}) exceeds the single-line row height ({})",
wide_row_size.y,
initial_row_size.y
);
}
#[test]
fn open_popup_resizes_after_explicit_sizing_pass() {
const POPUP_BUTTON: &str = "Growing popup";
const MAX_HEIGHT: f32 = 100.0;
struct State {
item_count: usize,
needs_sizing_pass: bool,
popup_height: f32,
viewport_height: f32,
content_height: f32,
}
let mut harness = Harness::builder()
.with_size(egui::Vec2::new(500.0, 300.0))
.build_ui_state(
|ui, state| {
let response = ui.button(POPUP_BUTTON);
let needs_sizing_pass = core::mem::take(&mut state.needs_sizing_pass);
let item_count = state.item_count;
if let Some(popup) = Popup::from_response(&response)
.sizing_pass(needs_sizing_pass)
.show(|ui| {
egui::ScrollArea::vertical()
.max_height(MAX_HEIGHT)
.show(ui, |ui| {
for index in 0..item_count {
ui.label(format!("Item {index}"));
}
})
})
{
state.popup_height = popup.response.rect.height();
state.viewport_height = popup.inner.inner_rect.height();
state.content_height = popup.inner.content_size.y;
}
},
State {
item_count: 2,
needs_sizing_pass: false,
popup_height: 0.0,
viewport_height: 0.0,
content_height: 0.0,
},
);
harness.run();
let initial_popup_height = harness.state().popup_height;
harness.state_mut().item_count = 20;
harness.run();
let stale_viewport_height = harness.state().viewport_height;
assert!(
stale_viewport_height < MAX_HEIGHT,
"viewport unexpectedly reached its maximum without a sizing pass"
);
harness.state_mut().needs_sizing_pass = true;
harness.run();
assert!(
harness.state().popup_height > initial_popup_height,
"popup did not grow after an explicit sizing pass"
);
assert!(
harness.state().viewport_height > stale_viewport_height,
"scroll viewport did not grow after an explicit sizing pass"
);
assert!(
(harness.state().viewport_height - MAX_HEIGHT).abs() <= 0.5,
"scroll viewport did not stop at its maximum height"
);
assert!(
harness.state().content_height > harness.state().viewport_height,
"popup contents did not remain scrollable at the maximum height"
);
}
#[test]
fn test_interactive_tooltip() {
struct State {
link_clicked: bool,
}
let mut harness = egui_kittest::Harness::new_ui_state(
|ui, state| {
ui.label("I have a tooltip").on_hover_ui(|ui| {
if ui.link("link").clicked() {
state.link_clicked = true;
}
});
},
State {
link_clicked: false,
},
);
harness.get_by_label_contains("tooltip").hover();
harness.run();
harness.get_by_label("link").hover();
harness.run();
harness.get_by_label("link").click();
harness.run();
assert!(harness.state().link_clicked);
}
#[cfg(all(feature = "snapshot", feature = "wgpu"))]
#[test]
fn scroll_area_extends_into_popup_margin() {
fn scroll_area(ui: &mut egui::Ui, extend: bool) {
egui::ScrollArea::vertical()
.max_height(110.0)
.auto_shrink([false, true])
.extend_into_parent_margin(extend)
.show(ui, |ui| {
for i in 0..20 {
_ = ui.selectable_label(i == 2, format!("Item {i}"));
}
});
}
fn popup_with_scroll_area(ui: &mut egui::Ui, label: &str, extend: bool, nested: bool) {
let response = ui.button(label);
Popup::from_response(&response).open(true).show(|ui| {
ui.set_width(120.0);
if nested {
// The scroll area is not a direct child of the popup frame here,
// so we must find the frame by walking up the `UiStack`:
ui.vertical(|ui| {
ui.label("Header");
scroll_area(ui, extend);
});
} else {
ui.label("Header");
scroll_area(ui, extend);
}
});
}
let mut harness = Harness::builder()
.with_size(egui::Vec2::new(600.0, 220.0))
.with_pixels_per_point(2.0)
.build_ui(|ui| {
// Solid scroll bars make it easy to see where the scroll area ends:
ui.ctx()
.all_styles_mut(|style| style.spacing.scroll = egui::style::ScrollStyle::solid());
ui.horizontal(|ui| {
popup_with_scroll_area(ui, "normal", false, false);
ui.add_space(140.0);
popup_with_scroll_area(ui, "full bleed", true, false);
ui.add_space(140.0);
popup_with_scroll_area(ui, "full bleed, nested", true, true);
});
});
harness.run();
harness.snapshot("popup_full_bleed_scroll_area");
}