mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
82 lines
3.2 KiB
Python
82 lines
3.2 KiB
Python
"""Tests for the animation image platform and the legacy `animation:` shim."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from esphome.components.animation import (
|
|
DOMAIN,
|
|
LEGACY_REMOVAL_VERSION,
|
|
_capture_legacy_entry,
|
|
_warn_legacy_animation,
|
|
)
|
|
from esphome.core import CORE
|
|
from esphome.types import ConfigType
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Legacy top-level `animation:` deprecation shim -- REMOVE these tests after
|
|
# 2027.1.0 together with the shim in esphome/components/animation/__init__.py.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_warn_legacy_animation_warns_once(
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""The deprecation warning fires exactly once and never mutates the config."""
|
|
config: ConfigType = {"id": "test_animation", "file": "anim.gif", "type": "rgb565"}
|
|
|
|
# A per-entry capture (CONFIG_SCHEMA step) records the raw entry so the
|
|
# one-shot warning can print a pasteable migrated block.
|
|
assert _capture_legacy_entry(config) is config
|
|
|
|
with caplog.at_level(logging.WARNING):
|
|
# First call: flag not yet set -> warns and records the flag.
|
|
assert _warn_legacy_animation(config) is config
|
|
# Second call: flag already set -> stays silent (the dedup branch).
|
|
assert _warn_legacy_animation(config) is config
|
|
|
|
assert CORE.data[DOMAIN]["legacy_warning_shown"] is True
|
|
warnings = [r for r in caplog.records if r.levelno == logging.WARNING]
|
|
assert len(warnings) == 1
|
|
assert "deprecated" in caplog.text
|
|
assert "platform: animation" in caplog.text
|
|
assert LEGACY_REMOVAL_VERSION in caplog.text
|
|
|
|
|
|
def test_legacy_animation_generation(
|
|
generate_main: Callable[[str | Path], str],
|
|
component_config_path: Callable[[str], Path],
|
|
caplog: pytest.LogCaptureFixture,
|
|
) -> None:
|
|
"""The legacy `animation:` block validates, warns, and generates codegen
|
|
through the real read_config/codegen pipeline."""
|
|
with caplog.at_level(logging.WARNING):
|
|
main_cpp = generate_main(component_config_path("animation_test.yaml"))
|
|
|
|
# Deprecation warning surfaced through the real validation pipeline.
|
|
assert "animation" in caplog.text
|
|
assert "deprecated" in caplog.text
|
|
|
|
# setup_animation ran: Animation object constructed and loop configured.
|
|
assert "new(test_animation) animation::Animation(" in main_cpp
|
|
assert "test_animation->set_loop(0, 2, 3);" in main_cpp
|
|
|
|
|
|
def test_animation_platform_generation(
|
|
generate_main: Callable[[str | Path], str],
|
|
component_config_path: Callable[[str], Path],
|
|
) -> None:
|
|
"""The `image:` `platform: animation` form generates codegen through the
|
|
real platform loader (animation/image.py) without any deprecation warning."""
|
|
main_cpp = generate_main(component_config_path("animation_platform_test.yaml"))
|
|
|
|
assert "new(test_animation) animation::Animation(" in main_cpp
|
|
assert "test_animation->set_loop(0, 2, 3);" in main_cpp
|
|
# The loop-less entry constructs the object but never configures a loop.
|
|
assert "new(test_animation_no_loop) animation::Animation(" in main_cpp
|
|
assert "test_animation_no_loop->set_loop(" not in main_cpp
|