v3.19.0 (cont.): live fixtures; menu text match is case-insensitive by default
No test scripts have been authored yet, so the format is still free to
change - the menu-select text match is now case-insensitive by default
(menu labels are UI text; case_sensitive: true still forces an exact-case
match, and a miss on it names the case-insensitive candidates).
Verification against the live card's own bytes (captured 2026-10-04):
- the Annex A Variant 2 Cyrillic menu (ids 128..130) resolves by text and
the case behaviour above is pinned ('кофе' -> item 130);
- the applet's SEND SHORT MESSAGE (alpha 'Отправка...', SMS-SUBMIT to
+79332505884) pins the new alpha and sms checks and the run-log line.
docs/help/api updated; sw cache simple-v388 (help pages changed).
Tests: 819 frontend + 726 Python.
This commit is contained in:
@@ -6033,22 +6033,34 @@ def _test_run_scp80(server, step, ctx):
|
||||
def _menu_item_by_text(server, p):
|
||||
"""Resolve a menu-select step's text against the cached SET UP MENU items
|
||||
(the item ids vary with the applet's install parameters, so a script
|
||||
matches the text the card actually shows). Raises a ScriptError naming
|
||||
matches the text the card actually shows; the match is case-insensitive
|
||||
unless the step sets `case_sensitive: true`). Raises a ScriptError naming
|
||||
the available items when nothing - or more than one item - matches."""
|
||||
menu = getattr(server, 'sim_menu', None) or {}
|
||||
items = menu.get('items') or []
|
||||
spec = {'mode': p.get('mode', 'exact'), 'value': p['text'],
|
||||
'case_sensitive': p.get('case_sensitive', True)}
|
||||
'case_sensitive': p.get('case_sensitive', False)}
|
||||
matches = [it for it in items
|
||||
if testscript.match_text(spec, it.get('text') or '')]
|
||||
if not matches:
|
||||
listing = ', '.join('%s=%r' % (it.get('id'), it.get('text'))
|
||||
for it in items)
|
||||
hint = ''
|
||||
if spec.get('case_sensitive') and items:
|
||||
# A strict-case miss is a common authoring slip with non-ASCII
|
||||
# menus: name the items a case-insensitive match would find.
|
||||
loose = [it for it in items if testscript.match_text(
|
||||
dict(spec, case_sensitive=False), it.get('text') or '')]
|
||||
if loose:
|
||||
hint = (' - a case-insensitive match exists (%s): set '
|
||||
'"case_sensitive": false or fix the case'
|
||||
% ', '.join('%s=%r' % (it.get('id'), it.get('text'))
|
||||
for it in loose))
|
||||
raise testscript.ScriptError(
|
||||
'menu-select: no menu item matches %r (%s)'
|
||||
'menu-select: no menu item matches %r (%s)%s'
|
||||
% (p['text'], 'menu: ' + listing if listing
|
||||
else 'no menu cached - fetch the menu (a SET UP MENU '
|
||||
'expectation) first'))
|
||||
'expectation) first', hint))
|
||||
if len(matches) > 1:
|
||||
raise testscript.ScriptError(
|
||||
'menu-select: %d items match %r (%s) - use the item id'
|
||||
|
||||
@@ -281,7 +281,10 @@ def _normalise_params(kind, p):
|
||||
if mode not in ('exact', 'contains'):
|
||||
raise ScriptError('menu-select: mode must be exact or contains')
|
||||
out['mode'] = mode
|
||||
out['case_sensitive'] = bool(p.get('case_sensitive', True))
|
||||
# Menu labels are UI text: case-insensitive by default (no test
|
||||
# scripts predate this choice); `case_sensitive: true` forces an
|
||||
# exact-case match.
|
||||
out['case_sensitive'] = bool(p.get('case_sensitive', False))
|
||||
if not out:
|
||||
raise ScriptError('menu-select: item_id or text is required')
|
||||
if 'item_id' in out and 'text' in out:
|
||||
|
||||
Reference in New Issue
Block a user