"""Tests for display metadata created by mipi_spi component.""" from collections.abc import Callable from pathlib import Path from esphome.components.display import ( DisplayMetaData, get_all_display_metadata, get_display_metadata, ) from esphome.components.esp32 import ( KEY_BOARD, KEY_VARIANT, VARIANT_ESP32, VARIANT_ESP32S3, ) from esphome.components.mipi_spi.display import ( CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA, get_instance, ) from esphome.const import PlatformFramework from tests.component_tests.types import SetCoreConfigCallable def validated_config(config): """Run schema + final validation and return the validated config.""" config = CONFIG_SCHEMA(config) FINAL_VALIDATE_SCHEMA(config) return config def test_metadata_native_quad_default_test_card( set_core_config: SetCoreConfigCallable, ) -> None: """A quad-mode display with no explicit drawing gets a test card from final validation.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3}, ) config = validated_config({"model": "JC3636W518"}) get_instance(config) meta = get_display_metadata(str(config["id"])) assert meta is not None assert meta.width == 360 assert meta.height == 360 # final validation auto-enables show_test_card when no drawing methods are configured assert meta.has_writer is True assert meta.has_hardware_rotation is True def test_metadata_single_mode_with_dc_pin( set_core_config: SetCoreConfigCallable, ) -> None: """A single-mode display with no explicit drawing gets a test card from final validation.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, ) config = validated_config( { "model": "ST7735", "dc_pin": 18, } ) get_instance(config) meta = get_display_metadata(str(config["id"])) assert meta is not None assert meta.width == 128 assert meta.height == 160 assert meta.has_writer is True assert meta.has_hardware_rotation is True def test_metadata_custom_dimensions( set_core_config: SetCoreConfigCallable, ) -> None: """A custom model picks up explicit dimensions.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, ) config = validated_config( { "model": "custom", "dc_pin": 18, "dimensions": {"width": 480, "height": 320}, "init_sequence": [[0xA0, 0x01]], } ) get_instance(config) meta = get_display_metadata(str(config["id"])) assert meta is not None assert meta.width == 480 assert meta.height == 320 # final validation auto-enables show_test_card assert meta.has_writer is True assert meta.has_hardware_rotation is True def test_metadata_with_test_card_has_writer( set_core_config: SetCoreConfigCallable, ) -> None: """When show_test_card is enabled, has_writer should be True.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, ) config = validated_config( { "model": "custom", "dc_pin": 18, "dimensions": {"width": 240, "height": 240}, "init_sequence": [[0xA0, 0x01]], "show_test_card": True, } ) get_instance(config) meta = get_display_metadata(str(config["id"])) assert meta is not None assert meta.has_writer is True def test_metadata_no_swap_xy_not_full_hardware_rotation( set_core_config: SetCoreConfigCallable, ) -> None: """A model that disables swap_xy should report has_hardware_rotation=False.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3}, ) # JC3248W535 has swap_xy=cv.UNDEFINED -> transforms={mirror_x, mirror_y} only config = validated_config({"model": "JC3248W535"}) get_instance(config) meta = get_display_metadata(str(config["id"])) assert meta is not None assert meta.has_hardware_rotation is False def test_metadata_multiple_displays_independent( set_core_config: SetCoreConfigCallable, ) -> None: """Multiple displays each get their own metadata entry.""" set_core_config( PlatformFramework.ESP32_IDF, platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, ) config_a = validated_config( { "id": "disp_a", "model": "custom", "dc_pin": 18, "dimensions": {"width": 320, "height": 240}, "init_sequence": [[0xA0, 0x01]], } ) config_b = validated_config( { "id": "disp_b", "model": "custom", "dc_pin": 19, "dimensions": {"width": 128, "height": 64}, "init_sequence": [[0xA0, 0x01]], } ) get_instance(config_a) get_instance(config_b) all_meta = get_all_display_metadata() # final validation auto-enables show_test_card for both assert all_meta["disp_a"] == DisplayMetaData(320, 240, True, True) assert all_meta["disp_b"] == DisplayMetaData(128, 64, True, True) def test_metadata_via_code_generation_native( generate_main: Callable[[str | Path], str], component_fixture_path: Callable[[str], Path], ) -> None: """Full code generation for native.yaml should produce correct metadata.""" generate_main(component_fixture_path("native.yaml")) all_meta = get_all_display_metadata() # native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation assert len(all_meta) == 1 meta = next(iter(all_meta.values())) assert meta == DisplayMetaData( width=360, height=360, has_writer=True, has_hardware_rotation=True ) def test_metadata_via_code_generation_lvgl( generate_main: Callable[[str | Path], str], component_fixture_path: Callable[[str], Path], ) -> None: """Full code generation for lvgl.yaml should produce correct metadata.""" generate_main(component_fixture_path("lvgl.yaml")) all_meta = get_all_display_metadata() # lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation assert len(all_meta) == 1 meta = next(iter(all_meta.values())) assert meta == DisplayMetaData( width=128, height=160, has_writer=False, has_hardware_rotation=True )