pub(super) mod lex;
mod live;
pub(super) mod scan;
mod spelling;
use super::super::render;
use crate::cli_outbound::Cli;
use lex::skeleton;
use scan::{chain_of, rust_files, sites};
use std::path::Path;
pub(super) const CONTROLS: &[&str] = &[
"ui.button(",
"ui.small_button(",
"ui.checkbox(",
"ui.selectable_label(",
"ui.selectable_value(",
"ui.radio_value(",
"ui.toggle_value(",
"ui.menu_button(",
"ui.text_edit_singleline(",
"ui.text_edit_multiline(",
"ui.collapsing(",
"ui.add(",
"ui.add_enabled(",
"ui.add_sized(",
"ComboBox::from_id_salt(",
"ComboBox::from_label(",
"CollapsingHeader::new(",
];
pub(super) const HOVERS: &[&str] = &["on_hover_text", "on_disabled_hover_text"];
#[test]
fn every_interactive_control_carries_a_hover() {
let mut mute = Vec::new();
let mut seen = 0usize;
for file in rust_files(&Path::new(env!("CARGO_MANIFEST_DIR")).join("src")) {
let source = std::fs::read_to_string(&file).unwrap();
let skeleton = skeleton(&source);
for hover in HOVERS {
assert!(
!skeleton.contains(&format!("{hover}(\"\")")),
"{}: an empty hover string says nothing",
file.display()
);
}
for (at, control) in sites(&skeleton, CONTROLS) {
seen += 1;
if !chain_of(&skeleton, at)
.iter()
.any(|(m, _)| HOVERS.contains(&m.as_str()))
{
mute.push(format!("{}: {control}", file.display()));
}
}
}
assert!(
seen > 50,
"the scan matched {seen} controls — the pattern list has rotted"
);
assert!(
mute.is_empty(),
"these controls say nothing on hover — §11 requires every one of them to \
state what pressing it does:\n{}",
mute.join("\n")
);
}
#[test]
fn the_hovers_reach_the_paint_layer() {
let (lernie, bl, bz) = (Cli::new("lernie"), Cli::new("bl"), Cli::new("bz"));
let mut world = super::fixture::world();
let ws = world.ws.clone();
world.model.focus_agent(&ws, "c-1");
world.state.activity_open = true;
world.state.actions.drafts.set(
crate::actions::DraftKey::Message("c-1".to_owned()),
"hello".to_owned(),
);
world.model.select_tab(crate::keymap::InspectorTab::Inbox);
let ctx = egui::Context::default();
ctx.memory_mut(|m| m.set_everything_is_visible(true));
let frame = |world: &mut super::fixture::World| {
let out = ctx.run(super::input(), |ctx| {
render(ctx, &mut world.model, &mut world.state, &lernie, &bl, &bz);
});
crate::paint_probe::text_of(&out)
};
frame(&mut world);
world.settle();
frame(&mut world);
world.settle();
frame(&mut world);
world.settle();
let painted = frame(&mut world);
for phrase in [
"writes a died epitaph for every driver",
"there is no driver to kill",
"Deposit this text in the selected conversation's inbox",
"open this conversation",
"Every setting yog can write",
"Workspaces that are real but not regimes",
"Escape from any other tab comes back here",
"Sign in to a model provider",
"What was said: one line per delivered message",
"Show the files behind this tab exactly as they are on disk",
"Open the ops trail",
] {
assert!(
painted.contains(phrase),
"no control painted the hover {phrase:?}:\n{painted}"
);
}
}