// UI contract for the Recover Upstream audio controls. // // Scope: source-level assertions around the launcher recovery rail and button // actions. This avoids opening a real GTK session while still protecting copy, // labels, tooltips, and RPC routing. // Targets: `client/src/launcher/ui_components/build_operations_rail.rs` and // `client/src/launcher/ui/utility_button_bindings.rs`. // Why: operators need the button that fixed the stale Google Meet epoch to say // exactly what it does, and it must not be confused with USB or video recovery. const OPERATIONS_RAIL_SRC: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/client/src/launcher/ui_components/build_operations_rail.rs" )); const UTILITY_BINDINGS_SRC: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/client/src/launcher/ui/utility_button_bindings.rs" )); #[test] fn recover_audio_button_is_labeled_as_audio_under_recover_upstream() { for marker in [ "let recovery_heading = gtk::Label::new(Some(\"Recover\\nUpstream\"));", "let uac_recover_button = rail_button(", "\"Audio\",", "retire the stale upstream audio epoch", "bundled mic+camera reconnect without resetting USB or changing calibration", ] { assert!( OPERATIONS_RAIL_SRC.contains(marker), "Recover Audio UI should preserve marker {marker}" ); } assert!( !OPERATIONS_RAIL_SRC.contains("\"Heal A/V\""), "the old label implied video/calibration mutation and should stay retired" ); } #[test] fn recover_audio_click_routes_to_uac_only_and_explains_side_effects() { let audio_start = UTILITY_BINDINGS_SRC .find("widgets.uac_recover_button.connect_clicked") .expect("audio recovery binding should exist"); let video_start = UTILITY_BINDINGS_SRC .find("widgets.uvc_recover_button.connect_clicked") .expect("video recovery binding should follow audio recovery"); let audio_block = &UTILITY_BINDINGS_SRC[audio_start..video_start]; for marker in [ "Recover Audio 1/3: retiring the stale upstream audio epoch cleanly", "recover_uac_soft(&server_addr)", "Recover Audio 2/3: old epoch released", "bundled media will reconnect without resetting USB or calibration", ] { assert!( audio_block.contains(marker), "Recover Audio action should preserve marker {marker}" ); } assert!(!audio_block.contains("recover_usb_soft")); assert!(!audio_block.contains("recover_uvc_soft")); assert!(!audio_block.contains("reset_usb")); }