diff --git a/homeassistant/components/chess_com/icons.json b/homeassistant/components/chess_com/icons.json index 9b5e9291683..f29b2517670 100644 --- a/homeassistant/components/chess_com/icons.json +++ b/homeassistant/components/chess_com/icons.json @@ -1,20 +1,68 @@ { "entity": { "sensor": { + "chess960_daily_draw": { + "default": "mdi:chess-pawn" + }, + "chess960_daily_lost": { + "default": "mdi:chess-pawn" + }, + "chess960_daily_rating": { + "default": "mdi:chart-line" + }, + "chess960_daily_won": { + "default": "mdi:chess-pawn" + }, + "chess_blitz_draw": { + "default": "mdi:chess-pawn" + }, + "chess_blitz_lost": { + "default": "mdi:chess-pawn" + }, + "chess_blitz_rating": { + "default": "mdi:chart-line" + }, + "chess_blitz_won": { + "default": "mdi:chess-pawn" + }, + "chess_bullet_draw": { + "default": "mdi:chess-pawn" + }, + "chess_bullet_lost": { + "default": "mdi:chess-pawn" + }, + "chess_bullet_rating": { + "default": "mdi:chart-line" + }, + "chess_bullet_won": { + "default": "mdi:chess-pawn" + }, + "chess_daily_draw": { + "default": "mdi:chess-pawn" + }, + "chess_daily_lost": { + "default": "mdi:chess-pawn" + }, "chess_daily_rating": { "default": "mdi:chart-line" }, + "chess_daily_won": { + "default": "mdi:chess-pawn" + }, + "chess_rapid_draw": { + "default": "mdi:chess-pawn" + }, + "chess_rapid_lost": { + "default": "mdi:chess-pawn" + }, + "chess_rapid_rating": { + "default": "mdi:chart-line" + }, + "chess_rapid_won": { + "default": "mdi:chess-pawn" + }, "followers": { "default": "mdi:account-multiple" - }, - "total_daily_draw": { - "default": "mdi:chess-pawn" - }, - "total_daily_lost": { - "default": "mdi:chess-pawn" - }, - "total_daily_won": { - "default": "mdi:chess-pawn" } } } diff --git a/homeassistant/components/chess_com/sensor.py b/homeassistant/components/chess_com/sensor.py index 3bb3ab268a4..ddac50bef31 100644 --- a/homeassistant/components/chess_com/sensor.py +++ b/homeassistant/components/chess_com/sensor.py @@ -2,6 +2,9 @@ from collections.abc import Callable from dataclasses import dataclass +from typing import TYPE_CHECKING, Any + +from chess_com_api import PlayerStats from homeassistant.components.sensor import ( SensorEntity, @@ -24,7 +27,14 @@ class ChessEntityDescription(SensorEntityDescription): value_fn: Callable[[ChessData], float] -SENSORS: tuple[ChessEntityDescription, ...] = ( +@dataclass(kw_only=True, frozen=True) +class ChessModeEntityDescription(SensorEntityDescription): + """Sensor description for a Chess.com game mode.""" + + value_fn: Callable[[dict[str, Any]], float] + + +PLAYER_SENSORS: tuple[ChessEntityDescription, ...] = ( ChessEntityDescription( key="followers", translation_key="followers", @@ -33,35 +43,46 @@ SENSORS: tuple[ChessEntityDescription, ...] = ( value_fn=lambda state: state.player.followers, entity_registry_enabled_default=False, ), - ChessEntityDescription( - key="chess_daily_rating", - translation_key="chess_daily_rating", +) + +GAME_MODE_SENSORS: tuple[ChessModeEntityDescription, ...] = ( + ChessModeEntityDescription( + key="rating", + translation_key="rating", state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda state: state.stats.chess_daily["last"]["rating"], + value_fn=lambda mode: mode["last"]["rating"], ), - ChessEntityDescription( - key="total_daily_won", - translation_key="total_daily_won", + ChessModeEntityDescription( + key="won", + translation_key="won", entity_category=EntityCategory.DIAGNOSTIC, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda state: state.stats.chess_daily["record"]["win"], + value_fn=lambda mode: mode["record"]["win"], ), - ChessEntityDescription( - key="total_daily_lost", - translation_key="total_daily_lost", + ChessModeEntityDescription( + key="lost", + translation_key="lost", entity_category=EntityCategory.DIAGNOSTIC, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda state: state.stats.chess_daily["record"]["loss"], + value_fn=lambda mode: mode["record"]["loss"], ), - ChessEntityDescription( - key="total_daily_draw", - translation_key="total_daily_draw", + ChessModeEntityDescription( + key="draw", + translation_key="draw", entity_category=EntityCategory.DIAGNOSTIC, state_class=SensorStateClass.TOTAL_INCREASING, - value_fn=lambda state: state.stats.chess_daily["record"]["draw"], + value_fn=lambda mode: mode["record"]["draw"], ), ) +GAME_MODES: dict[str, Callable[[PlayerStats], dict[str, Any] | None]] = { + "chess_daily": lambda stats: stats.chess_daily, + "chess_rapid": lambda stats: stats.chess_rapid, + "chess_bullet": lambda stats: stats.chess_bullet, + "chess_blitz": lambda stats: stats.chess_blitz, + "chess960_daily": lambda stats: stats.chess960_daily, +} + async def async_setup_entry( hass: HomeAssistant, @@ -71,13 +92,22 @@ async def async_setup_entry( """Initialize the entries.""" coordinator = entry.runtime_data - async_add_entities( - ChessPlayerSensor(coordinator, description) for description in SENSORS - ) + entities: list[SensorEntity] = [ + ChessPlayerSensor(coordinator, description) for description in PLAYER_SENSORS + ] + + for game_mode, stats_fn in GAME_MODES.items(): + if stats_fn(coordinator.data.stats) is not None: + entities.extend( + ChessGameModeSensor(coordinator, description, game_mode, stats_fn) + for description in GAME_MODE_SENSORS + ) + + async_add_entities(entities) class ChessPlayerSensor(ChessEntity, SensorEntity): - """Chess.com sensor.""" + """Chess.com player sensor.""" entity_description: ChessEntityDescription @@ -95,3 +125,33 @@ class ChessPlayerSensor(ChessEntity, SensorEntity): def native_value(self) -> float: """Return the state of the sensor.""" return self.entity_description.value_fn(self.coordinator.data) + + +class ChessGameModeSensor(ChessEntity, SensorEntity): + """Chess.com game mode sensor.""" + + entity_description: ChessModeEntityDescription + + def __init__( + self, + coordinator: ChessCoordinator, + description: ChessModeEntityDescription, + game_mode: str, + stats_fn: Callable[[PlayerStats], dict[str, Any] | None], + ) -> None: + """Initialize the sensor.""" + super().__init__(coordinator) + self.entity_description = description + self._stats_fn = stats_fn + self._attr_unique_id = ( + f"{coordinator.config_entry.unique_id}.{game_mode}.{description.key}" + ) + self._attr_translation_key = f"{game_mode}_{description.translation_key}" + + @property + def native_value(self) -> float: + """Return the state of the sensor.""" + mode_data = self._stats_fn(self.coordinator.data.stats) + if TYPE_CHECKING: + assert mode_data is not None + return self.entity_description.value_fn(mode_data) diff --git a/homeassistant/components/chess_com/strings.json b/homeassistant/components/chess_com/strings.json index 0646b004e79..7623e3e0c15 100644 --- a/homeassistant/components/chess_com/strings.json +++ b/homeassistant/components/chess_com/strings.json @@ -23,24 +23,84 @@ }, "entity": { "sensor": { + "chess960_daily_draw": { + "name": "Total daily Chess960 games drawn", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess960_daily_lost": { + "name": "Total daily Chess960 games lost", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess960_daily_rating": { + "name": "Daily Chess960 rating" + }, + "chess960_daily_won": { + "name": "Total daily Chess960 games won", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_blitz_draw": { + "name": "Total blitz chess games drawn", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_blitz_lost": { + "name": "Total blitz chess games lost", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_blitz_rating": { + "name": "Blitz chess rating" + }, + "chess_blitz_won": { + "name": "Total blitz chess games won", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_bullet_draw": { + "name": "Total bullet chess games drawn", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_bullet_lost": { + "name": "Total bullet chess games lost", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_bullet_rating": { + "name": "Bullet chess rating" + }, + "chess_bullet_won": { + "name": "Total bullet chess games won", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_daily_draw": { + "name": "Total daily chess games drawn", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_daily_lost": { + "name": "Total daily chess games lost", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, "chess_daily_rating": { "name": "Daily chess rating" }, + "chess_daily_won": { + "name": "Total daily chess games won", + "unit_of_measurement": "games" + }, + "chess_rapid_draw": { + "name": "Total rapid chess games drawn", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_rapid_lost": { + "name": "Total rapid chess games lost", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, + "chess_rapid_rating": { + "name": "Rapid chess rating" + }, + "chess_rapid_won": { + "name": "Total rapid chess games won", + "unit_of_measurement": "[%key:component::chess_com::entity::sensor::chess_daily_won::unit_of_measurement%]" + }, "followers": { "name": "Followers", "unit_of_measurement": "followers" - }, - "total_daily_draw": { - "name": "Total chess games drawn", - "unit_of_measurement": "[%key:component::chess_com::entity::sensor::total_daily_won::unit_of_measurement%]" - }, - "total_daily_lost": { - "name": "Total chess games lost", - "unit_of_measurement": "[%key:component::chess_com::entity::sensor::total_daily_won::unit_of_measurement%]" - }, - "total_daily_won": { - "name": "Total chess games won", - "unit_of_measurement": "games" } } } diff --git a/tests/components/chess_com/fixtures/stats.json b/tests/components/chess_com/fixtures/stats.json index cf49ad0b332..b22806ec121 100644 --- a/tests/components/chess_com/fixtures/stats.json +++ b/tests/components/chess_com/fixtures/stats.json @@ -13,6 +13,62 @@ "timeout_percent": 0 } }, + "chess_rapid": { + "last": { + "rating": 812, + "date": 1772800350, + "rd": 74 + }, + "record": { + "win": 5, + "loss": 3, + "draw": 1, + "time_per_move": 42, + "timeout_percent": 0 + } + }, + "chess_bullet": { + "last": { + "rating": 650, + "date": 1772800350, + "rd": 120 + }, + "record": { + "win": 2, + "loss": 6, + "draw": 0, + "time_per_move": 8, + "timeout_percent": 0 + } + }, + "chess_blitz": { + "last": { + "rating": 734, + "date": 1772800350, + "rd": 95 + }, + "record": { + "win": 10, + "loss": 8, + "draw": 2, + "time_per_move": 18, + "timeout_percent": 0 + } + }, + "chess960_daily": { + "last": { + "rating": 521, + "date": 1772800350, + "rd": 200 + }, + "record": { + "win": 1, + "loss": 2, + "draw": 0, + "time_per_move": 7200, + "timeout_percent": 0 + } + }, "fide": 0, "tactics": { "highest": { diff --git a/tests/components/chess_com/fixtures/stats_daily_only.json b/tests/components/chess_com/fixtures/stats_daily_only.json new file mode 100644 index 00000000000..cf49ad0b332 --- /dev/null +++ b/tests/components/chess_com/fixtures/stats_daily_only.json @@ -0,0 +1,33 @@ +{ + "chess_daily": { + "last": { + "rating": 495, + "date": 1772800350, + "rd": 196 + }, + "record": { + "win": 0, + "loss": 4, + "draw": 0, + "time_per_move": 6974, + "timeout_percent": 0 + } + }, + "fide": 0, + "tactics": { + "highest": { + "rating": 764, + "date": 1772782351 + }, + "lowest": { + "rating": 400, + "date": 1771584762 + } + }, + "puzzle_rush": { + "best": { + "total_attempts": 11, + "score": 8 + } + } +} diff --git a/tests/components/chess_com/snapshots/test_diagnostics.ambr b/tests/components/chess_com/snapshots/test_diagnostics.ambr index 39f689e66da..0bf6181c2d7 100644 --- a/tests/components/chess_com/snapshots/test_diagnostics.ambr +++ b/tests/components/chess_com/snapshots/test_diagnostics.ambr @@ -19,9 +19,48 @@ 'username': 'joostlek', }), 'stats': dict({ - 'chess960_daily': None, - 'chess_blitz': None, - 'chess_bullet': None, + 'chess960_daily': dict({ + 'last': dict({ + 'date': 1772800350, + 'rating': 521, + 'rd': 200, + }), + 'record': dict({ + 'draw': 0, + 'loss': 2, + 'time_per_move': 7200, + 'timeout_percent': 0, + 'win': 1, + }), + }), + 'chess_blitz': dict({ + 'last': dict({ + 'date': 1772800350, + 'rating': 734, + 'rd': 95, + }), + 'record': dict({ + 'draw': 2, + 'loss': 8, + 'time_per_move': 18, + 'timeout_percent': 0, + 'win': 10, + }), + }), + 'chess_bullet': dict({ + 'last': dict({ + 'date': 1772800350, + 'rating': 650, + 'rd': 120, + }), + 'record': dict({ + 'draw': 0, + 'loss': 6, + 'time_per_move': 8, + 'timeout_percent': 0, + 'win': 2, + }), + }), 'chess_daily': dict({ 'last': dict({ 'date': 1772800350, @@ -36,7 +75,20 @@ 'win': 0, }), }), - 'chess_rapid': None, + 'chess_rapid': dict({ + 'last': dict({ + 'date': 1772800350, + 'rating': 812, + 'rd': 74, + }), + 'record': dict({ + 'draw': 1, + 'loss': 3, + 'time_per_move': 42, + 'timeout_percent': 0, + 'win': 5, + }), + }), 'lessons': None, 'puzzle_rush': dict({ 'best': dict({ diff --git a/tests/components/chess_com/snapshots/test_sensor.ambr b/tests/components/chess_com/snapshots/test_sensor.ambr index a877762e62d..8b41dc970b6 100644 --- a/tests/components/chess_com/snapshots/test_sensor.ambr +++ b/tests/components/chess_com/snapshots/test_sensor.ambr @@ -1,4 +1,163 @@ # serializer version: 1 +# name: test_all_entities[sensor.joost_blitz_chess_rating-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.joost_blitz_chess_rating', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Blitz chess rating', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Blitz chess rating', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_blitz_rating', + 'unique_id': '532748851.chess_blitz.rating', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.joost_blitz_chess_rating-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Blitz chess rating', + 'state_class': , + }), + 'context': , + 'entity_id': 'sensor.joost_blitz_chess_rating', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '734', + }) +# --- +# name: test_all_entities[sensor.joost_bullet_chess_rating-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.joost_bullet_chess_rating', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Bullet chess rating', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Bullet chess rating', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_bullet_rating', + 'unique_id': '532748851.chess_bullet.rating', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.joost_bullet_chess_rating-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Bullet chess rating', + 'state_class': , + }), + 'context': , + 'entity_id': 'sensor.joost_bullet_chess_rating', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '650', + }) +# --- +# name: test_all_entities[sensor.joost_daily_chess960_rating-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.joost_daily_chess960_rating', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Daily Chess960 rating', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Daily Chess960 rating', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess960_daily_rating', + 'unique_id': '532748851.chess960_daily.rating', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.joost_daily_chess960_rating-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Daily Chess960 rating', + 'state_class': , + }), + 'context': , + 'entity_id': 'sensor.joost_daily_chess960_rating', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '521', + }) +# --- # name: test_all_entities[sensor.joost_daily_chess_rating-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -34,7 +193,7 @@ 'suggested_object_id': None, 'supported_features': 0, 'translation_key': 'chess_daily_rating', - 'unique_id': '532748851.chess_daily_rating', + 'unique_id': '532748851.chess_daily.rating', 'unit_of_measurement': None, }) # --- @@ -106,7 +265,60 @@ 'state': '2', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_drawn-entry] +# name: test_all_entities[sensor.joost_rapid_chess_rating-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.joost_rapid_chess_rating', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Rapid chess rating', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Rapid chess rating', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_rapid_rating', + 'unique_id': '532748851.chess_rapid.rating', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.joost_rapid_chess_rating-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Rapid chess rating', + 'state_class': , + }), + 'context': , + 'entity_id': 'sensor.joost_rapid_chess_rating', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '812', + }) +# --- +# name: test_all_entities[sensor.joost_total_blitz_chess_games_drawn-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -122,7 +334,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': , - 'entity_id': 'sensor.joost_total_chess_games_drawn', + 'entity_id': 'sensor.joost_total_blitz_chess_games_drawn', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -130,37 +342,199 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Total chess games drawn', + 'object_id_base': 'Total blitz chess games drawn', 'options': dict({ }), 'original_device_class': None, 'original_icon': None, - 'original_name': 'Total chess games drawn', + 'original_name': 'Total blitz chess games drawn', 'platform': 'chess_com', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'total_daily_draw', - 'unique_id': '532748851.total_daily_draw', + 'translation_key': 'chess_blitz_draw', + 'unique_id': '532748851.chess_blitz.draw', 'unit_of_measurement': 'games', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_drawn-state] +# name: test_all_entities[sensor.joost_total_blitz_chess_games_drawn-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'friendly_name': 'Joost Total chess games drawn', + 'friendly_name': 'Joost Total blitz chess games drawn', 'state_class': , 'unit_of_measurement': 'games', }), 'context': , - 'entity_id': 'sensor.joost_total_chess_games_drawn', + 'entity_id': 'sensor.joost_total_blitz_chess_games_drawn', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2', + }) +# --- +# name: test_all_entities[sensor.joost_total_blitz_chess_games_lost-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_blitz_chess_games_lost', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total blitz chess games lost', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total blitz chess games lost', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_blitz_lost', + 'unique_id': '532748851.chess_blitz.lost', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_blitz_chess_games_lost-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total blitz chess games lost', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_blitz_chess_games_lost', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '8', + }) +# --- +# name: test_all_entities[sensor.joost_total_blitz_chess_games_won-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_blitz_chess_games_won', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total blitz chess games won', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total blitz chess games won', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_blitz_won', + 'unique_id': '532748851.chess_blitz.won', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_blitz_chess_games_won-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total blitz chess games won', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_blitz_chess_games_won', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '10', + }) +# --- +# name: test_all_entities[sensor.joost_total_bullet_chess_games_drawn-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_bullet_chess_games_drawn', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total bullet chess games drawn', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total bullet chess games drawn', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_bullet_draw', + 'unique_id': '532748851.chess_bullet.draw', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_bullet_chess_games_drawn-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total bullet chess games drawn', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_bullet_chess_games_drawn', 'last_changed': , 'last_reported': , 'last_updated': , 'state': '0', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_lost-entry] +# name: test_all_entities[sensor.joost_total_bullet_chess_games_lost-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -176,7 +550,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': , - 'entity_id': 'sensor.joost_total_chess_games_lost', + 'entity_id': 'sensor.joost_total_bullet_chess_games_lost', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -184,37 +558,361 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Total chess games lost', + 'object_id_base': 'Total bullet chess games lost', 'options': dict({ }), 'original_device_class': None, 'original_icon': None, - 'original_name': 'Total chess games lost', + 'original_name': 'Total bullet chess games lost', 'platform': 'chess_com', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'total_daily_lost', - 'unique_id': '532748851.total_daily_lost', + 'translation_key': 'chess_bullet_lost', + 'unique_id': '532748851.chess_bullet.lost', 'unit_of_measurement': 'games', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_lost-state] +# name: test_all_entities[sensor.joost_total_bullet_chess_games_lost-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'friendly_name': 'Joost Total chess games lost', + 'friendly_name': 'Joost Total bullet chess games lost', 'state_class': , 'unit_of_measurement': 'games', }), 'context': , - 'entity_id': 'sensor.joost_total_chess_games_lost', + 'entity_id': 'sensor.joost_total_bullet_chess_games_lost', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '6', + }) +# --- +# name: test_all_entities[sensor.joost_total_bullet_chess_games_won-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_bullet_chess_games_won', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total bullet chess games won', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total bullet chess games won', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_bullet_won', + 'unique_id': '532748851.chess_bullet.won', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_bullet_chess_games_won-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total bullet chess games won', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_bullet_chess_games_won', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_drawn-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_drawn', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total daily Chess960 games drawn', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total daily Chess960 games drawn', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess960_daily_draw', + 'unique_id': '532748851.chess960_daily.draw', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_drawn-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total daily Chess960 games drawn', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_drawn', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_lost-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_lost', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total daily Chess960 games lost', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total daily Chess960 games lost', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess960_daily_lost', + 'unique_id': '532748851.chess960_daily.lost', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_lost-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total daily Chess960 games lost', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_lost', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_won-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_won', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total daily Chess960 games won', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total daily Chess960 games won', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess960_daily_won', + 'unique_id': '532748851.chess960_daily.won', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess960_games_won-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total daily Chess960 games won', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_daily_chess960_games_won', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess_games_drawn-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_daily_chess_games_drawn', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total daily chess games drawn', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total daily chess games drawn', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_daily_draw', + 'unique_id': '532748851.chess_daily.draw', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess_games_drawn-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total daily chess games drawn', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_daily_chess_games_drawn', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess_games_lost-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_daily_chess_games_lost', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total daily chess games lost', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total daily chess games lost', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_daily_lost', + 'unique_id': '532748851.chess_daily.lost', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_daily_chess_games_lost-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total daily chess games lost', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_daily_chess_games_lost', 'last_changed': , 'last_reported': , 'last_updated': , 'state': '4', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_won-entry] +# name: test_all_entities[sensor.joost_total_daily_chess_games_won-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -230,7 +928,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': , - 'entity_id': 'sensor.joost_total_chess_games_won', + 'entity_id': 'sensor.joost_total_daily_chess_games_won', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -238,33 +936,195 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Total chess games won', + 'object_id_base': 'Total daily chess games won', 'options': dict({ }), 'original_device_class': None, 'original_icon': None, - 'original_name': 'Total chess games won', + 'original_name': 'Total daily chess games won', 'platform': 'chess_com', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'total_daily_won', - 'unique_id': '532748851.total_daily_won', + 'translation_key': 'chess_daily_won', + 'unique_id': '532748851.chess_daily.won', 'unit_of_measurement': 'games', }) # --- -# name: test_all_entities[sensor.joost_total_chess_games_won-state] +# name: test_all_entities[sensor.joost_total_daily_chess_games_won-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'friendly_name': 'Joost Total chess games won', + 'friendly_name': 'Joost Total daily chess games won', 'state_class': , 'unit_of_measurement': 'games', }), 'context': , - 'entity_id': 'sensor.joost_total_chess_games_won', + 'entity_id': 'sensor.joost_total_daily_chess_games_won', 'last_changed': , 'last_reported': , 'last_updated': , 'state': '0', }) # --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_drawn-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_drawn', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total rapid chess games drawn', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total rapid chess games drawn', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_rapid_draw', + 'unique_id': '532748851.chess_rapid.draw', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_drawn-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total rapid chess games drawn', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_drawn', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1', + }) +# --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_lost-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_lost', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total rapid chess games lost', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total rapid chess games lost', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_rapid_lost', + 'unique_id': '532748851.chess_rapid.lost', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_lost-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total rapid chess games lost', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_lost', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '3', + }) +# --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_won-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_won', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Total rapid chess games won', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Total rapid chess games won', + 'platform': 'chess_com', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'chess_rapid_won', + 'unique_id': '532748851.chess_rapid.won', + 'unit_of_measurement': 'games', + }) +# --- +# name: test_all_entities[sensor.joost_total_rapid_chess_games_won-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Joost Total rapid chess games won', + 'state_class': , + 'unit_of_measurement': 'games', + }), + 'context': , + 'entity_id': 'sensor.joost_total_rapid_chess_games_won', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '5', + }) +# --- diff --git a/tests/components/chess_com/test_sensor.py b/tests/components/chess_com/test_sensor.py index 4d90b9d5364..ae154cc0e66 100644 --- a/tests/components/chess_com/test_sensor.py +++ b/tests/components/chess_com/test_sensor.py @@ -2,16 +2,22 @@ from unittest.mock import AsyncMock, patch +from chess_com_api import PlayerStats import pytest from syrupy.assertion import SnapshotAssertion +from homeassistant.components.chess_com.const import DOMAIN from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from . import setup_integration -from tests.common import MockConfigEntry, snapshot_platform +from tests.common import ( + MockConfigEntry, + async_load_json_object_fixture, + snapshot_platform, +) @pytest.mark.usefixtures("entity_registry_enabled_by_default") @@ -27,3 +33,21 @@ async def test_all_entities( await setup_integration(hass, mock_config_entry) await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +async def test_daily_only( + hass: HomeAssistant, + mock_chess_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test that entities for unplayed game modes are not created.""" + mock_chess_client.get_player_stats.return_value = PlayerStats.from_dict( + await async_load_json_object_fixture(hass, "stats_daily_only.json", DOMAIN) + ) + with patch("homeassistant.components.chess_com._PLATFORMS", [Platform.SENSOR]): + await setup_integration(hass, mock_config_entry) + + assert hass.states.get("sensor.joost_rapid_chess_rating") is None + assert hass.states.get("sensor.joost_bullet_chess_rating") is None + assert hass.states.get("sensor.joost_blitz_chess_rating") is None + assert hass.states.get("sensor.joost_daily_chess960_rating") is None