open-standards/aac/aac-rs/crates/aac-web/tests/scene_finder.rs
Transaction Science 813ed5b21d feat(aac-web): the way to a word on a visual scene — drawn on the hotspot's own shape, its press recorded by how it was made, a switch's pass starting at it
SPEC §14 draws the way on places, a scene's hotspot among them. A
hotspot is a cell of the scene's board (aac-core scene), so the finder
already found it and the way pressed it; what it lacked:
- scene_board.rs: the way's next press is outlined in the hotspot's own
  shape (.scene-path: its polygon or rectangle), a dashed purple line on
  a light halo (on dark, high-contrast and yellow-on-black, a lighter
  purple on a dark halo), under the scan's outline and wider than it, so
  both show; the button carries path-next as a grid cell does, with no
  box drawn; a hidden hotspot the way ends at is outlined too.
- A tap, mouse or key on a hotspot is recorded with how it was made
  (usage::with_via(click_via)), as on a grid's cell.
- finder::scan_place maps the mark into the scene's own scan rows
  (scenes::scan_place), so a pass can start at the hotspot to press.
- other_places stays empty and says why: listing hotspots there too would
  list each twice.
Tests: aac-core (a scene's hotspot is its board's cell), aac-web finder
(found from Home through the link, at once on the scene, a message's word,
its scan place in the scene's rows), and an integration test through the
public finder (an outlined hotspot).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 13:20:25 -04:00

28 lines
1.7 KiB
Rust

//! Finding a word on a visual scene through the app's public finder: the
//! hotspot is found with its words, the way presses it, and a message's word
//! on the scene is its hotspot (aac-web finder.rs, aac-core scene.rs).
use aac_core::finder::{Finder, Place, Reach, Step};
use aac_core::{scene, BoardType, CellAction, CellContent, GridLayout};
use aac_web::finder::{message_items, spots_in};
#[test]
fn the_way_to_a_word_on_a_scene_presses_its_hotspot() {
let mut home = aac_core::Board::new("Home", BoardType::Grid, GridLayout::new(2, 2));
let mut park = scene::new_scene("Park", "data:image/png;base64,AAAA", 1200, 800, &scene::starter_words(Some(home.id)));
let swing = scene::place_hotspot(
&mut park,
&scene::Hotspot::from_outline(&[(0.1, 0.2), (0.3, 0.2), (0.35, 0.6), (0.05, 0.6)]).unwrap(),
scene::hotspot_cell("swing", CellAction::Speak("swing".into())),
)
.unwrap();
home.add_cell(0, 0, CellContent::Text("Park".into()), CellAction::Navigate(park.id));
let (home_id, park_id) = (home.id, park.id);
let boards: std::collections::HashMap<_, _> = [(home_id, home), (park_id, park)].into_iter().collect();
let finder = Finder::new(spots_in(&boards, "en-US"));
let found = finder.find("swing", &[home_id], Reach::default());
let way = found[0].way.as_ref().expect("a way from Home");
assert_eq!(way.len(), 2);
assert!(matches!(&way.presses[1].what, Step::Place(Place::Cell { id, .. }) if *id == swing));
let items = message_items(&finder, &[("swing".to_string(), None)], &[home_id, park_id], Reach::default(), |_| false, None);
assert!(matches!(items[0].target.as_ref().map(|t| &t.place), Some(Place::Cell { id, .. }) if *id == swing));
}