An app can stop consuming input while it keeps drawing: Android delivers the tap, the app never acts on it. Phase 3 hit this three times against Spotify and the recipe failed on the label it was waiting for, which names the wrong problem. The new `expect_change <duration>` step fingerprints the screen (foreground package plus every visible label and its bounds) and fails when the screen does not change after the previous step, with the distinct reason "the app stopped consuming input". It supports `retry N`, which re-presses the step above a bounded number of times, so a dropped tap is still recovered and a wedged app still ends the run (FR-11). Co-Authored-By: Paperclip <noreply@paperclip.ing>
69 lines
2.3 KiB
Go
69 lines
2.3 KiB
Go
package ui
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestSignatureIsStable guards the wedged-app check: two reads of an unchanged
|
|
// screen must produce the same signature, or every screen would look like it
|
|
// changed and no wedge could ever be detected.
|
|
func TestSignatureIsStable(t *testing.T) {
|
|
h := parseSample(t)
|
|
first := h.Signature("com.android.settings")
|
|
second := h.Signature("com.android.settings")
|
|
if first != second {
|
|
t.Fatalf("signature is not stable:\n%q\n%q", first, second)
|
|
}
|
|
if !strings.Contains(first, "com.android.settings") {
|
|
t.Fatalf("signature %q does not name the foreground package", first)
|
|
}
|
|
}
|
|
|
|
// TestSignatureSeesRealChanges checks the three things a human would call a
|
|
// change: different text, a moved element, and a different app in front.
|
|
func TestSignatureSeesRealChanges(t *testing.T) {
|
|
h := parseSample(t)
|
|
base := h.Signature("com.android.settings")
|
|
|
|
if h.Signature("com.spotify.music") == base {
|
|
t.Fatal("a different foreground package must change the signature")
|
|
}
|
|
|
|
renamed, err := parseHierarchy([]byte(strings.Replace(sampleDump, "Connected", "Disconnected", 1)))
|
|
if err != nil {
|
|
t.Fatalf("parseHierarchy: %v", err)
|
|
}
|
|
if renamed.Signature("com.android.settings") == base {
|
|
t.Fatal("different visible text must change the signature")
|
|
}
|
|
|
|
moved, err := parseHierarchy([]byte(strings.Replace(sampleDump, "[221,217][453,277]", "[221,300][453,360]", 1)))
|
|
if err != nil {
|
|
t.Fatalf("parseHierarchy: %v", err)
|
|
}
|
|
if moved.Signature("com.android.settings") == base {
|
|
t.Fatal("an element that moved must change the signature")
|
|
}
|
|
}
|
|
|
|
// TestSignatureIgnoresNodeOrder keeps the fingerprint about the screen, not the
|
|
// order uiautomator happened to walk it in.
|
|
func TestSignatureIgnoresNodeOrder(t *testing.T) {
|
|
a, err := parseHierarchy([]byte(`<hierarchy rotation="0">` +
|
|
`<node index="0" text="Alpha" bounds="[0,0][10,10]"/>` +
|
|
`<node index="1" text="Beta" bounds="[0,10][10,20]"/></hierarchy>`))
|
|
if err != nil {
|
|
t.Fatalf("parseHierarchy: %v", err)
|
|
}
|
|
b, err := parseHierarchy([]byte(`<hierarchy rotation="0">` +
|
|
`<node index="0" text="Beta" bounds="[0,10][10,20]"/>` +
|
|
`<node index="1" text="Alpha" bounds="[0,0][10,10]"/></hierarchy>`))
|
|
if err != nil {
|
|
t.Fatalf("parseHierarchy: %v", err)
|
|
}
|
|
if a.Signature("app.one") != b.Signature("app.one") {
|
|
t.Fatal("node order must not change the signature")
|
|
}
|
|
}
|