From 88500f1e6cee8b5efb079192312cf30e3abd1682 Mon Sep 17 00:00:00 2001 From: Philip Vanloo Date: Wed, 21 Aug 2024 16:21:14 +0000 Subject: [PATCH 1/3] Improve set volume tests --- src/linkplay/bridge.py | 35 ++++++++++++++++++++++++-------- tests/linkplay/test_bridge.py | 36 +++++++++++++++++++++++++++------ tests/linkplay/test_consts.py | 1 - tests/linkplay/test_endpoint.py | 1 - tox.ini | 2 +- 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/linkplay/bridge.py b/src/linkplay/bridge.py index 7438c48..09f795f 100644 --- a/src/linkplay/bridge.py +++ b/src/linkplay/bridge.py @@ -151,7 +151,10 @@ async def set_play_mode(self, mode: PlayingMode) -> None: @property def muted(self) -> bool: """Returns if the player is muted.""" - return self.properties.get(PlayerAttribute.MUTED, MuteMode.UNMUTED) == MuteMode.MUTED + return ( + self.properties.get(PlayerAttribute.MUTED, MuteMode.UNMUTED) + == MuteMode.MUTED + ) @property def title(self) -> str: @@ -186,32 +189,46 @@ def total_length(self) -> int: @property def status(self) -> PlayingStatus: """Returns the current playing status.""" - return PlayingStatus(self.properties.get(PlayerAttribute.PLAYING_STATUS, PlayingStatus.STOPPED)) + return PlayingStatus( + self.properties.get(PlayerAttribute.PLAYING_STATUS, PlayingStatus.STOPPED) + ) @property def equalizer_mode(self) -> EqualizerMode: """Returns the current equalizer mode.""" - return EqualizerMode(self.properties.get(PlayerAttribute.EQUALIZER_MODE, EqualizerMode.CLASSIC)) + return EqualizerMode( + self.properties.get(PlayerAttribute.EQUALIZER_MODE, EqualizerMode.CLASSIC) + ) @property def speaker_type(self) -> SpeakerType: """Returns the current speaker the player is playing on.""" - return SpeakerType(self.properties.get(PlayerAttribute.SPEAKER_TYPE, SpeakerType.MAIN_SPEAKER)) + return SpeakerType( + self.properties.get(PlayerAttribute.SPEAKER_TYPE, SpeakerType.MAIN_SPEAKER) + ) @property def channel_type(self) -> ChannelType: """Returns the channel the player is playing on.""" - return ChannelType(self.properties.get(PlayerAttribute.CHANNEL_TYPE, ChannelType.STEREO)) + return ChannelType( + self.properties.get(PlayerAttribute.CHANNEL_TYPE, ChannelType.STEREO) + ) @property def play_mode(self) -> PlayingMode: """Returns the current playing mode of the player.""" - return PlayingMode(self.properties.get(PlayerAttribute.PLAYBACK_MODE, PlayingMode.IDLE)) + return PlayingMode( + self.properties.get(PlayerAttribute.PLAYBACK_MODE, PlayingMode.IDLE) + ) @property def loop_mode(self) -> LoopMode: """Returns the current playlist mode.""" - return LoopMode(self.properties.get(PlayerAttribute.PLAYLIST_MODE, LoopMode.CONTINUOUS_PLAYBACK)) + return LoopMode( + self.properties.get( + PlayerAttribute.PLAYLIST_MODE, LoopMode.CONTINUOUS_PLAYBACK + ) + ) class LinkPlayBridge: @@ -292,7 +309,9 @@ async def remove_follower(self, follower: LinkPlayBridge) -> None: async def set_volume(self, value: int) -> None: """Sets the volume for the multiroom group.""" - assert 0 < value <= 100 + if not 0 <= value <= 100: + raise ValueError("Volume must be between 0 and 100") + str_vol = str(value) await self.leader.request(LinkPlayCommand.MULTIROOM_VOL.format(str_vol)) # type: ignore[str-format] diff --git a/tests/linkplay/test_bridge.py b/tests/linkplay/test_bridge.py index a2d4d85..ed6392d 100644 --- a/tests/linkplay/test_bridge.py +++ b/tests/linkplay/test_bridge.py @@ -1,7 +1,9 @@ """Test bridge functionality.""" +from typing import Any from unittest.mock import AsyncMock +import pytest from linkplay.bridge import ( LinkPlayBridge, LinkPlayDevice, @@ -166,14 +168,25 @@ async def test_player_toggle(): bridge.request.assert_called_once_with(LinkPlayCommand.TOGGLE) -async def test_player_set_volume(): +@pytest.mark.parametrize("volume", range(0, 101)) +async def test_player_set_volume(volume: int): """Tests if the player set volume is correctly called.""" bridge = AsyncMock() player = LinkPlayPlayer(bridge) - await player.set_volume(100) + await player.set_volume(volume) - bridge.request.assert_called_once_with(LinkPlayCommand.VOLUME.format(100)) + bridge.request.assert_called_once_with(LinkPlayCommand.VOLUME.format(volume)) + + +@pytest.mark.parametrize("volume", [-1, 101]) +async def test_player_set_volume_raises_value_error(volume: Any): + """Tests if the player set volume is correctly called.""" + bridge = AsyncMock() + player = LinkPlayPlayer(bridge) + + with pytest.raises(ValueError): + await player.set_volume(volume) async def test_player_set_equalizer_mode(): @@ -297,11 +310,22 @@ async def test_multiroom_unmute(): leader.request.assert_called_once_with(LinkPlayCommand.MULTIROOM_UNMUTE) -async def test_multiroom_set_volume(): +@pytest.mark.parametrize("volume", range(0, 101)) +async def test_multiroom_set_volume(volume: int): """Tests if multiroom set volume is correctly called on the leader.""" leader = AsyncMock() multiroom = LinkPlayMultiroom(leader) - await multiroom.set_volume(100) + await multiroom.set_volume(volume) + + leader.request.assert_called_once_with(LinkPlayCommand.MULTIROOM_VOL.format(volume)) + + +@pytest.mark.parametrize("volume", [-1, 101]) +async def test_multiroom_set_volume_raises_value_error(volume: int): + """Tests if multiroom set volume is correctly called on the leader.""" + leader = AsyncMock() + multiroom = LinkPlayMultiroom(leader) - leader.request.assert_called_once_with(LinkPlayCommand.MULTIROOM_VOL.format(100)) + with pytest.raises(ValueError): + await multiroom.set_volume(volume) diff --git a/tests/linkplay/test_consts.py b/tests/linkplay/test_consts.py index 5723cfe..c301e2d 100644 --- a/tests/linkplay/test_consts.py +++ b/tests/linkplay/test_consts.py @@ -1,7 +1,6 @@ """Test consts.""" import pytest - from linkplay.consts import INPUT_MODE_MAP, PLAY_MODE_SEND_MAP, InputMode, PlayingMode diff --git a/tests/linkplay/test_endpoint.py b/tests/linkplay/test_endpoint.py index bba7e29..e1a139d 100644 --- a/tests/linkplay/test_endpoint.py +++ b/tests/linkplay/test_endpoint.py @@ -1,7 +1,6 @@ """Test endpoint functionality.""" import pytest - from linkplay.endpoint import LinkPlayApiEndpoint diff --git a/tox.ini b/tox.ini index 7b57489..cbae1f9 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ commands = [testenv:ruff] basepython = python3.11 deps = ruff -commands = ruff check src tests +commands = ruff check src tests --fix [testenv:mypy] basepython = python3.11 From b8dafd445974a23ab8c1fb9fd451b97724ab6719 Mon Sep 17 00:00:00 2001 From: Philip Vanloo Date: Wed, 21 Aug 2024 19:03:33 +0200 Subject: [PATCH 2/3] Run tests in py311 and 312, add ruff format to tox --- tests/linkplay/test_bridge.py | 1 + tests/linkplay/test_consts.py | 1 + tests/linkplay/test_endpoint.py | 1 + tox.ini | 9 +++++---- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/linkplay/test_bridge.py b/tests/linkplay/test_bridge.py index ed6392d..a4f8359 100644 --- a/tests/linkplay/test_bridge.py +++ b/tests/linkplay/test_bridge.py @@ -4,6 +4,7 @@ from unittest.mock import AsyncMock import pytest + from linkplay.bridge import ( LinkPlayBridge, LinkPlayDevice, diff --git a/tests/linkplay/test_consts.py b/tests/linkplay/test_consts.py index c301e2d..5723cfe 100644 --- a/tests/linkplay/test_consts.py +++ b/tests/linkplay/test_consts.py @@ -1,6 +1,7 @@ """Test consts.""" import pytest + from linkplay.consts import INPUT_MODE_MAP, PLAY_MODE_SEND_MAP, InputMode, PlayingMode diff --git a/tests/linkplay/test_endpoint.py b/tests/linkplay/test_endpoint.py index e1a139d..bba7e29 100644 --- a/tests/linkplay/test_endpoint.py +++ b/tests/linkplay/test_endpoint.py @@ -1,6 +1,7 @@ """Test endpoint functionality.""" import pytest + from linkplay.endpoint import LinkPlayApiEndpoint diff --git a/tox.ini b/tox.ini index cbae1f9..6998ba4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,12 @@ [tox] minversion = 4.6.0 -envlist = py311, ruff, mypy +envlist = py{311,312},ruff,mypy isolated_build = true [gh-actions] python = 3.11: py311, mypy, ruff + 3.12: py312, mypy, ruff [testenv] package = wheel @@ -17,12 +18,12 @@ commands = pytest --cov-report html:htmlcov/pytest --basetemp={envtmpdir} [testenv:ruff] -basepython = python3.11 deps = ruff -commands = ruff check src tests --fix +commands = + ruff check --fix --verbose src tests + ruff format --verbose src tests [testenv:mypy] -basepython = python3.11 deps = -r{toxinidir}/requirements_dev.txt commands = mypy --install-types --non-interactive src \ No newline at end of file From 3be2cc6b14dd99d97237503904252e5f95e83c7b Mon Sep 17 00:00:00 2001 From: Philip Vanloo Date: Thu, 22 Aug 2024 08:53:44 +0000 Subject: [PATCH 3/3] Cleanup --- tox.ini | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tox.ini b/tox.ini index 6998ba4..7b57489 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,11 @@ [tox] minversion = 4.6.0 -envlist = py{311,312},ruff,mypy +envlist = py311, ruff, mypy isolated_build = true [gh-actions] python = 3.11: py311, mypy, ruff - 3.12: py312, mypy, ruff [testenv] package = wheel @@ -18,12 +17,12 @@ commands = pytest --cov-report html:htmlcov/pytest --basetemp={envtmpdir} [testenv:ruff] +basepython = python3.11 deps = ruff -commands = - ruff check --fix --verbose src tests - ruff format --verbose src tests +commands = ruff check src tests [testenv:mypy] +basepython = python3.11 deps = -r{toxinidir}/requirements_dev.txt commands = mypy --install-types --non-interactive src \ No newline at end of file