//! Protect Sheet / Unprotect Sheet mask the password as it's typed (issue #347). use egui::accesskit::Role; use egui_kittest::kittest::Queryable as _; use gridcraft_engine::Session; use gridcraft_ui_egui::SheetApp; use serde_json::json; const SECRET: &str = "s3cret"; fn harness() -> egui_kittest::Harness<'static, SheetApp> { let mut session = Session::new(); session.new_workbook(); let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state( |ui, app: &mut SheetApp| { let ctx = ui.ctx().clone(); app.logic(&ctx); app.ui(ui); }, SheetApp::new(session, Default::default()), ); h.run_steps(4); h } fn type_password(h: &mut egui_kittest::Harness<'static, SheetApp>) { h.get_by_role(Role::PasswordInput).click(); h.run_steps(2); h.input_mut().events.push(egui::Event::Text(SECRET.into())); h.run_steps(2); } fn secret_on_screen(h: &egui_kittest::Harness<'static, SheetApp>) -> bool { h.query_all_by(|n| n.value().is_some_and(|v| v.contains(SECRET)) || n.label().is_some_and(|l| l.contains(SECRET))).next().is_some() } #[test] fn protect_and_unprotect_sheet_mask_the_password() { let mut h = harness(); h.state_mut().open_dialog("protectSheet", json!({})); h.run_steps(3); type_password(&mut h); assert_eq!(h.state().dialog.as_ref().and_then(|d| d.values.get("password")), Some(&json!(SECRET))); assert!(!secret_on_screen(&h), "the typed password must not be readable"); assert!(h.get_by_role(Role::PasswordInput).value().is_some_and(|v| !v.is_empty() && !v.contains(SECRET))); // Show password reveals it on purpose; unticking masks it again. h.get_by_label("Show password").click(); h.run_steps(3); assert!(h.query_by_role(Role::PasswordInput).is_none()); assert!(secret_on_screen(&h)); h.get_by_label("Show password").click(); h.run_steps(3); assert!(h.query_by_role(Role::PasswordInput).is_some()); assert!(!secret_on_screen(&h)); h.get_by_label(" OK ").click(); h.run_steps(3); assert!(h.state().dialog.is_none()); assert!(h.state().session.active().unwrap().wb.active().unwrap().protection.as_ref().is_some_and(|p| p.password.is_some())); // Unprotect asks for the password with a masked field too, and it starts hidden again. h.state_mut().open_dialog("unprotectSheet", json!({})); h.run_steps(3); type_password(&mut h); assert!(!secret_on_screen(&h), "the typed password must not be readable"); h.get_by_label(" OK ").click(); h.run_steps(3); assert!(h.state().session.active().unwrap().wb.active().unwrap().protection.is_none()); }