import pytest import asyncio from copy import deepcopy from sqlalchemy import delete, update from server.dna.category.models import CategoryEntity from server.dna.utils import QueryWrapper from tests.constants import ( ARTIST_1343350, ARTIST_175179, TRACK_13692288, TRACK_13698092, CATEGORY_ARTIST_1343350_175179_ENTITY_EXPECTED_DATA, CATEGORY_TRACK_13698092_13692288_ENTITY_EXPECTED_DATA, UNAUTHORIZED, TEST_X_USER_ID_2, TEST_SLEEP_TIME, ) from server.dna.category.errors import HOMEPAGE_CATEGORY_EXISTS_ERR, FORBIDDEN_ERROR, NAME_IS_HOMEPAGE_CATEGORY_ERR from server.dna.constants import ARTIST, TRACK, LIKES, FOLLOWERS from server.artist.models import ArtistSearchData from server.track.models import TrackSearchData from tests.dna.category.constants import ( CATEGORY_FIELDS, CATEGORY_FIELDS_2, CATEGORY_FIELDS_ERR, CATEGORY_FIELDS_HOME, ARTIST_CATEGORY_ENTITY_1643771_RESPONSE_DATA, ARTIST_CATEGORY_ENTITY_SIGNED_NON_SIGNED_RESPONSE_DATA, ES_DATA_TO_INSERT, PG_DATA_TO_INSERT, TRACK_ES_DATA_TO_INSERT, TRACK_PG_DATA_TO_INSERT, TRACK_CATEGORY_ENTITY_13698092_RESPONSE_DATA, GET_ARTIST_CATEGORIES_URL, GET_TRACK_CATEGORIES_URL, EMPTY_CATEGORY_RESPONSE, CATEGORY_ARTIST_EXPECTED_RETURN_DATA, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA, CATEGORY_TRACK_EXPECTED_RETURN_DATA, CATEGORIES_TRACK_EXPECTED_RETURN_DATA, CATEGORY_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL, CATEGORY_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL_UPDATED, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL_UPDATED, CATEGORIES_ARTIST_TRACK_LONG_IDS_EXPECTED_RETURN_DATA, ) class TestCategories: @pytest.mark.parametrize( "expected_return_data, query_params", [(UNAUTHORIZED, {"ids": f"{ARTIST_1343350},{ARTIST_175179}"})], ) async def test_get_artist_categories_unauthorized( self, expected_return_data, query_params, postgres_client, app_client, auth_header ): response = await app_client.get(GET_ARTIST_CATEGORIES_URL, headers=auth_header, params=query_params) assert expected_return_data == await response.json() @pytest.mark.parametrize( "expected_return_data, expected_status, query_params", [ ( [ {"id": ARTIST_1343350, "categories": []}, {"id": ARTIST_175179, "categories": []}, ], 200, {"ids": f"{ARTIST_1343350},{ARTIST_175179}"}, ) ], ) async def test_get_artist_categories_empty_dict( self, expected_return_data, expected_status, query_params, postgres_client, app_client, auth_header_authorized ): response = await app_client.get(GET_ARTIST_CATEGORIES_URL, headers=auth_header_authorized, params=query_params) assert response.status == expected_status result = await response.json() assert expected_return_data == result @pytest.mark.parametrize( "url, expected_return_data, expected_status, query_params", [ ( "/api/dna/categories/art1k", {"entity_type": [f"Must be one of: {ARTIST}, {TRACK}."]}, 422, {"ids": f"{ARTIST_1343350}"}, ), (GET_ARTIST_CATEGORIES_URL, {"error": ["Wrong ids"]}, 422, {"ids": "undefined"}), (GET_ARTIST_CATEGORIES_URL, {"error": ["Wrong ids"]}, 422, {"ids": f"{ARTIST_1343350}, TEST"}), (GET_ARTIST_CATEGORIES_URL, {"ids": ["Missing data for required field."]}, 422, {}), ], ) async def test_get_artist_categories_validation_errors( self, url, expected_return_data, expected_status, query_params, postgres_client, app_client, auth_header_authorized, ): response = await app_client.get(url, headers=auth_header_authorized, params=query_params) assert response.status == expected_status result = await response.json() assert expected_return_data == result @pytest.mark.parametrize( "category_1, category_2, category_3, category_4, category_1343350_entity,\ category_175179_entity, status_code_created, expected_retrun_data, query_params,\ get_categories_url, elastic_client", [ ( {"is_homepage": False, "name": "category_1"}, {"is_homepage": False, "name": "category_2"}, {"is_homepage": False, "name": "category_3"}, {"is_homepage": False, "name": "category_4"}, {"entity_id": 1343350, "entity_type": ARTIST, "chart_type": LIKES}, {"entity_id": 175179, "entity_type": ARTIST, "chart_type": LIKES}, 201, CATEGORY_ARTIST_1343350_175179_ENTITY_EXPECTED_DATA, {"ids": f"{ARTIST_1343350},{ARTIST_175179}"}, GET_ARTIST_CATEGORIES_URL, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ( {"is_homepage": False, "name": "category_1"}, {"is_homepage": False, "name": "category_2"}, {"is_homepage": False, "name": "category_3"}, {"is_homepage": False, "name": "category_4"}, {"entity_id": 13698092, "entity_type": TRACK, "chart_type": LIKES}, {"entity_id": 13692288, "entity_type": TRACK, "chart_type": LIKES}, 201, CATEGORY_TRACK_13698092_13692288_ENTITY_EXPECTED_DATA, {"ids": f"{TRACK_13698092},{TRACK_13692288}"}, GET_TRACK_CATEGORIES_URL, (("track_search", deepcopy(TRACK_ES_DATA_TO_INSERT)),), ), ], indirect=["elastic_client"], ) async def test_get_artist_categories( self, category_1, category_2, category_3, category_4, category_1343350_entity, category_175179_entity, status_code_created, expected_retrun_data, query_params, get_categories_url, elastic_client, postgres_client, app_client, auth_header_authorized, ): response_1 = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_1) assert status_code_created == response_1.status cat_1 = await response_1.json() cat_id_1 = cat_1["id"] response_2 = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_2) assert status_code_created == response_2.status cat_2 = await response_2.json() cat_id_2 = cat_2["id"] response_3 = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_3) assert status_code_created == response_3.status cat_3 = await response_3.json() cat_id_3 = cat_3["id"] response_4 = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_4) assert status_code_created == response_4.status cat_4 = await response_4.json() cat_id_4 = cat_4["id"] response_cat_ent_1 = await app_client.post( f"/api/dna/categories/{cat_id_1}/entities", headers=auth_header_authorized, json=category_1343350_entity ) assert status_code_created == response_cat_ent_1.status response_cat_ent_2 = await app_client.post( f"/api/dna/categories/{cat_id_2}/entities", headers=auth_header_authorized, json=category_1343350_entity ) assert status_code_created == response_cat_ent_2.status response_cat_ent_3 = await app_client.post( f"/api/dna/categories/{cat_id_3}/entities", headers=auth_header_authorized, json=category_175179_entity ) assert status_code_created == response_cat_ent_3.status response_cat_ent_4 = await app_client.post( f"/api/dna/categories/{cat_id_4}/entities", headers=auth_header_authorized, json=category_175179_entity ) assert status_code_created == response_cat_ent_4.status response = await app_client.get(get_categories_url, headers=auth_header_authorized, params=query_params) res = await response.json() assert cat_id_1 == res[0]["categories"][0]["id"] assert cat_id_2 == res[0]["categories"][1]["id"] assert expected_retrun_data[0]["categories"][0]["name"] == res[0]["categories"][0]["name"] assert expected_retrun_data[0]["categories"][1]["name"] == res[0]["categories"][1]["name"] assert cat_id_3 == res[1]["categories"][0]["id"] assert cat_id_4 == res[1]["categories"][1]["id"] assert expected_retrun_data[1]["categories"][0]["name"] == res[1]["categories"][0]["name"] assert expected_retrun_data[1]["categories"][1]["name"] == res[1]["categories"][1]["name"] @pytest.mark.parametrize( "url, expected_return_data, http_method, request_body", [ ("/api/dna/categories", UNAUTHORIZED, "get", {}), ("/api/dna/categories/1", UNAUTHORIZED, "get", {}), ("/api/dna/categories", UNAUTHORIZED, "post", CATEGORY_FIELDS), ("/api/dna/categories/1", UNAUTHORIZED, "put", CATEGORY_FIELDS), ("/api/dna/categories/1", UNAUTHORIZED, "delete", {}), ], ) async def test_categories_endpoints_unauthorized( self, url, expected_return_data, http_method, request_body, postgres_client, app_client, auth_header ): request = getattr(app_client, http_method) response = await request(url, headers=auth_header, json=request_body) result = await response.json() assert expected_return_data == result @pytest.mark.parametrize( "url, expected_return_data, http_method, request_body", [ ("/api/dna/categories/1/entities", UNAUTHORIZED, "get", {}), ( "/api/dna/categories/1/entities", UNAUTHORIZED, "post", {"entity_type": TRACK, "entity_id": 123, "chart_type": LIKES}, ), ("/api/dna/categories/1/entities/123", UNAUTHORIZED, "delete", {}), ], ) async def test_categories_entities_endpoints_unauthorized( self, url, expected_return_data, http_method, request_body, postgres_client, app_client, auth_header ): request = getattr(app_client, http_method) response = await request(url, headers=auth_header, json=request_body) result = await response.json() assert expected_return_data == result @pytest.mark.parametrize( "request_body,expected_status_code", [ (CATEGORY_FIELDS_HOME, 201), (CATEGORY_FIELDS, 201), (CATEGORY_FIELDS_ERR, 422), ], ) async def test_create_category( self, request_body, expected_status_code, postgres_client, app_client, auth_header_authorized ): response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) assert expected_status_code == response.status @pytest.mark.parametrize( "category_body, entity_body_1, entity_body_2, expected_status_code, category_expected_return_data,\ categories_expected_return_data, elastic_client", [ ( {"is_homepage": False, "name": "category_1"}, {"entity_id": 1343350, "entity_type": ARTIST, "chart_type": LIKES}, {"entity_id": 175179, "entity_type": ARTIST, "chart_type": LIKES}, 201, CATEGORY_ARTIST_EXPECTED_RETURN_DATA, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ( {"is_homepage": False, "name": "category_1"}, {"entity_id": 13698092, "entity_type": TRACK, "chart_type": LIKES}, {"entity_id": 13692288, "entity_type": TRACK, "chart_type": LIKES}, 201, CATEGORY_TRACK_EXPECTED_RETURN_DATA, CATEGORIES_TRACK_EXPECTED_RETURN_DATA, (("track_search", deepcopy(TRACK_ES_DATA_TO_INSERT)),), ), ], indirect=["elastic_client"], ) async def test_get_categories( self, category_body, entity_body_1, entity_body_2, expected_status_code, category_expected_return_data, categories_expected_return_data, elastic_client, postgres_client, app_client, auth_header_authorized, ): response_cat = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_body) assert expected_status_code == response_cat.status cat_1 = await response_cat.json() cat_id_1 = cat_1["id"] response_category_entity_1 = await app_client.post( f"/api/dna/categories/{cat_id_1}/entities", headers=auth_header_authorized, json=entity_body_1 ) assert expected_status_code == response_category_entity_1.status response_category_entity_2 = await app_client.post( f"/api/dna/categories/{cat_id_1}/entities", headers=auth_header_authorized, json=entity_body_2 ) assert expected_status_code == response_category_entity_2.status response = await app_client.get(f"/api/dna/categories/{cat_id_1}", headers=auth_header_authorized) res = await response.json() issubset = category_expected_return_data.items() <= res.items() assert issubset is True response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) res = await response.json() issubset = categories_expected_return_data[0].items() <= res[0].items() assert issubset is True @pytest.mark.parametrize( "request_body, request_body_2, expected_status_code", [ (CATEGORY_FIELDS, CATEGORY_FIELDS_2, 400), ], ) async def test_create_category_unique_name_case_sensitive( self, request_body, request_body_2, expected_status_code, postgres_client, app_client, auth_header_authorized ): await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body_2) assert expected_status_code == response.status response = await response.json() assert response == {"error": "A category with this name already exists"} @pytest.mark.parametrize( "request_body, expected_status_code, expectected_result", [(CATEGORY_FIELDS, 400, {"error": "A category with this name already exists"})], ) async def test_create_category_error_same_name( self, request_body, expected_status_code, expectected_result, postgres_client, app_client, auth_header_authorized, ): await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) result = await response.json() assert expected_status_code == response.status assert expectected_result == result @pytest.mark.parametrize( "request_body, expected_status_code, expectected_result", [(CATEGORY_FIELDS_HOME, 400, {"error": HOMEPAGE_CATEGORY_EXISTS_ERR})], ) async def test_create_category_error_homepage( self, request_body, expected_status_code, expectected_result, postgres_client, app_client, auth_header_authorized, ): await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) result = await response.json() assert expected_status_code == response.status assert expectected_result == result @pytest.mark.parametrize( "request_body,expected_status_code, expected_return_data", [ (CATEGORY_FIELDS_HOME, 200, EMPTY_CATEGORY_RESPONSE), ], ) async def test_get_categories_flow( self, request_body, expected_status_code, expected_return_data, postgres_client, app_client, auth_header_authorized, ): response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.get(f"/api/dna/categories/{category_id}", headers=auth_header_authorized) assert response.status == expected_status_code response = await response.json() assert response["id"] == category_id assert response["name"] == CATEGORY_FIELDS_HOME.get("name") assert response["is_homepage"] == CATEGORY_FIELDS_HOME.get("is_homepage") assert response["counters"] == {"track": 0, "artist": 0} response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) response = await response.json() issubset = expected_return_data[0].items() <= response[0].items() assert issubset is True assert isinstance(response, list) assert len(response) == 1 assert response[0]["id"] == category_id @pytest.mark.parametrize( "request_body,expected_status_code", [ (CATEGORY_FIELDS_HOME, 200), ], ) async def test_edit_categories( self, request_body, expected_status_code, postgres_client, app_client, auth_header_authorized ): response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.put( f"/api/dna/categories/{category_id}", headers=auth_header_authorized, json={"name": "new_name"} ) assert response.status == expected_status_code response = await app_client.get(f"/api/dna/categories/{category_id}", headers=auth_header_authorized) response = await response.json() assert response["id"] == category_id assert response["name"] == "new_name" @pytest.mark.parametrize( "request_body, expected_status_code", [ (CATEGORY_FIELDS_HOME, 204), ], ) async def test_delete_categories( self, request_body, expected_status_code, postgres_client, app_client, auth_header_authorized ): response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=request_body) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.delete(f"/api/dna/categories/{category_id}", headers=auth_header_authorized) assert response.status == expected_status_code response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) response = await response.json() assert isinstance(response, list) assert len(response) == 0 @pytest.mark.parametrize( "resp_status, post_cat_ent_stat, result_len, entity_id,\ entity_type, chart_type, expected_return_data, elastic_client, aggregates_postgres_client", [ ( 200, 201, 1, 1643771, ARTIST, FOLLOWERS, ARTIST_CATEGORY_ENTITY_1643771_RESPONSE_DATA, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ((ArtistSearchData, deepcopy(PG_DATA_TO_INSERT)), (TrackSearchData, [])), ), ( 200, 422, 0, 1111111, ARTIST, None, [], (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ((ArtistSearchData, deepcopy(PG_DATA_TO_INSERT)), (TrackSearchData, [])), ), ( 200, 201, 1, 13698092, TRACK, LIKES, TRACK_CATEGORY_ENTITY_13698092_RESPONSE_DATA, (("track_search", deepcopy(TRACK_ES_DATA_TO_INSERT)),), ((ArtistSearchData, []), (TrackSearchData, TRACK_PG_DATA_TO_INSERT)), ), ( 200, 422, 0, 1111111, TRACK, None, [], (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ((ArtistSearchData, deepcopy(PG_DATA_TO_INSERT)), (TrackSearchData, [])), ), ], indirect=["elastic_client", "aggregates_postgres_client"], ) async def test_category_entity( self, resp_status, post_cat_ent_stat, result_len, entity_id, entity_type, chart_type, expected_return_data, postgres_client, aggregates_postgres_client, app_client, auth_header_authorized, elastic_client, ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS_HOME ) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.post( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == post_cat_ent_stat response = await app_client.get( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, ) assert resp_status == response.status res = await response.json() assert isinstance(res, list) assert len(res) == result_len if result_len > 0: issubset = expected_return_data[0].items() <= res[0].items() assert issubset is True @pytest.mark.parametrize( "resp_status, post_cat_ent_stat, result_len, entity_id,\ signed_entity_id, entity_type, chart_type, expected_return_data,\ elastic_client, aggregates_postgres_client", [ ( 200, 201, 2, 1643771, 1343350, ARTIST, FOLLOWERS, ARTIST_CATEGORY_ENTITY_SIGNED_NON_SIGNED_RESPONSE_DATA, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ((ArtistSearchData, deepcopy(PG_DATA_TO_INSERT)), (TrackSearchData, [])), ), ], indirect=["elastic_client", "aggregates_postgres_client"], ) async def test_category_entity_check_entity_is_signed( self, resp_status, post_cat_ent_stat, result_len, entity_id, signed_entity_id, entity_type, chart_type, expected_return_data, postgres_client, auth_header_authorized, elastic_client, aggregates_postgres_client, app_client, ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS_HOME ) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.post( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == post_cat_ent_stat response = await app_client.post( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, json={"entity_id": signed_entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == post_cat_ent_stat aggregates_postgres_client.execute(delete(ArtistSearchData).where(ArtistSearchData.id == str(signed_entity_id))) response = await app_client.get( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, ) assert resp_status == response.status res = await response.json() assert isinstance(res, list) assert len(res) == result_len if result_len > 0: issubset_1 = expected_return_data[0].items() <= res[0].items() issubset_2 = expected_return_data[1].items() <= res[1].items() assert issubset_1 is True assert issubset_2 is True @pytest.mark.parametrize( "created_status, err_status, entity_id, entity_type, chart_type, err_response", [ ( 201, 422, 759151, ARTIST, "give_me_chart", { "chart_type": [ "Must be one of: " + "likes, followers, views, subscribers, listeners, popularity, streams, monthly_listeners," + " plays, comments." ] }, ), (201, 422, 759151, ARTIST, 123, {"chart_type": ["Not a valid string."]}), (201, 422, 759151, ARTIST, None, {"chart_type": ["Field may not be null."]}), (201, 422, 759151, TRACK, "popularity", {"error": ["Wrong chart_type for entity_type track"]}), ( 201, 422, 759151, TRACK, "wrong_chart_type", { "chart_type": [ "Must be one of: " + "likes, followers, views, subscribers, listeners, popularity, streams, monthly_listeners," + " plays, comments." ] }, ), ], ) async def test_create_category_entity_errors( self, created_status, err_status, entity_id, entity_type, chart_type, err_response, postgres_client, app_client, auth_header_authorized, ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS_HOME ) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.post( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == err_status response = await response.json() assert response == err_response @pytest.mark.parametrize( "resp_status, entity_id, entity_type, chart_type, elastic_client", [ ( 201, 759151, ARTIST, LIKES, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ( 201, 13698092, TRACK, LIKES, (("track_search", deepcopy(TRACK_ES_DATA_TO_INSERT)),), ), ], indirect=["elastic_client"], ) async def test_delete_category_entity( self, resp_status, entity_id, entity_type, chart_type, elastic_client, postgres_client, app_client, auth_header_authorized, ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS_HOME ) assert response.status == resp_status response = await response.json() category_id = response.get("id") response = await app_client.post( f"/api/dna/categories/{category_id}/entities", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == resp_status response = await app_client.delete( f"/api/dna/categories/{category_id}/entities/{entity_id}", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type}, ) assert response.status == 204 @pytest.mark.parametrize( "created_status, forbidden_status, expected_result, http_method", [ (201, 403, FORBIDDEN_ERROR, "put"), (201, 403, FORBIDDEN_ERROR, "delete"), ], ) async def test_few_users_categories( self, created_status, forbidden_status, expected_result, http_method, postgres_client, app_client, auth_header_authorized, ): request = getattr(app_client, http_method) auth_header_authorized_2 = auth_header_authorized.copy() auth_header_authorized_2["X-User-Id"] = TEST_X_USER_ID_2 response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS) assert response.status == created_status response = await response.json() category_id_1 = response.get("id") response = await app_client.post("/api/dna/categories", headers=auth_header_authorized_2, json=CATEGORY_FIELDS) assert response.status == created_status response = await response.json() category_id_2 = response.get("id") # edit : response = await request( f"/api/dna/categories/{category_id_2}", headers=auth_header_authorized, json={"name": "new_name"} ) assert response.status == forbidden_status response = await response.json() assert response == expected_result response = await request( f"/api/dna/categories/{category_id_1}", headers=auth_header_authorized_2, json={"name": "new_name"} ) assert response.status == forbidden_status response = await response.json() assert response == expected_result @pytest.mark.parametrize( "expected_status, expected_result", [ (422, {"name": ["Longer than maximum length 255."]}), ], ) async def test_category_max_size_name( self, expected_status, expected_result, postgres_client, app_client, auth_header_authorized ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json={"name": "name" * 100} ) assert response.status == 422 response = await response.json() assert response == expected_result @pytest.mark.parametrize( "expected_status, request_body, expected_result", [ (422, {"is_homepage": False}, {"is_homepage": ["Must be one of: True."]}), (422, {"is_homepage": True, "name": "new test"}, {"error": [NAME_IS_HOMEPAGE_CATEGORY_ERR]}), ], ) async def test_category_edit_request_body_errors( self, expected_status, request_body, expected_result, postgres_client, app_client, auth_header_authorized ): response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS) assert response.status == 201 response = await response.json() category_id = response.get("id") response = await app_client.put( f"/api/dna/categories/{category_id}", headers=auth_header_authorized, json=request_body ) assert response.status == expected_status response = await response.json() assert response == expected_result @pytest.mark.parametrize( "resp_status, entity_id, entity_type, chart_type, elastic_client", [ ( 201, 759151, ARTIST, LIKES, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), (201, 13698092, TRACK, LIKES, (("track_search", deepcopy(TRACK_ES_DATA_TO_INSERT)),)), ], indirect=["elastic_client"], ) async def test_category_order_after_added_entity( self, resp_status, entity_id, entity_type, chart_type, elastic_client, postgres_client, app_client, auth_header_authorized, ): response = await app_client.post( "/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS_HOME ) assert response.status == resp_status response = await response.json() category_id_1 = response.get("id") response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=CATEGORY_FIELDS) assert response.status == resp_status response = await response.json() category_id_2 = response.get("id") response = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json={"name": "test_3"}) assert response.status == resp_status response = await response.json() category_id_3 = response.get("id") response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) response = await response.json() assert isinstance(response, list) assert len(response) == 3 assert response[0]["id"] == category_id_1 assert response[0]["is_homepage"] assert response[1]["id"] == category_id_3 assert response[2]["id"] == category_id_2 # add category_entity to category - it should change order of categories in category list response = await app_client.post( f"/api/dna/categories/{category_id_2}/entities", headers=auth_header_authorized, json={"entity_id": entity_id, "entity_type": entity_type, "chart_type": chart_type}, ) assert response.status == resp_status await asyncio.sleep(TEST_SLEEP_TIME) response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) response = await response.json() assert isinstance(response, list) assert len(response) == 3 # new correct order: assert response[0]["id"] == category_id_1 assert response[0]["is_homepage"] assert response[1]["id"] == category_id_2 assert response[2]["id"] == category_id_3 @pytest.mark.parametrize( "category_body, entity_body_1, entity_body_2, expected_status_code, category_expected_return_data,\ categories_expected_return_data, new_entity_id, category_expected_return_data_updated,\ categories_expected_return_data_updated, elastic_client", [ ( {"is_homepage": False, "name": "test_category"}, {"entity_id": 1343350, "entity_type": ARTIST, "chart_type": LIKES}, {"entity_id": 175179, "entity_type": ARTIST, "chart_type": LIKES}, 201, CATEGORY_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL, 1111111111, # non existing entity id in elastic CATEGORY_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL_UPDATED, CATEGORIES_ARTIST_EXPECTED_RETURN_DATA_IMAGE_URL_UPDATED, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ], indirect=["elastic_client"], ) async def test_get_categories_check_image_url( self, category_body, entity_body_1, entity_body_2, expected_status_code, category_expected_return_data, categories_expected_return_data, new_entity_id, category_expected_return_data_updated, categories_expected_return_data_updated, elastic_client, postgres_client, app_client, auth_header_authorized, ): """ The test checks that `image_url` field is returning for existing entity in elastic. For example, if the last entity in existing category become inavailable in elastic, the endpoint should return `image_url` for next entity from that category. """ response_cat = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_body) assert expected_status_code == response_cat.status cat_1 = await response_cat.json() cat_id_1 = cat_1["id"] response_category_entity_1 = await app_client.post( f"/api/dna/categories/{cat_id_1}/entities", headers=auth_header_authorized, json=entity_body_1 ) assert expected_status_code == response_category_entity_1.status response_category_entity_2 = await app_client.post( f"/api/dna/categories/{cat_id_1}/entities", headers=auth_header_authorized, json=entity_body_2 ) assert expected_status_code == response_category_entity_2.status response = await app_client.get(f"/api/dna/categories/{cat_id_1}", headers=auth_header_authorized) res = await response.json() issubset = category_expected_return_data.items() <= res.items() assert issubset is True response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) res = await response.json() issubset = categories_expected_return_data[0].items() <= res[0].items() assert issubset is True # Update the existing entity_id to non_existing to execute necessary flow category_entity = await response_category_entity_2.json() data = {"entity_id": new_entity_id} update_entity_id_query = update(CategoryEntity).values(**data).where(CategoryEntity.id == category_entity["id"]) await QueryWrapper.update(update_entity_id_query) response = await app_client.get(f"/api/dna/categories/{cat_id_1}", headers=auth_header_authorized) res = await response.json() issubset = category_expected_return_data_updated.items() <= res.items() assert issubset is True response = await app_client.get("/api/dna/categories", headers=auth_header_authorized) res = await response.json() issubset = categories_expected_return_data_updated[0].items() <= res[0].items() assert issubset is True @pytest.mark.parametrize( "category_body, expected_status_code, entity_type, artist_ids, expected_return_data, elastic_client", [ ( {"is_homepage": False, "name": "category_1"}, 201, ARTIST, "1111111111111,222222222222", # long ids CATEGORIES_ARTIST_TRACK_LONG_IDS_EXPECTED_RETURN_DATA, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ( {"is_homepage": False, "name": "category_2"}, 201, TRACK, "1111111111111,222222222222", # long ids CATEGORIES_ARTIST_TRACK_LONG_IDS_EXPECTED_RETURN_DATA, (("artist_search", deepcopy(ES_DATA_TO_INSERT)),), ), ], indirect=["elastic_client"], ) async def test_get_categories_entities_ids_check_big_integers( self, category_body, expected_status_code, entity_type, artist_ids, expected_return_data, elastic_client, app_client, auth_header_authorized, ): response_cat = await app_client.post("/api/dna/categories", headers=auth_header_authorized, json=category_body) assert expected_status_code == response_cat.status response = await app_client.get( f"/api/dna/categories/{entity_type}?ids={artist_ids}", headers=auth_header_authorized ) assert expected_return_data == await response.json()