async def test_literal(aresponses: ResponsesMockServer) -> None: """Test literal is handled correctly.""" aresponses.add( MATCH_HOST, "/keypress/Lit_t", "POST", aresponses.Response(status=200), ) aresponses.add( MATCH_HOST, "/keypress/Lit_h", "POST", aresponses.Response(status=200), ) aresponses.add( MATCH_HOST, "/keypress/Lit_e", "POST", aresponses.Response(status=200), ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.literal("the")
async def test_get_dns_state( aresponses: ResponsesMockServer, resolver: AsyncMock, freezer, ) -> None: """Test get_dns_state is handled correctly.""" aresponses.add( f"192.168.1.99:{PORT}", "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) aresponses.add( f"192.168.1.89:{PORT}", "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: roku = Roku(HOST, session=session) assert roku.get_dns_state() == { "enabled": False, "hostname": None, "ip_address": None, "resolved_at": None, } roku2 = Roku("roku.dev", session=session) assert roku2.get_dns_state() == { "enabled": True, "hostname": "roku.dev", "ip_address": None, "resolved_at": None, } resolver.return_value = fake_addrinfo_results(["192.168.1.99"]) assert await roku2._request("support/hostname") dns = roku2.get_dns_state() assert dns["enabled"] assert dns["hostname"] == "roku.dev" assert dns["ip_address"] == "192.168.1.99" assert dns["resolved_at"] == datetime(2022, 3, 27, 0, 0) resolver.return_value = fake_addrinfo_results(["192.168.1.89"]) freezer.tick(delta=timedelta(hours=3)) assert await roku2._request("support/hostname") dns = roku2.get_dns_state() assert dns["enabled"] assert dns["hostname"] == "roku.dev" assert dns["ip_address"] == "192.168.1.89" assert dns["resolved_at"] == datetime(2022, 3, 27, 3, 0)
async def test_batch_get_partial_failure( aresponses: ResponsesMockServer, context: Dict[str, Any], query_paths: List[str], db_movies: List[Movie], json_movies: List[Dict[str, Any]], movie_keys: List[int], mocker: MockFixture, ): from movies.core.dataloaders import movie_loader mocker.patch.object(movie_loader.crud, "get_movies").return_value = db_movies # The request for movie_id=2 will fail with a 500. aresponses.add(TMDB_API_HOST, query_paths[0], "GET", response=json_movies[0]) aresponses.add(TMDB_API_HOST, query_paths[1], "GET", aresponses.Response(status=500)) aresponses.add(TMDB_API_HOST, query_paths[2], "GET", response=json_movies[2]) movie_loader = MovieLoader.for_context(context) movies = await movie_loader.load_many(movie_keys) assert movies == [ EntityMovie(**json_movies[0]), None, EntityMovie(**json_movies[2]), ]
async def test_make_request(self, aresponses: ResponsesMockServer): aresponses.add( aresponses.ANY, "/bot42:TEST/method", "post", aresponses.Response( status=200, text='{"ok": true, "result": 42}', headers={"Content-Type": "application/json"}, ), ) session = AiohttpSession() class TestMethod(TelegramMethod[int]): __returning__ = int def build_request(self) -> Request: return Request(method="method", data={}) call = TestMethod() with patch( "aiogram.api.client.session.base.BaseSession.raise_for_status" ) as patched_raise_for_status: result = await session.make_request("42:TEST", call) assert isinstance(result, int) assert result == 42 assert patched_raise_for_status.called_once()
async def test_resolve_rate_tmdb_exception(aresponses: ResponsesMockServer): aresponses.add(TMDB_API_HOST, URL_PATH, "POST", aresponses.Response(status=500)) with pytest.raises(HTTPException): await resolve_rate(movie_id=MOVIE_ID, rating=10.0) aresponses.assert_plan_strictly_followed()
async def test_device(aresponses: ResponsesMockServer) -> None: """Test app property is handled correctly.""" aresponses.add( MATCH_HOST, "/query/device-info", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("device-info.xml"), ), ) aresponses.add( MATCH_HOST, "/query/apps", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("apps.xml"), ), ) aresponses.add( MATCH_HOST, "/query/active-app", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("active-app-roku.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) await client.update() assert client.device assert isinstance(client.device, models.Device)
async def test_resolve_hostname( aresponses: ResponsesMockServer, resolver: AsyncMock, freezer, ) -> None: """Test that hostnames are resolved before request.""" resolver.return_value = fake_addrinfo_results([HOST]) aresponses.add( MATCH_HOST, "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) aresponses.add( f"192.168.1.68:{PORT}", "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: client = Roku(HOSTNAME, session=session) assert await client._request("support/hostname") dns = client.get_dns_state() assert dns["enabled"] assert dns["hostname"] == HOSTNAME assert dns["ip_address"] == HOST assert dns["resolved_at"] == datetime(2022, 3, 27, 0, 0) freezer.tick(delta=timedelta(hours=3)) resolver.return_value = fake_addrinfo_results(["192.168.1.68"]) assert await client._request("support/hostname") dns = client.get_dns_state() assert dns["enabled"] assert dns["hostname"] == HOSTNAME assert dns["ip_address"] == "192.168.1.68" assert dns["resolved_at"] == datetime(2022, 3, 27, 3, 0)
async def test_launch(aresponses: ResponsesMockServer) -> None: """Test launch is handled correctly.""" aresponses.add( MATCH_HOST, "/launch/101", "POST", aresponses.Response(status=200), ) aresponses.add( MATCH_HOST, "/launch/102?contentID=deeplink", "POST", aresponses.Response(status=200), match_querystring=True, ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.launch("101") await roku.launch("102", {"contentID": "deeplink"})
async def test_remote_search(aresponses: ResponsesMockServer) -> None: """Test remote search keypress is handled correctly.""" aresponses.add( MATCH_HOST, "/search/browse", "POST", aresponses.Response(status=200), ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.remote("search")
async def test_text_request(aresponses: ResponsesMockServer) -> None: """Test non XML response is handled correctly.""" aresponses.add( MATCH_HOST, "/response/text", "GET", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: client = Roku(HOST, session=session) response = await client._request("response/text") assert response == "OK"
async def test_update_power_off(aresponses: ResponsesMockServer) -> None: """Test update method is handled correctly when power is off.""" aresponses.add( MATCH_HOST, "/query/device-info", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("device-info-power-off.xml"), ), ) aresponses.add( MATCH_HOST, "/query/apps", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("apps.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) response = await client.update() assert response assert isinstance(response.info, models.Info) assert isinstance(response.state, models.State) assert isinstance(response.apps, list) assert isinstance(response.channels, list) assert response.app is None assert response.channel is None assert response.media is None assert response.state.available assert response.state.standby assert len(response.channels) == 0
async def test_search(aresponses: ResponsesMockServer) -> None: """Test search is handled correctly.""" aresponses.add( MATCH_HOST, "/search/browse?keyword=test", "POST", aresponses.Response(status=200, text="OK"), match_querystring=True, ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.search("test")
async def test_http_error500(aresponses: ResponsesMockServer) -> None: """Test HTTP 500 response handling.""" aresponses.add( MATCH_HOST, "/http/500", "GET", aresponses.Response(text="Internal Server Error", status=500), ) async with ClientSession() as session: client = Roku(HOST, session=session) with pytest.raises(RokuError): assert await client._request("http/500")
async def test_request_port(aresponses: ResponsesMockServer) -> None: """Test the handling of non-standard API port.""" aresponses.add( f"{HOST}:{NON_STANDARD_PORT}", "/support/port", "GET", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: client = Roku(host=HOST, port=NON_STANDARD_PORT, session=session) response = await client._request("support/port") assert response == "OK"
async def test_http_error404(aresponses: ResponsesMockServer) -> None: """Test HTTP 404 response handling.""" aresponses.add( MATCH_HOST, "/http/404", "GET", aresponses.Response(text="Not Found!", status=404), ) async with ClientSession() as session: client = Roku(HOST, session=session) with pytest.raises(RokuError): assert await client._request("http/404")
async def test_tune(aresponses: ResponsesMockServer) -> None: """Test tune is handled correctly.""" aresponses.add( MATCH_HOST, "/launch/tvinput.dtv?ch=13.4", "POST", aresponses.Response(status=200, text="OK"), match_querystring=True, ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.tune("13.4")
async def test_post_request(aresponses: ResponsesMockServer) -> None: """Test POST requests are handled correctly.""" aresponses.add( MATCH_HOST, "/method/post", "POST", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: client = Roku(HOST, session=session) response = await client._request("method/post", method="POST") assert response == "OK"
async def test_resolve_hostname_multiple_clients( aresponses: ResponsesMockServer, resolver: AsyncMock) -> None: """Test that hostnames are resolved before request with multiple clients.""" aresponses.add( MATCH_HOST, "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) aresponses.add( f"192.168.1.99:{PORT}", "/support/hostname", "GET", aresponses.Response(status=200, text="OK"), ) async with ClientSession() as session: resolver.return_value = fake_addrinfo_results([HOST]) client = Roku(HOSTNAME, session=session) assert await client._request("support/hostname") dns = client.get_dns_state() assert dns["enabled"] assert dns["hostname"] == HOSTNAME assert dns["ip_address"] == HOST assert dns["resolved_at"] == datetime(2022, 3, 27, 0, 0) resolver.return_value = fake_addrinfo_results(["192.168.1.99"]) client2 = Roku("roku.dev", session=session) assert await client2._request("support/hostname") dns2 = client2.get_dns_state() assert dns2["enabled"] assert dns2["hostname"] == "roku.dev" assert dns2["ip_address"] == "192.168.1.99" assert dns2["resolved_at"] == datetime(2022, 3, 27, 0, 0)
async def test_get_media_state_play(aresponses: ResponsesMockServer) -> None: """Test _get_media_state method is handled correctly with playing media.""" aresponses.add( MATCH_HOST, "/query/media-player", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("media-player-pluto-play.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) assert await client._get_media_state()
async def test_get_active_app(aresponses: ResponsesMockServer) -> None: """Test _get_active_app method is handled correctly.""" aresponses.add( MATCH_HOST, "/query/active-app", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("active-app-amazon.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) assert await client._get_active_app()
async def test_play_on_roku(aresponses: ResponsesMockServer) -> None: """Test play_on_roku is handled correctly.""" video_url = "http://example.com/video file÷awe.mp4?v=2" encoded = "http%3A%2F%2Fexample.com%2Fvideo+file%C3%B7awe.mp4%3Fv%3D2" aresponses.add( MATCH_HOST, f"/input/15985?t=v&u={encoded}", "POST", aresponses.Response(status=200), match_querystring=True, ) async with ClientSession() as session: roku = Roku(HOST, session=session) await roku.play_on_roku(video_url)
async def test_get_tv_channels(aresponses: ResponsesMockServer) -> None: """Test _get_tv_channels method is handled correctly.""" aresponses.add( MATCH_HOST, "/query/tv-channels", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text="<other>value</other>", ), ) async with ClientSession() as session: client = Roku(HOST, session=session) with pytest.raises(RokuError): assert await client._get_tv_channels()
async def test_internal_session(aresponses: ResponsesMockServer) -> None: """Test JSON response is handled correctly with internal session.""" aresponses.add( MATCH_HOST, "/response/xml", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text="<status>OK</status>", ), ) async with Roku(HOST) as client: response = await client._request("response/xml") assert isinstance(response, dict) assert response["status"] == "OK"
async def test_get_apps_single_app(aresponses: ResponsesMockServer) -> None: """Test _get_apps method is handled correctly with single app.""" aresponses.add( MATCH_HOST, "/query/apps", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("apps-single.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) res = await client._get_apps() assert isinstance(res, list) assert len(res) == 1
async def test_xml_request_parse_error( aresponses: ResponsesMockServer) -> None: """Test invalid XML response is handled correctly.""" aresponses.add( MATCH_HOST, "/response/xml-parse-error", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text="<!status>>", ), ) async with ClientSession() as session: client = Roku(HOST, session=session) with pytest.raises(RokuError): assert await client._request("response/xml-parse-error")
async def test_text_xml_request(aresponses: ResponsesMockServer) -> None: """Test (text) XML response is handled correctly.""" aresponses.add( MATCH_HOST, "/response/text-xml", "GET", aresponses.Response( status=200, headers={"Content-Type": "text/xml"}, text="<status>OK</status>", ), ) async with ClientSession() as session: client = Roku(HOST, session=session) response = await client._request("response/text-xml") assert isinstance(response, dict) assert response["status"] == "OK"
async def test_get_tv_channels_no_channels( aresponses: ResponsesMockServer) -> None: """Test _get_tv_channels method is handled correctly with no channels.""" aresponses.add( MATCH_HOST, "/query/tv-channels", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("tv-channels-empty.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) res = await client._get_tv_channels() assert isinstance(res, list) assert len(res) == 0
async def test_stream_content(self, aresponses: ResponsesMockServer): aresponses.add( aresponses.ANY, aresponses.ANY, "get", aresponses.Response(status=200, body=b"\f" * 10), ) session = AiohttpSession() stream = session.stream_content( "https://www.python.org/static/img/python-logo.png", timeout=5, chunk_size=1) assert isinstance(stream, AsyncGenerator) size = 0 async for chunk in stream: assert isinstance(chunk, bytes) chunk_size = len(chunk) assert chunk_size == 1 size += chunk_size assert size == 10
async def test_batch_get_partial_failure( aresponses: ResponsesMockServer, context: Dict[str, Any], query_paths: List[str], json_companies: List[Dict[str, Any]], company_keys: List[int], ): # The request for company_id=2 will fail with a 500. aresponses.add(TMDB_API_HOST, query_paths[0], "GET", response=json_companies[0]) aresponses.add( TMDB_API_HOST, query_paths[1], "GET", aresponses.Response(status=500) ) aresponses.add(TMDB_API_HOST, query_paths[2], "GET", response=json_companies[2]) company_loader = CompanyLoader.for_context(context) companies = await company_loader.load_many(company_keys) assert companies == [ Company(**json_companies[0]), None, Company(**json_companies[2]), ] aresponses.assert_plan_strictly_followed()
async def test_update_tv(aresponses: ResponsesMockServer) -> None: """Test update method is handled correctly for TVs.""" for _ in range(0, 2): aresponses.add( MATCH_HOST, "/query/device-info", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("device-info-7820x.xml"), ), ) aresponses.add( MATCH_HOST, "/query/apps", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("apps-tv.xml"), ), ) aresponses.add( MATCH_HOST, "/query/active-app", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("active-app-tv.xml"), ), ) aresponses.add( MATCH_HOST, "/query/tv-active-channel", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("tv-active-channel.xml"), ), ) aresponses.add( MATCH_HOST, "/query/tv-channels", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("tv-channels.xml"), ), ) aresponses.add( MATCH_HOST, "/query/tv-channels", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/xml"}, text=load_fixture("tv-channels-single.xml"), ), ) async with ClientSession() as session: client = Roku(HOST, session=session) response = await client.update() assert response assert isinstance(response.info, models.Info) assert isinstance(response.state, models.State) assert isinstance(response.apps, list) assert isinstance(response.channels, list) assert isinstance(response.app, models.Application) assert isinstance(response.channel, models.Channel) assert response.media is None assert response.state.available assert not response.state.standby assert len(response.channels) == 2 response = await client.update(True) assert response assert isinstance(response.info, models.Info) assert isinstance(response.state, models.State) assert isinstance(response.apps, list) assert isinstance(response.channels, list) assert isinstance(response.app, models.Application) assert isinstance(response.channel, models.Channel) assert response.media is None assert response.state.available assert not response.state.standby assert len(response.channels) == 1