"""Guard: enum dropdowns in the plugin config form honour x-options.labels. The form derives an option's visible text from its value — underscores replaced, title case applied ("day_first" -> "Day First"). That cannot express every label a schema needs: "vs" reads as "Vs", and "abbrev" says nothing about the "Sep 19" it produces. Schemas can supply x-options.labels instead, the same convention the checkbox-group widget already uses. These tests extract the enum `. ENUM_BLOCK_RE = re.compile( r"(\{%\s*set enum_labels\s*=.*?)", re.S ) def _shipped_enum_block() -> str: """Return the live enum block in plugin_config.html — the ' 'template changed shape and this guard needs updating' ) return match.group(1) def _render(prop: dict, value=None) -> str: """Render the shipped enum block with a minimal fixture.""" env = Environment(loader=DictLoader({'f': _shipped_enum_block()}), autoescape=True) return env.get_template('f').render( prop=prop, value=value, field_id='fid', full_key='k' ) def _option_labels(html: str) -> dict: """Map each rendered option's value to its visible text.""" return { value: text.strip() for value, text in re.findall( r'', html, re.S ) } def test_labels_are_used_when_supplied() -> None: html = _render({ 'enum': ['vs', 'date_time'], 'x-options': {'labels': {'vs': 'VS', 'date_time': 'Date and time'}}, }) assert _option_labels(html) == {'vs': 'VS', 'date_time': 'Date and time'} def test_unlabelled_values_keep_the_humanised_fallback() -> None: """Schemas without labels must render exactly as they did before.""" html = _render({'enum': ['day_first', 'weekday']}) assert _option_labels(html) == {'day_first': 'Day First', 'weekday': 'Weekday'} def test_partial_labels_fall_back_per_value() -> None: """A labels map covering some values leaves the rest humanised.""" html = _render({'enum': ['vs', 'day_first'], 'x-options': {'labels': {'vs': 'VS'}}}) assert _option_labels(html) == {'vs': 'VS', 'day_first': 'Day First'} def test_option_values_are_unchanged_by_labelling() -> None: """Labels are display-only: the submitted value stays the enum value.""" html = _render({'enum': ['abbrev'], 'x-options': {'labels': {'abbrev': 'Sep 19'}}}) assert _option_labels(html) == {'abbrev': 'Sep 19'} def test_selected_option_still_tracks_the_current_value() -> None: """Labelling must not disturb which option is marked selected.""" html = _render({'enum': ['abbrev', 'numeric'], 'x-options': {'labels': {'abbrev': 'Sep 19'}}}, value='numeric') selected = re.search(r'