Course codes on the shared /course/vs/0 contract aren't guaranteed consistent across board generations: washer/combo devices report course table Table_02, dryer devices Table_03 (x.com.samsung.da.st.courseTable, previously fully ignored), and every code in washer_cycle/dryer_cycle was confirmed exclusively against those. FlexWash's older DA_WM_A51 board reports Table_00 instead -- applying the same translations there risked showing a wrong name for any code that happens to numerically collide between tables, not just an untranslated one. SelectDesc.translation_key can now be a callable (resources -> key or None), mirroring the existing pattern for `options`. laundry.cycle_select gains optional table_href/validated_table params: when given, the renamed washer_cycle_table_02/dryer_cycle_table_03 keys only apply when the device's own course table matches exactly -- a different table, or no table id at all, gets no translation_key (raw code display) rather than a guess. dishwasher's call site is unchanged (static key, unconditional): no equivalent table-id resource exists in any dump seen, and no evidence its course codes vary by table the way washer/dryer's do. entity.py and select.py resolve a callable translation_key once (via coordinator.last_resources) and reuse that resolved value everywhere _display() needs it, rather than re-checking the raw descriptor field.
39 lines
1.5 KiB
Python
39 lines
1.5 KiB
Python
"""Tests for select-option display casing (custom_components/localthings/select.py)."""
|
|
from custom_components.localthings.select import _display
|
|
|
|
_UNTRANSLATED = None
|
|
_TRANSLATED = 'door_alert'
|
|
|
|
|
|
def test_display_titlecases_a_fully_lowercase_device_native_token():
|
|
"""Samsung's sound-mode field is genuinely lowercase on the wire
|
|
('voice'/'tone'/'mute') -- these have no other casing signal to key
|
|
off, so title-case them for display."""
|
|
assert _display('voice', _UNTRANSLATED) == 'Voice'
|
|
assert _display('mute', _UNTRANSLATED) == 'Mute'
|
|
|
|
|
|
def test_display_inserts_a_space_at_a_camelcase_boundary():
|
|
"""'ExtraHigh' (from supportedHeatedDry) should read as two words."""
|
|
assert _display('ExtraHigh', _UNTRANSLATED) == 'Extra High'
|
|
|
|
|
|
def test_display_passes_through_an_already_human_friendly_value():
|
|
"""'AI Wash' etc. (dishwasher cycle names) already read fine and
|
|
have no camelCase boundary or all-lowercase pattern -- must not be
|
|
mangled."""
|
|
assert _display('AI Wash', _UNTRANSLATED) == 'AI Wash'
|
|
assert _display('Low', _UNTRANSLATED) == 'Low'
|
|
assert _display('Off', _UNTRANSLATED) == 'Off'
|
|
|
|
|
|
def test_display_lowercases_for_translation_key_lookup():
|
|
"""An entity with a translation_key must match strings.json's
|
|
lowercase keys exactly -- unlike the untranslated cases above, this
|
|
is not a cosmetic transform."""
|
|
assert _display('Whiskey_IceBall_3', _TRANSLATED) == 'whiskey_iceball_3'
|
|
|
|
|
|
def test_display_passes_through_non_string_values():
|
|
assert _display(None, _UNTRANSLATED) is None
|