diff --git a/homeassistant/components/ps4/__init__.py b/homeassistant/components/ps4/__init__.py index 28ebd8ff077..d9c5f2f6ddb 100644 --- a/homeassistant/components/ps4/__init__.py +++ b/homeassistant/components/ps4/__init__.py @@ -28,7 +28,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.json import save_json from homeassistant.helpers.typing import ConfigType from homeassistant.util import location -from homeassistant.util.json import load_json +from homeassistant.util.json import JsonObjectType, load_json_object from .config_flow import PlayStation4FlowHandler # noqa: F401 from .const import ( @@ -165,19 +165,15 @@ def format_unique_id(creds, mac_address): return f"{mac_address}_{suffix}" -def load_games(hass: HomeAssistant, unique_id: str) -> dict: +def load_games(hass: HomeAssistant, unique_id: str) -> JsonObjectType: """Load games for sources.""" g_file = hass.config.path(GAMES_FILE.format(unique_id)) try: - games = load_json(g_file) + games = load_json_object(g_file) except HomeAssistantError as error: games = {} _LOGGER.error("Failed to load games file: %s", error) - if not isinstance(games, dict): - _LOGGER.error("Games file was not parsed correctly") - games = {} - # If file exists if os.path.isfile(g_file): games = _reformat_data(hass, games, unique_id) diff --git a/tests/components/ps4/conftest.py b/tests/components/ps4/conftest.py index 5bb27012b18..13b6a6e997c 100644 --- a/tests/components/ps4/conftest.py +++ b/tests/components/ps4/conftest.py @@ -1,4 +1,5 @@ """Test configuration for PS4.""" +from collections.abc import Generator from unittest.mock import MagicMock, patch from pyps4_2ndscreen.ddp import DEFAULT_UDP_PORT, DDPProtocol @@ -6,28 +7,30 @@ import pytest @pytest.fixture -def patch_load_json(): +def patch_load_json_object() -> Generator[MagicMock, None, None]: """Prevent load JSON being used.""" - with patch("homeassistant.components.ps4.load_json", return_value={}) as mock_load: + with patch( + "homeassistant.components.ps4.load_json_object", return_value={} + ) as mock_load: yield mock_load @pytest.fixture -def patch_save_json(): +def patch_save_json() -> Generator[MagicMock, None, None]: """Prevent save JSON being used.""" with patch("homeassistant.components.ps4.save_json") as mock_save: yield mock_save @pytest.fixture -def patch_get_status(): +def patch_get_status() -> Generator[MagicMock, None, None]: """Prevent save JSON being used.""" with patch("pyps4_2ndscreen.ps4.get_status", return_value=None) as mock_get_status: yield mock_get_status @pytest.fixture -def mock_ddp_endpoint(): +def mock_ddp_endpoint() -> Generator[None, None, None]: """Mock pyps4_2ndscreen.ddp.async_create_ddp_endpoint.""" protocol = DDPProtocol() protocol._local_port = DEFAULT_UDP_PORT @@ -40,5 +43,10 @@ def mock_ddp_endpoint(): @pytest.fixture(autouse=True) -def patch_io(patch_load_json, patch_save_json, patch_get_status, mock_ddp_endpoint): +def patch_io( + patch_load_json_object: MagicMock, + patch_save_json: MagicMock, + patch_get_status: MagicMock, + mock_ddp_endpoint: None, +) -> None: """Prevent PS4 doing I/O.""" diff --git a/tests/components/ps4/test_init.py b/tests/components/ps4/test_init.py index 5d17421a4b6..3b8dc5e1e24 100644 --- a/tests/components/ps4/test_init.py +++ b/tests/components/ps4/test_init.py @@ -198,14 +198,14 @@ async def setup_mock_component(hass): await hass.async_block_till_done() -def test_games_reformat_to_dict(hass: HomeAssistant) -> None: +def test_games_reformat_to_dict( + hass: HomeAssistant, patch_load_json_object: MagicMock +) -> None: """Test old data format is converted to new format.""" + patch_load_json_object.return_value = MOCK_GAMES_DATA_OLD_STR_FORMAT with patch( - "homeassistant.components.ps4.load_json", - return_value=MOCK_GAMES_DATA_OLD_STR_FORMAT, - ), patch("homeassistant.components.ps4.save_json", side_effect=MagicMock()), patch( - "os.path.isfile", return_value=True - ): + "homeassistant.components.ps4.save_json", side_effect=MagicMock() + ), patch("os.path.isfile", return_value=True): mock_games = ps4.load_games(hass, MOCK_ENTRY_ID) # New format is a nested dict. @@ -221,13 +221,12 @@ def test_games_reformat_to_dict(hass: HomeAssistant) -> None: assert mock_data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.GAME -def test_load_games(hass: HomeAssistant) -> None: +def test_load_games(hass: HomeAssistant, patch_load_json_object: MagicMock) -> None: """Test that games are loaded correctly.""" + patch_load_json_object.return_value = MOCK_GAMES with patch( - "homeassistant.components.ps4.load_json", return_value=MOCK_GAMES - ), patch("homeassistant.components.ps4.save_json", side_effect=MagicMock()), patch( - "os.path.isfile", return_value=True - ): + "homeassistant.components.ps4.save_json", side_effect=MagicMock() + ), patch("os.path.isfile", return_value=True): mock_games = ps4.load_games(hass, MOCK_ENTRY_ID) assert isinstance(mock_games, dict) @@ -240,29 +239,12 @@ def test_load_games(hass: HomeAssistant) -> None: assert mock_data[ATTR_MEDIA_CONTENT_TYPE] == MediaType.GAME -def test_loading_games_returns_dict(hass: HomeAssistant) -> None: +def test_loading_games_returns_dict( + hass: HomeAssistant, patch_load_json_object: MagicMock +) -> None: """Test that loading games always returns a dict.""" + patch_load_json_object.side_effect = HomeAssistantError with patch( - "homeassistant.components.ps4.load_json", side_effect=HomeAssistantError - ), patch("homeassistant.components.ps4.save_json", side_effect=MagicMock()), patch( - "os.path.isfile", return_value=True - ): - mock_games = ps4.load_games(hass, MOCK_ENTRY_ID) - - assert isinstance(mock_games, dict) - assert not mock_games - - with patch( - "homeassistant.components.ps4.load_json", return_value="Some String" - ), patch("homeassistant.components.ps4.save_json", side_effect=MagicMock()), patch( - "os.path.isfile", return_value=True - ): - mock_games = ps4.load_games(hass, MOCK_ENTRY_ID) - - assert isinstance(mock_games, dict) - assert not mock_games - - with patch("homeassistant.components.ps4.load_json", return_value=[]), patch( "homeassistant.components.ps4.save_json", side_effect=MagicMock() ), patch("os.path.isfile", return_value=True): mock_games = ps4.load_games(hass, MOCK_ENTRY_ID) diff --git a/tests/components/ps4/test_media_player.py b/tests/components/ps4/test_media_player.py index 2c5f3d1a836..acb84186c0b 100644 --- a/tests/components/ps4/test_media_player.py +++ b/tests/components/ps4/test_media_player.py @@ -263,11 +263,11 @@ async def test_media_attributes_are_fetched(hass: HomeAssistant) -> None: async def test_media_attributes_are_loaded( - hass: HomeAssistant, patch_load_json + hass: HomeAssistant, patch_load_json_object: MagicMock ) -> None: """Test that media attributes are loaded.""" mock_entity_id = await setup_mock_component(hass) - patch_load_json.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA_LOCKED} + patch_load_json_object.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA_LOCKED} with patch( "homeassistant.components.ps4.media_player." @@ -451,9 +451,11 @@ async def test_media_stop(hass: HomeAssistant) -> None: assert len(mock_call.mock_calls) == 1 -async def test_select_source(hass: HomeAssistant, patch_load_json) -> None: +async def test_select_source( + hass: HomeAssistant, patch_load_json_object: MagicMock +) -> None: """Test that select source service calls function with title.""" - patch_load_json.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} + patch_load_json_object.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} with patch("pyps4_2ndscreen.ps4.get_status", return_value=MOCK_STATUS_IDLE): mock_entity_id = await setup_mock_component(hass) @@ -471,9 +473,11 @@ async def test_select_source(hass: HomeAssistant, patch_load_json) -> None: assert len(mock_call.mock_calls) == 1 -async def test_select_source_caps(hass: HomeAssistant, patch_load_json) -> None: +async def test_select_source_caps( + hass: HomeAssistant, patch_load_json_object: MagicMock +) -> None: """Test that select source service calls function with upper case title.""" - patch_load_json.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} + patch_load_json_object.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} with patch("pyps4_2ndscreen.ps4.get_status", return_value=MOCK_STATUS_IDLE): mock_entity_id = await setup_mock_component(hass) @@ -494,9 +498,11 @@ async def test_select_source_caps(hass: HomeAssistant, patch_load_json) -> None: assert len(mock_call.mock_calls) == 1 -async def test_select_source_id(hass: HomeAssistant, patch_load_json) -> None: +async def test_select_source_id( + hass: HomeAssistant, patch_load_json_object: MagicMock +) -> None: """Test that select source service calls function with Title ID.""" - patch_load_json.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} + patch_load_json_object.return_value = {MOCK_TITLE_ID: MOCK_GAMES_DATA} with patch("pyps4_2ndscreen.ps4.get_status", return_value=MOCK_STATUS_IDLE): mock_entity_id = await setup_mock_component(hass)