test(conformance): the g4 fixture holds what a redacted android trace holds

Android reports no secure fact for any field, so every InputText it records
writes the redaction placeholder rather than the typed value. The fixture still
carried the real value, which is the only reason the gate reported itself as
catching the doubling. Two more fixtures come with it: a repeated-character
corpus value that reads as its own doubling and must not fail, and a backend
that does record the typed value.

Red at this commit: G4 reports PASS on a doubled field it cannot see.
This commit is contained in:
pj committed 2026-08-18 20:07:39 +05:30
1 parent f7b90a9886
commit f631415cb6
15 files changed
+85 -23

No files matched your search

+59 -10
View File
@@ -11,13 +11,22 @@ HERE = os.path.dirname(os.path.abspath(__file__))
BASE = datetime(2026, 6, 6, 12, 0, 0, tzinfo=timezone(timedelta(hours=5, minutes=30)))
def element(resource_id, text="", element_class="android.widget.EditText"):
# What a typed value is written to the trace as when the target reports no
# secure fact for the field. Android reports none for any field, so every
# InputText it records reads this (internal/verifier/redaction.go).
REDACTED = "[redacted]"
def element(resource_id, text="", element_class="android.widget.EditText", secure=None):
attrs = {"resource-id": resource_id, "class": element_class, "text": text}
if secure is not None:
attrs["secure"] = "true" if secure else "false"
return {
"resourceId": resource_id,
"class": element_class,
"editable": True,
"bounds": {"left": 34, "top": 87, "right": 286, "bottom": 135},
"attrs": {"resource-id": resource_id, "class": element_class, "text": text},
"attrs": attrs,
}
@@ -32,7 +41,21 @@ def login_screen(email_text="", password_text=""):
}
def input_action(field, text):
# iOS states the secure fact on every editable field, so the typed value reaches
# the trace for any field the platform reports as not a secure entry.
def ios_login_screen(email_text=""):
return {
"elements": [
element("LoginScreen", element_class="XCUIElementTypeOther"),
element("LoginEmail", email_text,
element_class="XCUIElementTypeTextField", secure=False),
element("LoginPassword", element_class="XCUIElementTypeSecureTextField",
secure=True),
]
}
def input_action(field, text=REDACTED):
return {
"kind": "InputText",
"text": text,
@@ -61,12 +84,12 @@ def write_run(name, steps, exit_status="0", output_lines=None):
handle.writelines(lines)
# A clean run: empty login fields first, single (not doubled) typed values in
# the following snapshots, sub-second step gaps.
# A clean run on the android backend: empty login fields first, single (not
# doubled) values observed in the following snapshots, sub-second step gaps.
def healthy_steps(gap_ms=600):
return [
step(1, gap_ms, login_screen("", ""), input_action("LoginEmail", "[email protected]")),
step(2, gap_ms, login_screen("[email protected]", ""), input_action("LoginPassword", "ledger123")),
step(1, gap_ms, login_screen("", ""), input_action("LoginEmail")),
step(2, gap_ms, login_screen("[email protected]", ""), input_action("LoginPassword")),
step(3, gap_ms, login_screen("[email protected]", "ledger123")),
step(4, gap_ms, login_screen("[email protected]", "ledger123")),
]
@@ -100,21 +123,47 @@ write_run(
write_run(
"g3-dirty-field",
[
step(1, 600, login_screen("[email protected]", "leftover"), input_action("LoginEmail", "[email protected]")),
step(1, 600, login_screen("[email protected]", "leftover"), input_action("LoginEmail")),
step(2, 600, login_screen("[email protected]", "leftover")),
],
)
# G4: after typing into LoginEmail the next snapshot shows the value appended to
# itself (append-vs-replace / double-paste regression).
# itself (append-vs-replace / double-paste regression). The typed value is the
# redaction placeholder, as it is on every android InputText, so the doubling is
# only visible in the observed field value.
write_run(
"g4-doubled-text",
[
step(1, 600, login_screen("", ""), input_action("LoginEmail", "[email protected]")),
step(1, 600, login_screen("", ""), input_action("LoginEmail")),
step(2, 600, login_screen("[email protected]@folio.app", "")),
],
)
# G4: two corpus values that read as their own doubling. "a" repeated and a pair
# of spaces are each one character over and over, so neither says anything about
# how many times the driver typed it, and neither may fail the gate.
write_run(
"g4-repeated-character",
[
step(1, 600, login_screen("", ""), input_action("LoginEmail")),
step(2, 600, login_screen("a" * 4096, ""), input_action("LoginEmail")),
step(3, 600, login_screen(" ", "")),
],
)
# 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.
write_run(
"g4-recorded-text",
[
step(1, 600, ios_login_screen("[email protected]"),
input_action("LoginEmail", "ledger123")),
step(2, 600, ios_login_screen("[email protected]")),
],
)
# G5: step gaps far exceed the 2.5s ceiling, driving p95 over the limit.
write_run("g5-slow-p95", healthy_steps(gap_ms=4000))