From ef3bd0100c0941c5d28bad73dcda9ec1483b06dd Mon Sep 17 00:00:00 2001 From: jjlawren Date: Fri, 29 Sep 2023 22:04:00 -0500 Subject: [PATCH] Bump plexapi to 4.15.3 (#101088) * Bump plexapi to 4.15.3 * Update tests for updated account endpoint * Update tests for updated resources endpoint * Switch to non-web client fixture * Set __qualname__ attribute for new library behavior --- homeassistant/components/plex/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/plex/conftest.py | 10 +++- .../fixtures/player_plexhtpc_resources.xml | 3 ++ .../plex/fixtures/plextv_account.xml | 23 +++++---- .../fixtures/plextv_resources_one_server.xml | 40 +++++++++------- .../fixtures/plextv_resources_two_servers.xml | 48 +++++++++++-------- tests/components/plex/test_config_flow.py | 12 ++--- tests/components/plex/test_init.py | 10 ++-- tests/components/plex/test_media_players.py | 4 +- tests/components/plex/test_media_search.py | 11 ++++- tests/components/plex/test_playback.py | 40 ++++++++++++---- tests/components/plex/test_sensor.py | 30 ++++++++++-- tests/components/plex/test_services.py | 6 ++- 15 files changed, 159 insertions(+), 84 deletions(-) create mode 100644 tests/components/plex/fixtures/player_plexhtpc_resources.xml diff --git a/homeassistant/components/plex/manifest.json b/homeassistant/components/plex/manifest.json index bc0c54c49bf..6cf94793173 100644 --- a/homeassistant/components/plex/manifest.json +++ b/homeassistant/components/plex/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_push", "loggers": ["plexapi", "plexwebsocket"], "requirements": [ - "PlexAPI==4.13.2", + "PlexAPI==4.15.3", "plexauth==0.0.6", "plexwebsocket==0.0.13" ], diff --git a/requirements_all.txt b/requirements_all.txt index a0b33962ea4..1c3b3b58098 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -46,7 +46,7 @@ Mastodon.py==1.5.1 Pillow==10.0.0 # homeassistant.components.plex -PlexAPI==4.13.2 +PlexAPI==4.15.3 # homeassistant.components.progettihwsw ProgettiHWSW==0.1.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 153083fbcf3..986828f170c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -42,7 +42,7 @@ HATasmota==0.7.3 Pillow==10.0.0 # homeassistant.components.plex -PlexAPI==4.13.2 +PlexAPI==4.15.3 # homeassistant.components.progettihwsw ProgettiHWSW==0.1.3 diff --git a/tests/components/plex/conftest.py b/tests/components/plex/conftest.py index e4bf61ccd94..78a3b7387ea 100644 --- a/tests/components/plex/conftest.py +++ b/tests/components/plex/conftest.py @@ -232,6 +232,12 @@ def player_plexweb_resources_fixture(): return load_fixture("plex/player_plexweb_resources.xml") +@pytest.fixture(name="player_plexhtpc_resources", scope="session") +def player_plexhtpc_resources_fixture(): + """Load resources payload for a Plex HTPC player and return it.""" + return load_fixture("plex/player_plexhtpc_resources.xml") + + @pytest.fixture(name="playlists", scope="session") def playlists_fixture(): """Load payload for all playlists and return it.""" @@ -450,8 +456,8 @@ def mock_plex_calls( """Mock Plex API calls.""" requests_mock.get("https://plex.tv/api/users/", text=plextv_shared_users) requests_mock.get("https://plex.tv/api/invites/requested", text=empty_payload) - requests_mock.get("https://plex.tv/users/account", text=plextv_account) - requests_mock.get("https://plex.tv/api/resources", text=plextv_resources) + requests_mock.get("https://plex.tv/api/v2/user", text=plextv_account) + requests_mock.get("https://plex.tv/api/v2/resources", text=plextv_resources) url = plex_server_url(entry) diff --git a/tests/components/plex/fixtures/player_plexhtpc_resources.xml b/tests/components/plex/fixtures/player_plexhtpc_resources.xml new file mode 100644 index 00000000000..6cc9cc0afbd --- /dev/null +++ b/tests/components/plex/fixtures/player_plexhtpc_resources.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/components/plex/fixtures/plextv_account.xml b/tests/components/plex/fixtures/plextv_account.xml index 32d6eec7c2d..b47896de577 100644 --- a/tests/components/plex/fixtures/plextv_account.xml +++ b/tests/components/plex/fixtures/plextv_account.xml @@ -1,15 +1,18 @@ - - - + + + + + + + + + - - - - testuser - testuser@email.com - 2000-01-01 12:34:56 UTC - faketoken + + + + diff --git a/tests/components/plex/fixtures/plextv_resources_one_server.xml b/tests/components/plex/fixtures/plextv_resources_one_server.xml index ff2e458ff24..75b7e54b7e6 100644 --- a/tests/components/plex/fixtures/plextv_resources_one_server.xml +++ b/tests/components/plex/fixtures/plextv_resources_one_server.xml @@ -1,18 +1,22 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/components/plex/fixtures/plextv_resources_two_servers.xml b/tests/components/plex/fixtures/plextv_resources_two_servers.xml index 7da5df4c1df..f14b55fe161 100644 --- a/tests/components/plex/fixtures/plextv_resources_two_servers.xml +++ b/tests/components/plex/fixtures/plextv_resources_two_servers.xml @@ -1,21 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/components/plex/test_config_flow.py b/tests/components/plex/test_config_flow.py index beb454e2e9c..235596715f4 100644 --- a/tests/components/plex/test_config_flow.py +++ b/tests/components/plex/test_config_flow.py @@ -143,7 +143,7 @@ async def test_no_servers_found( current_request_with_host: None, ) -> None: """Test when no servers are on an account.""" - requests_mock.get("https://plex.tv/api/resources", text=empty_payload) + requests_mock.get("https://plex.tv/api/v2/resources", text=empty_payload) result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} @@ -225,7 +225,7 @@ async def test_multiple_servers_with_selection( assert result["step_id"] == "user" requests_mock.get( - "https://plex.tv/api/resources", + "https://plex.tv/api/v2/resources", text=plextv_resources_two_servers, ) with patch("plexauth.PlexAuth.initiate_auth"), patch( @@ -289,7 +289,7 @@ async def test_adding_last_unconfigured_server( assert result["step_id"] == "user" requests_mock.get( - "https://plex.tv/api/resources", + "https://plex.tv/api/v2/resources", text=plextv_resources_two_servers, ) @@ -346,9 +346,9 @@ async def test_all_available_servers_configured( assert result["type"] == FlowResultType.FORM assert result["step_id"] == "user" - requests_mock.get("https://plex.tv/users/account", text=plextv_account) + requests_mock.get("https://plex.tv/api/v2/user", text=plextv_account) requests_mock.get( - "https://plex.tv/api/resources", + "https://plex.tv/api/v2/resources", text=plextv_resources_two_servers, ) @@ -776,7 +776,7 @@ async def test_reauth_multiple_servers_available( ) -> None: """Test setup and reauthorization of a Plex token when multiple servers are available.""" requests_mock.get( - "https://plex.tv/api/resources", + "https://plex.tv/api/v2/resources", text=plextv_resources_two_servers, ) diff --git a/tests/components/plex/test_init.py b/tests/components/plex/test_init.py index bc43a1e0d89..6e1043b5c52 100644 --- a/tests/components/plex/test_init.py +++ b/tests/components/plex/test_init.py @@ -231,7 +231,7 @@ async def test_setup_when_certificate_changed( # Test with account failure requests_mock.get( - "https://plex.tv/users/account", status_code=HTTPStatus.UNAUTHORIZED + "https://plex.tv/api/v2/user", status_code=HTTPStatus.UNAUTHORIZED ) old_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(old_entry.entry_id) is False @@ -241,8 +241,8 @@ async def test_setup_when_certificate_changed( await hass.config_entries.async_unload(old_entry.entry_id) # Test with no servers found - requests_mock.get("https://plex.tv/users/account", text=plextv_account) - requests_mock.get("https://plex.tv/api/resources", text=empty_payload) + requests_mock.get("https://plex.tv/api/v2/user", text=plextv_account) + requests_mock.get("https://plex.tv/api/v2/resources", text=empty_payload) assert await hass.config_entries.async_setup(old_entry.entry_id) is False await hass.async_block_till_done() @@ -252,7 +252,7 @@ async def test_setup_when_certificate_changed( # Test with success new_url = PLEX_DIRECT_URL - requests_mock.get("https://plex.tv/api/resources", text=plextv_resources) + requests_mock.get("https://plex.tv/api/v2/resources", text=plextv_resources) for resource_url in [new_url, "http://1.2.3.4:32400"]: requests_mock.get(resource_url, text=plex_server_default) requests_mock.get(f"{new_url}/accounts", text=plex_server_accounts) @@ -287,7 +287,7 @@ async def test_bad_token_with_tokenless_server( ) -> None: """Test setup with a bad token and a server with token auth disabled.""" requests_mock.get( - "https://plex.tv/users/account", status_code=HTTPStatus.UNAUTHORIZED + "https://plex.tv/api/v2/user", status_code=HTTPStatus.UNAUTHORIZED ) await setup_plex_server() diff --git a/tests/components/plex/test_media_players.py b/tests/components/plex/test_media_players.py index 27fea36e3b0..e9efc945f71 100644 --- a/tests/components/plex/test_media_players.py +++ b/tests/components/plex/test_media_players.py @@ -12,10 +12,10 @@ async def test_plex_tv_clients( entry, setup_plex_server, requests_mock: requests_mock.Mocker, - player_plexweb_resources, + player_plexhtpc_resources, ) -> None: """Test getting Plex clients from plex.tv.""" - requests_mock.get("/resources", text=player_plexweb_resources) + requests_mock.get("/resources", text=player_plexhtpc_resources) with patch("plexapi.myplex.MyPlexResource.connect", side_effect=NotFound): await setup_plex_server() diff --git a/tests/components/plex/test_media_search.py b/tests/components/plex/test_media_search.py index 0cc94134f1c..21b50724786 100644 --- a/tests/components/plex/test_media_search.py +++ b/tests/components/plex/test_media_search.py @@ -70,7 +70,10 @@ async def test_media_lookups( ) assert "Library 'Not a Library' not found in" in str(excinfo.value) - with patch("plexapi.library.LibrarySection.search") as search: + with patch( + "plexapi.library.LibrarySection.search", + __qualname__="search", + ) as search: await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, @@ -261,7 +264,11 @@ async def test_media_lookups( with pytest.raises(MediaNotFound) as excinfo: payload = '{"library_name": "Movies", "title": "Not a Movie"}' - with patch("plexapi.library.LibrarySection.search", side_effect=BadRequest): + with patch( + "plexapi.library.LibrarySection.search", + side_effect=BadRequest, + __qualname__="search", + ): await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, diff --git a/tests/components/plex/test_playback.py b/tests/components/plex/test_playback.py index c9dba4e4aca..9ea684256c4 100644 --- a/tests/components/plex/test_playback.py +++ b/tests/components/plex/test_playback.py @@ -49,14 +49,14 @@ async def test_media_player_playback( setup_plex_server, requests_mock: requests_mock.Mocker, playqueue_created, - player_plexweb_resources, + player_plexhtpc_resources, ) -> None: """Test playing media on a Plex media_player.""" - requests_mock.get("http://1.2.3.5:32400/resources", text=player_plexweb_resources) + requests_mock.get("http://1.2.3.6:32400/resources", text=player_plexhtpc_resources) await setup_plex_server() - media_player = "media_player.plex_plex_web_chrome" + media_player = "media_player.plex_plex_htpc_for_mac_plex_htpc" requests_mock.post("/playqueues", text=playqueue_created) playmedia_mock = requests_mock.get( "/player/playback/playMedia", status_code=HTTPStatus.OK @@ -65,7 +65,9 @@ async def test_media_player_playback( # Test media lookup failure payload = '{"library_name": "Movies", "title": "Movie 1" }' with patch( - "plexapi.library.LibrarySection.search", return_value=None + "plexapi.library.LibrarySection.search", + return_value=None, + __qualname__="search", ), pytest.raises(HomeAssistantError) as excinfo: await hass.services.async_call( MP_DOMAIN, @@ -86,7 +88,11 @@ async def test_media_player_playback( # Test movie success movies = [movie1] - with patch("plexapi.library.LibrarySection.search", return_value=movies): + with patch( + "plexapi.library.LibrarySection.search", + return_value=movies, + __qualname__="search", + ): await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, @@ -101,7 +107,11 @@ async def test_media_player_playback( # Test movie success with resume playmedia_mock.reset() - with patch("plexapi.library.LibrarySection.search", return_value=movies): + with patch( + "plexapi.library.LibrarySection.search", + return_value=movies, + __qualname__="search", + ): await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, @@ -163,7 +173,11 @@ async def test_media_player_playback( # Test multiple choices with exact match playmedia_mock.reset() movies = [movie1, movie2] - with patch("plexapi.library.LibrarySection.search", return_value=movies): + with patch( + "plexapi.library.LibrarySection.search", + return_value=movies, + __qualname__="search", + ): await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, @@ -181,7 +195,11 @@ async def test_media_player_playback( movies = [movie2, movie3] with pytest.raises(HomeAssistantError) as excinfo: payload = '{"library_name": "Movies", "title": "Movie" }' - with patch("plexapi.library.LibrarySection.search", return_value=movies): + with patch( + "plexapi.library.LibrarySection.search", + return_value=movies, + __qualname__="search", + ): await hass.services.async_call( MP_DOMAIN, SERVICE_PLAY_MEDIA, @@ -197,7 +215,11 @@ async def test_media_player_playback( # Test multiple choices with allow_multiple movies = [movie1, movie2, movie3] - with patch("plexapi.library.LibrarySection.search", return_value=movies), patch( + with patch( + "plexapi.library.LibrarySection.search", + return_value=movies, + __qualname__="search", + ), patch( "homeassistant.components.plex.server.PlexServer.create_playqueue" ) as mock_create_playqueue: await hass.services.async_call( diff --git a/tests/components/plex/test_sensor.py b/tests/components/plex/test_sensor.py index 9c73bf9f915..5b9729792f4 100644 --- a/tests/components/plex/test_sensor.py +++ b/tests/components/plex/test_sensor.py @@ -129,7 +129,11 @@ async def test_library_sensor_values( ) media = [MockPlexTVEpisode()] - with patch("plexapi.library.LibrarySection.recentlyAdded", return_value=media): + with patch( + "plexapi.library.LibrarySection.recentlyAdded", + return_value=media, + __qualname__="recentlyAdded", + ): await hass.async_block_till_done() library_tv_sensor = hass.states.get("sensor.plex_server_1_library_tv_shows") @@ -165,7 +169,11 @@ async def test_library_sensor_values( trigger_plex_update( mock_websocket, msgtype="status", payload=LIBRARY_UPDATE_PAYLOAD ) - with patch("plexapi.library.LibrarySection.recentlyAdded", return_value=media): + with patch( + "plexapi.library.LibrarySection.recentlyAdded", + return_value=media, + __qualname__="recentlyAdded", + ): await hass.async_block_till_done() library_tv_sensor = hass.states.get("sensor.plex_server_1_library_tv_shows") @@ -200,7 +208,11 @@ async def test_library_sensor_values( ) media = [MockPlexMovie()] - with patch("plexapi.library.LibrarySection.recentlyAdded", return_value=media): + with patch( + "plexapi.library.LibrarySection.recentlyAdded", + return_value=media, + __qualname__="recentlyAdded", + ): await hass.async_block_till_done() library_movies_sensor = hass.states.get("sensor.plex_server_1_library_movies") @@ -210,7 +222,11 @@ async def test_library_sensor_values( # Test with clip media = [MockPlexClip()] - with patch("plexapi.library.LibrarySection.recentlyAdded", return_value=media): + with patch( + "plexapi.library.LibrarySection.recentlyAdded", + return_value=media, + __qualname__="recentlyAdded", + ): async_dispatcher_send( hass, PLEX_UPDATE_LIBRARY_SIGNAL.format(mock_plex_server.machine_identifier) ) @@ -236,7 +252,11 @@ async def test_library_sensor_values( ) media = [MockPlexMusic()] - with patch("plexapi.library.LibrarySection.recentlyAdded", return_value=media): + with patch( + "plexapi.library.LibrarySection.recentlyAdded", + return_value=media, + __qualname__="recentlyAdded", + ): await hass.async_block_till_done() library_music_sensor = hass.states.get("sensor.plex_server_1_library_music") diff --git a/tests/components/plex/test_services.py b/tests/components/plex/test_services.py index a74b3e91460..dfd02bb1d3f 100644 --- a/tests/components/plex/test_services.py +++ b/tests/components/plex/test_services.py @@ -190,7 +190,11 @@ async def test_lookup_media_for_other_integrations( assert result.shuffle # Test with media not found - with patch("plexapi.library.LibrarySection.search", return_value=None): + with patch( + "plexapi.library.LibrarySection.search", + return_value=None, + __qualname__="search", + ): with pytest.raises(HomeAssistantError) as excinfo: process_plex_payload(hass, MediaType.MUSIC, CONTENT_ID_BAD_MEDIA) assert f"No {MediaType.MUSIC} results in 'Music' for" in str(excinfo.value)