Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

iOS: resolveRunnerWindow fails when an unused trailing window disappears

Aperta Adatta ai principianti
#2,995 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
84/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
ios, swift
Ambito
mobile, testing-qa

Direzione di ricerca

Inizia in apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift, in resolveRunnerWindow(app:), quindi esegui la riproduzione nativa collegata con ./reproduce.sh . Il lavoro è completato quando il resolver restituisce la prima finestra utilizzabile e non vuota senza leggere finestre successive non necessarie, mantiene il fallback app.frame e la riproduzione passa senza l’errore stale-element.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Bug

resolveRunnerWindow(app:) eagerly reads the frame of every app window before returning the first usable one. If an unused trailing window disappears between its exists check and its frame read, XCTest records a failure even though the first/main window is still available.

Affected implementation: Agent Device 0.21.15; also still present in upstream source at 3660c7fa.

Small native reproduction

Public repo: https://github.com/wcastand/agent-device-window-race-repro
Verified commit: b1baf97

The fixture is a small UIKit app with a persistent main UIWindow. It shows a second window every 5 seconds, then hides/releases it after 600 ms. Two XCUITests repeatedly call the extracted original resolver or the proposed short-circuit version using real XCUIApplication/XCUIElement objects. No Expo/React Native, backend, account, mocked failures, or hooks/delays inside the resolver are involved.

git clone https://github.com/wcastand/agent-device-window-race-repro.git
cd agent-device-window-race-repro
./reproduce.sh <iOS-simulator-UDID>

The Xcode project is included; no package install or signing team is needed. Each loop is bounded to 60 seconds / 6,000 calls. This is a natural timing race, so a run can miss it. The script returns success only if the original produces the specific stale-element failure and the patched test passes; setup errors and missed races are rejected.

Observed vs expected

On Xcode 27.0 (27A266a), macOS 27.0 arm64, iPhone 18 Pro simulator / iOS 27.0, the script exited 0:

  • Original: failed on call 332 (zero-based iteration 331).
  • Patched: completed 3,843 calls over one minute, no failures.
  • The original failure was also observed separately on iPhone 17 / iOS 26.5.

Sanitized native test output:

Checking existence of `Window (Element at index 1)`
Find the Window (Element at index 1)
Find the Window (Element at index 1) (retry 1)
Find the Window (Element at index 1) (retry 2)
Failed to get matching snapshot: No matches found for Element at index 1 from input {(
    Window (Main)
)}

Expected: return the first usable window without resolving later windows that cannot affect the result. The repro isolates the native resolver; it does not run the full CLI/daemon or reproduce a keyboard-specific lifecycle.

Proposed patch

Downloadable patch, checked against the upstream source path:

--- a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift
+++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift
@@ -226,12 +226,13 @@
   /// display can never name a different window than the one the reference frame was measured on.
   func resolveRunnerWindow(app: XCUIApplication) -> (window: XCUIElement?, frame: CGRect) {
     let windows = app.windows.allElementsBoundByIndex
-    var frames: [CGRect?] = []
-    for window in windows {
-      frames.append(window.exists ? window.frame : nil)
-    }
-    if let index = Self.firstUsableWindowIndex(frames: frames) {
-      return (windows[index], frames[index] ?? .zero)
+    // Stop at the first usable window. Later keyboard/overlay windows can disappear
+    // between exists and frame, recording an XCTest failure before a valid tap.
+    for window in windows where window.exists {
+      let frame = window.frame
+      if !frame.isEmpty {
+        return (window, frame)
+      }
     }
     return (nil, app.frame)
   }

This preserves first-non-empty-window selection and the app.frame fallback. It avoids unnecessary trailing-window reads; it does not make exists + frame atomic or claim to fix disappearance of the selected window.

Lingua principale
TypeScript
Stelle
4.7k
Fork
304
Merge medio
11h 31m
PR unite (30g)
513

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di callstack/agent-device

Tutte le issue di callstack/agent-device

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.