from http import HTTPStatus as http_status from typing import List from unittest.mock import AsyncMock import pytest from server.client.clients.apollo_api import ApolloApiClient from server.client.clients.dsp_api import DspApiClient from server.client.clients.elastic_search import ElasticSearchClient def get_user_data(count: int = 5) -> List[dict]: return [ {"name": f"name{i}", "uri": f"uri{i}", "subscribers": 100 * i, "country_code": f"c{i}", "image": f"img{i}"} for i in range(1, count + 1) ] @pytest.mark.parametrize( "vendors,query,include_users", ( (["spotify"], "hits", False), (["apple"], "hits", False), (["spotify", "apple"], "hits", False), (["spotify", "apple", "amazon"], "hits", False), (["amazon"], "hits", False), (["spotify", "apple"], "hits", True), ) ) async def test_elasticsearch_v1_playlists_search(client, auth, mocker, vendors, query, include_users): params = {"vendor": vendors, "query": query, **({"include": "users"} if include_users else {})} # responses for spotify & apple elasticsearch are hardcoded just to check if API works as expected and the # length of response is correct # tests with response items checks will be added after discussion and solution for specifics of tests writing # especially for creation/fabrication of responses (to get rid of json files) for API(s) that are used # and for expected response to check for equality apple_elasticsearch_response = { "hits": { "hits": [ { "_index": "sony_filtr_admin_search", "_type": "sony_filtr_admin_search", "_id": "pl.6db5f7b47286460e9928d09d9ac0be69", "_score": 20.74635, "_source": { "playlistId": "pl.6db5f7b47286460e9928d09d9ac0be69", "name": "Top Hits Run", "artworkUrl": "", "updateDate": "2022-01-30T23:47:23Z", "buzzCategoryId": 11, "countryCode": "us", "streams56Days": 426379 } }, ] } } spotify_elasticsearch_response = { "hits": { "hits": [ { "_index": "sony_filtr_admin_search", "_type": "playlistindexitem", "_id": "spotify:playlist:1yQtBmz7oew3Wgurddxn5k", "_score": 0.0, "_source": { "playlistUri": "spotify:playlist:1yQtBmz7oew3Wgurddxn5k", "name": "Hot Hits 2021 – Global Chart Toppers by Filtr Arabia ", "description": "", "image": "playlist-1yQtBmz7oew3Wgurddxn5k.jpeg", "user": "filtrmiddleeast", "countryCode": "us", "duration": 23037, "trackCount": 120, "updateDate": "2021-12-27T07:04:50Z", "trackLatestAdded": "2021-08-20T04:54:16Z", "public": True, "followers": 0 } } ] } } amazon_elasticsearch_response = { "hits": { "total": 272, "max_score": None, "hits": [ { "_index": "sony_filtr_admin_search", "_type": "AmazonPlaylistIndexItem", "_id": "amazon_10_us", "_score": None, "_source": { "name": "The Top Hits 100 Most Played: Holiday", "playlistId": "amazon_10_us", "tracksNumber": 100, "countryCode": "us", "dspPlaylistId": 10, "amazonPlaylistId": "B07K2FVM3G", "imageUri": "https://m.media-amazon.com/images/I/71dXCV+0JhL.jpg" }, "sort": [ 10 ] } ] } } async def elasticsearch_send(url: str, *args, **kwargs): if url == "sony_filtr_admin_search/applemusicplaylistindexitem/_search": return apple_elasticsearch_response if url == "sony_filtr_admin_search/playlistindexitem/_search": return spotify_elasticsearch_response if url == "sony_filtr_admin_search/AmazonPlaylistIndexItem/_search": return amazon_elasticsearch_response apollo_async_mock = AsyncMock(return_value={"items": get_user_data()}) mocker.patch.object(ElasticSearchClient, "_send_request", side_effect=elasticsearch_send) mocker.patch.object(ApolloApiClient, "_send_request", side_effect=apollo_async_mock) async def dsp_mock(*args, **kwargs): pl_id = args[0].replace("api/delphi/public/playlists/spotify_", "") return {"is_personalised": True, "dsp_playlist_id": pl_id} mocker.patch.object(DspApiClient, "_send_request", side_effect=dsp_mock) response = await client.get("/api/v1/playlists/search/", headers=auth, params=params) assert response.status == http_status.OK response_json = await response.json() assert len(response_json["items"]) == len(vendors) assert apollo_async_mock.called == (1 if include_users else 0) if include_users: assert response_json["users"] == get_user_data()