Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions homeassistant/components/ps4/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
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 (
Expand Down Expand Up @@ -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)
Expand Down
20 changes: 14 additions & 6 deletions tests/components/ps4/conftest.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
"""Test configuration for PS4."""
from collections.abc import Generator
from unittest.mock import MagicMock, patch

from pyps4_2ndscreen.ddp import DEFAULT_UDP_PORT, DDPProtocol
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
Expand All @@ -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."""
46 changes: 14 additions & 32 deletions tests/components/ps4/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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)
Expand Down
22 changes: 14 additions & 8 deletions tests/components/ps4/test_media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand All @@ -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)

Expand Down