mirror of
https://github.com/lahfir/agent-desktop.git
synced 2026-08-04 05:07:04 +00:00
fix: classify benign AX absence codes as complete action reads
The live e2e gate exposed that find could never address the fixture's zero-bounds synthetic element: AppKit answers kAXErrorFailure for accessibilityActionNames on NSAccessibilityElements with no action support and kAXErrorAttributeUnsupported for unimplemented settable probes, and the action reader classified both as incomplete transport reads, so selected-anchor hydration retried to TIMEOUT with locator_selected_evidence_incomplete. Mirror the renderer-probe absence classification for action reads: unsupported/no-value/ not-implemented/action-unsupported/failure are complete none-present answers; CannotComplete, InvalidUIElement, and APIDisabled still mark the read incomplete.
This commit is contained in:
parent
ec8501d4ca
commit
a65d4530a1
1 changed files with 52 additions and 0 deletions
|
|
@ -116,12 +116,32 @@ fn read_settable(
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn record_error(read: &mut AvailableActionsRead, error: i32) {
|
||||
if is_definitive_absence(error) {
|
||||
return;
|
||||
}
|
||||
read.complete = false;
|
||||
read.cannot_complete |= error == accessibility_sys::kAXErrorCannotComplete;
|
||||
read.invalid_element |= error == accessibility_sys::kAXErrorInvalidUIElement;
|
||||
read.api_disabled |= error == accessibility_sys::kAXErrorAPIDisabled;
|
||||
}
|
||||
|
||||
/// AppKit's NSAccessibility bridge answers these codes when an element simply
|
||||
/// does not implement the probed attribute or action list — including
|
||||
/// `kAXErrorFailure`, which it returns for synthetic `NSAccessibilityElement`s
|
||||
/// with no action support. They are complete "none present" answers, not
|
||||
/// transport failures, so they must not mark the read incomplete.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn is_definitive_absence(error: i32) -> bool {
|
||||
matches!(
|
||||
error,
|
||||
accessibility_sys::kAXErrorAttributeUnsupported
|
||||
| accessibility_sys::kAXErrorNoValue
|
||||
| accessibility_sys::kAXErrorNotImplemented
|
||||
| accessibility_sys::kAXErrorActionUnsupported
|
||||
| accessibility_sys::kAXErrorFailure
|
||||
)
|
||||
}
|
||||
|
||||
fn role_may_bear_value(role: &str) -> bool {
|
||||
matches!(
|
||||
role,
|
||||
|
|
@ -265,4 +285,36 @@ mod tests {
|
|||
assert!(read.cannot_complete);
|
||||
assert!(read.actions.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn definitive_absence_codes_are_complete_empty_answers() {
|
||||
for error in [
|
||||
accessibility_sys::kAXErrorAttributeUnsupported,
|
||||
accessibility_sys::kAXErrorNoValue,
|
||||
accessibility_sys::kAXErrorNotImplemented,
|
||||
accessibility_sys::kAXErrorActionUnsupported,
|
||||
accessibility_sys::kAXErrorFailure,
|
||||
] {
|
||||
let mut read = AvailableActionsRead::default();
|
||||
record_error(&mut read, error);
|
||||
assert!(read.complete, "code {error} must stay complete");
|
||||
assert!(!read.cannot_complete);
|
||||
assert!(read.actions.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn transport_failures_are_never_classified_as_absence() {
|
||||
for error in [
|
||||
accessibility_sys::kAXErrorCannotComplete,
|
||||
accessibility_sys::kAXErrorInvalidUIElement,
|
||||
accessibility_sys::kAXErrorAPIDisabled,
|
||||
] {
|
||||
let mut read = AvailableActionsRead::default();
|
||||
record_error(&mut read, error);
|
||||
assert!(!read.complete, "code {error} must mark the read incomplete");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue