mirror of
https://github.com/esphome/esphome.git
synced 2026-09-12 15:57:33 +00:00
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org>
143 lines
4.4 KiB
Python
143 lines
4.4 KiB
Python
"""Tests for the LVGL table widget's configuration validation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from esphome import config_validation as cv
|
|
from esphome.automation import ACTION_REGISTRY
|
|
from esphome.components.lvgl.widgets.table import (
|
|
CONF_MERGE_RIGHT,
|
|
CONF_TEXT_CROP,
|
|
TABLE_SCHEMA,
|
|
)
|
|
|
|
|
|
def test_minimal_config_is_valid() -> None:
|
|
assert TABLE_SCHEMA({}) == {}
|
|
|
|
|
|
def test_row_shorthand_expands_to_plain_cells() -> None:
|
|
config = TABLE_SCHEMA({"rows": [["Name", "Value"]]})
|
|
[row] = config["rows"]
|
|
assert row["cells"] == [{"text": "Name"}, {"text": "Value"}]
|
|
|
|
|
|
def test_row_dict_form_with_cell_overrides() -> None:
|
|
config = TABLE_SCHEMA(
|
|
{
|
|
"rows": [
|
|
{
|
|
"cells": [
|
|
"Temp",
|
|
{"text": "22.5", "text_crop": True, "merge_right": True},
|
|
]
|
|
}
|
|
]
|
|
}
|
|
)
|
|
[row] = config["rows"]
|
|
assert row["cells"][0] == {"text": "Temp"}
|
|
assert row["cells"][1] == {
|
|
"text": "22.5",
|
|
"merge_right": True,
|
|
"text_crop": True,
|
|
}
|
|
|
|
|
|
def test_row_count_defaults_are_not_injected_by_the_schema() -> None:
|
|
# Inference of row/column counts from `rows` happens at code generation
|
|
# time, not during validation - the schema should leave them unset.
|
|
config = TABLE_SCHEMA({"rows": [["a", "b"], ["c"]]})
|
|
assert "row_count" not in config
|
|
assert "column_count" not in config
|
|
|
|
|
|
def test_explicit_row_and_column_count_are_kept() -> None:
|
|
config = TABLE_SCHEMA({"row_count": 5, "column_count": 3})
|
|
assert config["row_count"] == 5
|
|
assert config["column_count"] == 3
|
|
|
|
|
|
def test_row_count_too_small_for_given_rows_raises() -> None:
|
|
with pytest.raises(cv.Invalid, match="row_count"):
|
|
TABLE_SCHEMA({"rows": [["a"], ["b"], ["c"]], "row_count": 2})
|
|
|
|
|
|
def test_column_count_too_small_for_given_cells_raises() -> None:
|
|
with pytest.raises(cv.Invalid, match="column_count"):
|
|
TABLE_SCHEMA({"rows": [["a", "b", "c"]], "column_count": 2})
|
|
|
|
|
|
def test_columns_list_longer_than_column_count_raises() -> None:
|
|
with pytest.raises(cv.Invalid, match="columns"):
|
|
TABLE_SCHEMA(
|
|
{
|
|
"column_count": 1,
|
|
"columns": [{"width": 10}, {"width": 20}],
|
|
}
|
|
)
|
|
|
|
|
|
def test_columns_list_matching_inferred_column_count_is_valid() -> None:
|
|
config = TABLE_SCHEMA(
|
|
{
|
|
"rows": [["a", "b"]],
|
|
"columns": [{"width": 10}, {"width": 20}],
|
|
}
|
|
)
|
|
assert [c["width"] for c in config["columns"]] == [10, 20]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("width", "expected"),
|
|
[
|
|
(100, 100),
|
|
("50%", 0.5),
|
|
("32px", 32),
|
|
],
|
|
)
|
|
def test_column_width_accepts_pixels_and_percent(width, expected) -> None:
|
|
config = TABLE_SCHEMA({"columns": [{"width": width}]})
|
|
assert config["columns"][0]["width"] == expected
|
|
|
|
|
|
def test_columns_percent_widths_summing_over_100_percent_raises() -> None:
|
|
with pytest.raises(cv.Invalid, match="columns"):
|
|
TABLE_SCHEMA({"columns": [{"width": "60%"}, {"width": "50%"}]})
|
|
|
|
|
|
def test_columns_percent_widths_summing_to_100_percent_is_valid() -> None:
|
|
config = TABLE_SCHEMA({"columns": [{"width": "60%"}, {"width": "40%"}]})
|
|
assert [c["width"] for c in config["columns"]] == [0.6, 0.4]
|
|
|
|
|
|
def test_columns_mixed_pixel_and_percent_widths_ignore_pixels_in_the_total() -> None:
|
|
# Pixel widths aren't part of the percentage budget, so they shouldn't
|
|
# count towards the 100% limit.
|
|
config = TABLE_SCHEMA(
|
|
{"columns": [{"width": 200}, {"width": "80%"}, {"width": "20%"}]}
|
|
)
|
|
assert [c["width"] for c in config["columns"]] == [200, 0.8, 0.2]
|
|
|
|
|
|
def test_selected_row_and_selected_column_are_independently_optional() -> None:
|
|
config = TABLE_SCHEMA({"selected_row": 1})
|
|
assert config["selected_row"] == 1
|
|
assert "selected_column" not in config
|
|
|
|
|
|
def test_cell_update_action_requires_at_least_one_field() -> None:
|
|
entry = ACTION_REGISTRY["lvgl.table.cell.update"]
|
|
with pytest.raises(cv.Invalid):
|
|
entry.schema({"id": "some_table", "row": 0, "column": 0})
|
|
|
|
|
|
def test_cell_update_action_accepts_a_single_field() -> None:
|
|
entry = ACTION_REGISTRY["lvgl.table.cell.update"]
|
|
config = entry.schema(
|
|
{"id": "some_table", "row": 0, "column": 0, "merge_right": True}
|
|
)
|
|
assert config[CONF_MERGE_RIGHT] is True
|
|
assert CONF_TEXT_CROP not in config
|