fix: address the Maps search box by id, and re-prove Phase 5
The Maps omnibox hint rotates: it read "Search here" in the Phase 5 run and "Try petrol stations, ATMs" in the AUD-128 re-verification, so the recipe's text match on it failed. The resource id does not rotate. - internal/ui: add Find/FindID and the "id:" selector; Find dispatches an id: selector to the resource id and everything else to text as before. - internal/recipe: wait/tap/wait_gone/tap_if and the tap helper use Find, so a recipe may name a resource id. Guards stay text-only. - recipes/maps_navigate.recipe: wait/tap id:search_omnibox_text_box. - tests for the id selector; docs and README updated. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -129,7 +129,8 @@ func pickBestMatch(matches []*Node) (*Node, error) {
|
||||
}
|
||||
|
||||
// TapText finds an element by its text (or content description) and taps its
|
||||
// centre. This is FR-4: text match first, coordinates derived from bounds.
|
||||
// centre. This is FR-4: a named match first, coordinates derived from bounds.
|
||||
// A selector may also name a resource id with the "id:" prefix.
|
||||
//
|
||||
// It fails loudly when no element matches and never falls back to tapping a
|
||||
// guessed coordinate.
|
||||
@@ -141,9 +142,9 @@ func TapText(r *adb.Runner, query string, exact bool) (*Node, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
matches := h.FindText(query, exact)
|
||||
matches := h.Find(query, exact)
|
||||
if len(matches) == 0 {
|
||||
return nil, fmt.Errorf("element with text %q not found on screen; refusing to tap blindly", query)
|
||||
return nil, fmt.Errorf("element matching %q not found on screen; refusing to tap blindly", query)
|
||||
}
|
||||
return TapNode(r, matches)
|
||||
}
|
||||
@@ -172,7 +173,8 @@ func TapNode(r *adb.Runner, matches []*Node) (*Node, error) {
|
||||
|
||||
// WaitForText polls the screen until an element matching query appears, then
|
||||
// returns the best tappable match. Use it after an action that loads a new
|
||||
// screen; apps do not draw instantly.
|
||||
// screen; apps do not draw instantly. A selector may name a resource id with
|
||||
// the "id:" prefix.
|
||||
func WaitForText(r *adb.Runner, query string, exact bool, timeout time.Duration) (*Node, error) {
|
||||
if timeout <= 0 {
|
||||
timeout = 10 * time.Second
|
||||
@@ -182,7 +184,7 @@ func WaitForText(r *adb.Runner, query string, exact bool, timeout time.Duration)
|
||||
for time.Now().Before(deadline) {
|
||||
h, err := Dump(r)
|
||||
if err == nil {
|
||||
matches := h.FindText(query, exact)
|
||||
matches := h.Find(query, exact)
|
||||
if len(matches) > 0 {
|
||||
sawMatch = true
|
||||
if n, perr := pickBestMatch(matches); perr == nil {
|
||||
@@ -193,14 +195,15 @@ func WaitForText(r *adb.Runner, query string, exact bool, timeout time.Duration)
|
||||
time.Sleep(PollInterval)
|
||||
}
|
||||
if sawMatch {
|
||||
return nil, fmt.Errorf("text %q is present but never became a usable tap target within %s (it is off screen or disabled)", query, timeout)
|
||||
return nil, fmt.Errorf("element matching %q is present but never became a usable tap target within %s (it is off screen or disabled)", query, timeout)
|
||||
}
|
||||
return nil, fmt.Errorf("text %q did not appear within %s", query, timeout)
|
||||
return nil, fmt.Errorf("element matching %q did not appear within %s", query, timeout)
|
||||
}
|
||||
|
||||
// WaitForNoText polls the screen until no element matches query. Recipes use it
|
||||
// to wait for one list to be replaced by another, for example a search result
|
||||
// list replacing the "Recents" list.
|
||||
// list replacing the "Recents" list. A selector may name a resource id with the
|
||||
// "id:" prefix.
|
||||
func WaitForNoText(r *adb.Runner, query string, exact bool, timeout time.Duration) error {
|
||||
if timeout <= 0 {
|
||||
timeout = 10 * time.Second
|
||||
@@ -208,12 +211,12 @@ func WaitForNoText(r *adb.Runner, query string, exact bool, timeout time.Duratio
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
h, err := Dump(r)
|
||||
if err == nil && len(h.FindText(query, exact)) == 0 {
|
||||
if err == nil && len(h.Find(query, exact)) == 0 {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(PollInterval)
|
||||
}
|
||||
return fmt.Errorf("text %q was still on screen after %s", query, timeout)
|
||||
return fmt.Errorf("element matching %q was still on screen after %s", query, timeout)
|
||||
}
|
||||
|
||||
// ScreenSize reads the physical screen size.
|
||||
|
||||
Reference in New Issue
Block a user