|
| 1 | +Verify a Field After Typing |
| 2 | +=========================== |
| 3 | + |
| 4 | +``field_entry`` types into a control and *hopes* it landed. A slow IME, a focus |
| 5 | +steal, an input mask or an auto-format can silently mangle or drop characters, |
| 6 | +and nothing reads the field back to notice. This is distinct from |
| 7 | +``action_effect`` (did *anything* change near the target?) and |
| 8 | +``postcondition.text_present`` (does the text appear *anywhere* on screen?) — |
| 9 | +neither confirms *this* field now equals *this* value. ``verify_field`` closes |
| 10 | +the read-back gap. |
| 11 | + |
| 12 | +* :func:`compare_field_value` — pure: compare an expected and actual value under |
| 13 | + a match ``mode`` — ``exact`` / ``trim`` / ``ci`` (case-insensitive) / |
| 14 | + ``normalized`` (Unicode NFKC + case-fold + whitespace) / ``contains``. |
| 15 | +* :func:`verify_field_value` — read the field through an injectable ``reader`` |
| 16 | + and compare. |
| 17 | +* :func:`fill_and_verify` — type through an injectable ``filler``, read back, and |
| 18 | + retry (optionally clearing first) until it matches or attempts run out. |
| 19 | + |
| 20 | +In the executor the reader is the native accessibility value, but every |
| 21 | +comparison and retry decision is pure and testable without a real control. |
| 22 | +Imports no ``PySide6``. |
| 23 | + |
| 24 | +Headless API |
| 25 | +------------ |
| 26 | + |
| 27 | +.. code-block:: python |
| 28 | +
|
| 29 | + from je_auto_control import ( |
| 30 | + compare_field_value, verify_field_value, fill_and_verify, |
| 31 | + ) |
| 32 | +
|
| 33 | + compare_field_value("café", "café", mode="normalized")["match"] # True |
| 34 | +
|
| 35 | + # Read a control back and assert it took the value |
| 36 | + ok = verify_field_value("invoice.pdf", |
| 37 | + reader=lambda: read_control_value())["match"] |
| 38 | +
|
| 39 | + # Type, read back, and retry up to 3 times (clearing before each retry) |
| 40 | + fill_and_verify("2026-06-26", filler=type_into_field, |
| 41 | + reader=read_control_value, attempts=3, clear=select_all_del) |
| 42 | +
|
| 43 | +``fill_and_verify`` returns the final :func:`compare_field_value` result plus an |
| 44 | +``attempts`` count, so a flow can branch on a persistent mismatch instead of |
| 45 | +typing blind. ``filler`` / ``reader`` / ``clear`` are injectable, so the retry |
| 46 | +logic is fully unit-tested without a real field. |
| 47 | + |
| 48 | +Executor commands |
| 49 | +----------------- |
| 50 | + |
| 51 | +``AC_compare_field_value`` (``expected`` / ``actual`` / ``mode`` → ``{match, |
| 52 | +mode, expected, actual}``, pure) and ``AC_verify_field_value`` (``expected`` + |
| 53 | +``name`` / ``role`` / ``app_name`` / ``automation_id`` / ``mode`` → the match |
| 54 | +result, reading the control's value through the accessibility backend). They are |
| 55 | +the matching read-only ``ac_*`` MCP tools and Script Builder commands under |
| 56 | +**Flow**. :func:`fill_and_verify` (which wraps a typing callable) is the |
| 57 | +Python-API surface. |
0 commit comments