From faa1a33a682a57e747883046c940cbd988a43a66 Mon Sep 17 00:00:00 2001 From: PJ Date: Tue, 18 Aug 2026 20:14:14 +0530 Subject: [PATCH] test(conformance): g4 keeps checking past an input typed at coordinates An InputText that names no field aborts the analyzer, so the gate reports the whole run as failed and checks none of the steps after it. 129 of the 485 recorded traces hold such a step. Red at this commit: jq stops on a null selector and the gate reports FAIL. --- conformance/gates.sh | 2 ++ .../testdata/g4-selectorless-input/exit_status | 1 + conformance/testdata/g4-selectorless-input/output.log | 1 + .../testdata/g4-selectorless-input/trace.jsonl | 3 +++ conformance/testdata/generate.py | 11 +++++++++++ 5 files changed, 18 insertions(+) create mode 100644 conformance/testdata/g4-selectorless-input/exit_status create mode 100644 conformance/testdata/g4-selectorless-input/output.log create mode 100644 conformance/testdata/g4-selectorless-input/trace.jsonl diff --git a/conformance/gates.sh b/conformance/gates.sh index 6e571f8..2cba52a 100755 --- a/conformance/gates.sh +++ b/conformance/gates.sh @@ -518,6 +518,8 @@ self_test() { "$(gate_no_doubled_text "${testdata}/g4-repeated-character" && echo PASS || echo FAIL)" assert "G4 doubled text caught from the recorded value" FAIL \ "$(gate_no_doubled_text "${testdata}/g4-recorded-text" && echo PASS || echo FAIL)" + assert "G4 input without a selector does not abort the gate" PASS \ + "$(gate_no_doubled_text "${testdata}/g4-selectorless-input" && echo PASS || echo FAIL)" assert "seeds default to one distinct value per run" "101 202 303 404 505" \ "$(select_seeds 5 "101 202 303 404 505" >/dev/null 2>&1 && echo "${seed_list[*]}")" diff --git a/conformance/testdata/g4-selectorless-input/exit_status b/conformance/testdata/g4-selectorless-input/exit_status new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/conformance/testdata/g4-selectorless-input/exit_status @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/conformance/testdata/g4-selectorless-input/output.log b/conformance/testdata/g4-selectorless-input/output.log new file mode 100644 index 0000000..ca891a9 --- /dev/null +++ b/conformance/testdata/g4-selectorless-input/output.log @@ -0,0 +1 @@ +run complete diff --git a/conformance/testdata/g4-selectorless-input/trace.jsonl b/conformance/testdata/g4-selectorless-input/trace.jsonl new file mode 100644 index 0000000..ee509ba --- /dev/null +++ b/conformance/testdata/g4-selectorless-input/trace.jsonl @@ -0,0 +1,3 @@ +{"step": 1, "timestamp": "2026-06-06T12:00:00.600000+05:30", "hierarchy": {"elements": [{"resourceId": "LoginScreen", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginScreen", "class": "android.view.View", "text": ""}}, {"resourceId": "LoginEmail", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginEmail", "class": "android.widget.EditText", "text": ""}}, {"resourceId": "LoginPassword", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginPassword", "class": "android.widget.EditText", "text": ""}}, {"resourceId": "LoginSubmit", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginSubmit", "class": "android.view.View", "text": ""}}]}, "next_action": {"kind": "InputText", "text": "[redacted]"}} +{"step": 2, "timestamp": "2026-06-06T12:00:01.200000+05:30", "hierarchy": {"elements": [{"resourceId": "LoginScreen", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginScreen", "class": "android.view.View", "text": ""}}, {"resourceId": "LoginEmail", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginEmail", "class": "android.widget.EditText", "text": "demo@folio.app"}}, {"resourceId": "LoginPassword", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginPassword", "class": "android.widget.EditText", "text": ""}}, {"resourceId": "LoginSubmit", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginSubmit", "class": "android.view.View", "text": ""}}]}, "next_action": {"kind": "InputText", "text": "[redacted]", "selector": "testTag:LoginScreen > testTag:LoginPassword"}} +{"step": 3, "timestamp": "2026-06-06T12:00:01.800000+05:30", "hierarchy": {"elements": [{"resourceId": "LoginScreen", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginScreen", "class": "android.view.View", "text": ""}}, {"resourceId": "LoginEmail", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginEmail", "class": "android.widget.EditText", "text": "demo@folio.app"}}, {"resourceId": "LoginPassword", "class": "android.widget.EditText", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginPassword", "class": "android.widget.EditText", "text": "ledger123"}}, {"resourceId": "LoginSubmit", "class": "android.view.View", "editable": true, "bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135}, "attrs": {"resource-id": "LoginSubmit", "class": "android.view.View", "text": ""}}]}} diff --git a/conformance/testdata/generate.py b/conformance/testdata/generate.py index 4fdbdb5..b17a89c 100644 --- a/conformance/testdata/generate.py +++ b/conformance/testdata/generate.py @@ -152,6 +152,17 @@ write_run( ], ) +# G4: an action typed at coordinates names no field. The step carries nothing +# the gate can check, and it may not stop the gate checking the rest. +write_run( + "g4-selectorless-input", + [ + step(1, 600, login_screen("", ""), {"kind": "InputText", "text": REDACTED}), + step(2, 600, login_screen("demo@folio.app", ""), input_action("LoginPassword")), + step(3, 600, login_screen("demo@folio.app", "ledger123")), + ], +) + # G4: the same regression on a backend that records the typed value. The driver # appended the value twice to what the field already held, so the observed value # is not its own doubling and only the recorded text reveals it.