187 lines
6.6 KiB
Rust
187 lines
6.6 KiB
Rust
use egui::containers::menu::{MenuBar, MenuConfig, SubMenuButton};
|
|
use egui::{PopupCloseBehavior, Ui, include_image};
|
|
use egui_kittest::{Harness, SnapshotResults};
|
|
use kittest::Queryable as _;
|
|
|
|
struct TestMenu {
|
|
config: MenuConfig,
|
|
checked: bool,
|
|
}
|
|
|
|
impl TestMenu {
|
|
fn new(config: MenuConfig) -> Self {
|
|
Self {
|
|
config,
|
|
checked: false,
|
|
}
|
|
}
|
|
|
|
fn ui(&mut self, ui: &mut Ui) {
|
|
ui.vertical(|ui| {
|
|
MenuBar::new().config(self.config.clone()).ui(ui, |ui| {
|
|
egui::Sides::new().show(
|
|
ui,
|
|
|ui| {
|
|
ui.menu_button("Menu A", |ui| {
|
|
_ = ui.button("Button in Menu A");
|
|
ui.menu_button("Submenu A", |ui| {
|
|
for i in 0..4 {
|
|
_ = ui.button(format!("Button {i} in Submenu A"));
|
|
}
|
|
});
|
|
ui.menu_image_text_button(
|
|
include_image!("../../eframe/data/icon.png"),
|
|
"Submenu B with icon",
|
|
|ui| {
|
|
_ = ui.button("Button in Submenu B");
|
|
},
|
|
);
|
|
SubMenuButton::new("Submenu C (CloseOnClickOutside)")
|
|
.config(
|
|
MenuConfig::new()
|
|
.close_behavior(PopupCloseBehavior::CloseOnClickOutside),
|
|
)
|
|
.ui(ui, |ui| {
|
|
_ = ui.button("Button in Submenu C");
|
|
ui.checkbox(&mut self.checked, "Checkbox in Submenu C");
|
|
ui.menu_button("Submenu D", |ui| {
|
|
if ui
|
|
.button("Button in Submenu D (close on click)")
|
|
.clicked()
|
|
{
|
|
ui.close();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
ui.menu_image_text_button(
|
|
include_image!("../../eframe/data/icon.png"),
|
|
"Menu B with icon",
|
|
|ui| {
|
|
_ = ui.button("Button in Menu B");
|
|
},
|
|
);
|
|
_ = ui.button("Menu Button");
|
|
ui.menu_button("Menu C", |ui| {
|
|
_ = ui.button("Button in Menu C");
|
|
});
|
|
},
|
|
|ui| {
|
|
ui.label("Some other label");
|
|
},
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn into_harness(self) -> Harness<'static, Self> {
|
|
Harness::builder()
|
|
.with_size(egui::Vec2::new(500.0, 300.0))
|
|
.build_ui_state(
|
|
|ui, menu| {
|
|
egui_extras::install_image_loaders(ui.ctx());
|
|
menu.ui(ui);
|
|
},
|
|
self,
|
|
)
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn menu_close_on_click_outside() {
|
|
// We're intentionally setting CloseOnClick here so we can test if a submenu can override the
|
|
// close behavior. (Note how Submenu C has CloseOnClickOutside set)
|
|
let mut harness =
|
|
TestMenu::new(MenuConfig::new().close_behavior(PopupCloseBehavior::CloseOnClick))
|
|
.into_harness();
|
|
|
|
harness.get_by_label("Menu A").click();
|
|
harness.run();
|
|
|
|
harness
|
|
.get_by_label_contains("Submenu C (CloseOnClickOutside)")
|
|
.hover();
|
|
harness.run();
|
|
|
|
// We should be able to check the checkbox without closing the menu
|
|
// Click a couple of times, just in case
|
|
for expect_checked in [true, false, true, false] {
|
|
harness.get_by_label("Checkbox in Submenu C").click();
|
|
harness.run();
|
|
assert_eq!(expect_checked, harness.state().checked);
|
|
}
|
|
|
|
// Hovering outside should not close the menu
|
|
harness.get_by_label("Some other label").hover();
|
|
harness.run();
|
|
assert!(harness.query_by_label("Checkbox in Submenu C").is_some());
|
|
|
|
// Clicking outside should close the menu
|
|
harness.get_by_label("Some other label").click();
|
|
harness.run();
|
|
assert!(harness.query_by_label("Checkbox in Submenu C").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn menu_close_on_click() {
|
|
let mut harness =
|
|
TestMenu::new(MenuConfig::new().close_behavior(PopupCloseBehavior::CloseOnClick))
|
|
.into_harness();
|
|
|
|
harness.get_by_label("Menu A").click();
|
|
harness.run();
|
|
|
|
harness.get_by_label_contains("Submenu B with icon").hover();
|
|
harness.run();
|
|
|
|
// Clicking the button should close the menu (even if ui.close() is not called by the button)
|
|
harness.get_by_label("Button in Submenu B").click();
|
|
harness.run();
|
|
assert!(harness.query_by_label("Button in Submenu B").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn clicking_submenu_button_should_never_close_menu() {
|
|
// We test for this since otherwise the menu wouldn't work on touch devices
|
|
// The other tests use .hover to open submenus, but this test explicitly uses .click
|
|
let mut harness =
|
|
TestMenu::new(MenuConfig::new().close_behavior(PopupCloseBehavior::CloseOnClick))
|
|
.into_harness();
|
|
|
|
harness.get_by_label("Menu A").click();
|
|
harness.run();
|
|
|
|
// Clicking the submenu button should not close the menu
|
|
harness.get_by_label_contains("Submenu B with icon").click();
|
|
harness.run();
|
|
|
|
harness.get_by_label("Button in Submenu B").click();
|
|
harness.run();
|
|
assert!(harness.query_by_label("Button in Submenu B").is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn menu_snapshots() {
|
|
let mut harness = TestMenu::new(MenuConfig::new()).into_harness();
|
|
|
|
let mut results = SnapshotResults::new();
|
|
|
|
harness.get_by_label("Menu A").hover();
|
|
harness.run();
|
|
results.add(harness.try_snapshot("menu/closed_hovered"));
|
|
|
|
harness.get_by_label("Menu A").click();
|
|
harness.run();
|
|
results.add(harness.try_snapshot("menu/opened"));
|
|
|
|
harness
|
|
.get_by_label_contains("Submenu C (CloseOnClickOutside)")
|
|
.hover();
|
|
harness.run();
|
|
results.add(harness.try_snapshot("menu/submenu"));
|
|
|
|
harness.get_by_label_contains("Submenu D").hover();
|
|
harness.run();
|
|
results.add(harness.try_snapshot("menu/subsubmenu"));
|
|
}
|