diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 950c12c..d429115 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -827,13 +827,16 @@ func confirmFocus( // otherElementHoldsFocus reports whether the hierarchy shows focus on // something outside the selector's subtree, which is the state that sends -// typed text to the wrong field. +// typed text to the wrong field. A selector the hierarchy cannot resolve +// answers false: not knowing where the target is says nothing about where the +// text would land, and failing on it turns every step the dump has no node for +// into an apply error, which is an aborted run three steps later. func otherElementHoldsFocus(tree *hierarchy.Tree, selector string) bool { if tree == nil || focusedElement(tree) == nil { return false } target := tree.FindNode(selector) - return target == nil || !holdsFocus(target) + return target != nil && !holdsFocus(target) } func focusedElement(tree *hierarchy.Tree) *hierarchy.Element { diff --git a/internal/runner/runner_test.go b/internal/runner/runner_test.go index 1e1cd90..4911ae5 100644 --- a/internal/runner/runner_test.go +++ b/internal/runner/runner_test.go @@ -974,6 +974,30 @@ func TestApplyAction_InputTextSkipsFocusCheckWhenNoOtherFieldHoldsFocus(t *testi } } +// A selector the hierarchy cannot resolve is the guard saying "I cannot tell", +// not "another element holds focus". Answering the second manufactures an apply +// error on every InputText the tree has no node for, and three in a row abort +// the run. +func TestApplyAction_InputTextTypesWhenTheTargetIsNotInTheHierarchy(t *testing.T) { + fastFocusSettle(t) + tree, err := hierarchy.Parse(loginFocusOnEmail) + if err != nil { + t.Fatalf("Parse: %v", err) + } + driverMock := mockdriver.New() + driverMock.HierarchyJSON = loginFocusOnEmail + action := verifier.Action{ + Kind: verifier.ActionKindInputText, + On: "data-testid:LoginPassword", + Text: "ledger123", + } + + mustDispatch(t, driverMock, action, tree) + if !typedText(driverMock.Actions(), "ledger123") { + t.Errorf("an unresolvable target must not block typing, got %v", driverMock.Actions()) + } +} + func typedText(actions []mockdriver.Action, text string) bool { for _, action := range actions { if action.Kind == mockdriver.ActionInputText && action.Text == text {