from datetime import datetime as dt from datetime import timezone import pytest from conftest import DB, Response from hircine.db.models import Artist @pytest.fixture def query_artist(execute_id): query = """ query artist($id: Int!) { artist(id: $id) { __typename ... on Artist { id name } ... on Error { message } ... on IDNotFoundError { id } } } """ return execute_id(query) @pytest.fixture def query_artists(execute): query = """ query artists { artists { __typename count edges { id name } } } """ return execute(query) @pytest.fixture def add_artist(execute_add): mutation = """ mutation addArtist($input: AddArtistInput!) { addArtist(input: $input) { __typename ... on AddSuccess { id } ... on Error { message } ... on InvalidParameterError { parameter } } } """ return execute_add(mutation) @pytest.fixture def update_artists(execute_update): mutation = """ mutation updateArtists($ids: [Int!]!, $input: UpdateArtistInput!) { updateArtists(ids: $ids, input: $input) { __typename ... on Success { message } ... on Error { message } ... on IDNotFoundError { id } ... on InvalidParameterError { parameter } } } """ # noqa: E501 return execute_update(mutation) @pytest.fixture def delete_artists(execute_delete): mutation = """ mutation deleteArtists($ids: [Int!]!) { deleteArtists(ids: $ids) { __typename ... on Success { message } ... on Error { message } ... on IDNotFoundError { id } } } """ return execute_delete(mutation) @pytest.mark.anyio async def test_query_artist(query_artist, gen_artist): artist = await DB.add(next(gen_artist)) response = Response(await query_artist(artist.id)) response.assert_is("Artist") assert response.id == artist.id assert response.name == artist.name @pytest.mark.anyio async def test_query_artist_fails_not_found(query_artist): response = Response(await query_artist(1)) response.assert_is("IDNotFoundError") assert response.id == 1 assert response.message == "Artist ID not found: '1'" @pytest.mark.anyio async def test_query_artists(query_artists, gen_artist): artists = await DB.add_all(*gen_artist) response = Response(await query_artists()) response.assert_is("ArtistFilterResult") assert response.count == len(artists) assert isinstance((response.edges), list) assert len(response.edges) == len(artists) edges = iter(response.edges) for artist in sorted(artists, key=lambda a: a.name): edge = next(edges) assert edge["id"] == artist.id assert edge["name"] == artist.name @pytest.mark.anyio async def test_add_artist(add_artist): response = Response(await add_artist({"name": "added artist"})) response.assert_is("AddSuccess") artist = await DB.get(Artist, response.id) assert artist is not None assert artist.name == "added artist" @pytest.mark.anyio async def test_add_artist_fails_empty_parameter(add_artist): response = Response(await add_artist({"name": ""})) response.assert_is("InvalidParameterError") assert response.parameter == "name" assert response.message == "Invalid parameter 'name': cannot be empty" @pytest.mark.anyio async def test_add_artist_fails_exists(add_artist, gen_artist): artist = await DB.add(next(gen_artist)) response = Response(await add_artist({"name": artist.name})) response.assert_is("NameExistsError") assert response.message == "Another Artist with this name exists" @pytest.mark.anyio async def test_delete_artist(delete_artists, gen_artist): artist = await DB.add(next(gen_artist)) id = artist.id response = Response(await delete_artists(id)) response.assert_is("DeleteSuccess") artist = await DB.get(Artist, id) assert artist is None @pytest.mark.anyio async def test_delete_artist_not_found(delete_artists): response = Response(await delete_artists(1)) response.assert_is("IDNotFoundError") assert response.id == 1 assert response.message == "Artist ID not found: '1'" @pytest.mark.anyio async def test_update_artist(update_artists, gen_artist): artist = await DB.add(next(gen_artist)) input = {"name": "updated artist"} response = Response(await update_artists(artist.id, input)) response.assert_is("UpdateSuccess") artist = await DB.get(Artist, artist.id) assert artist is not None assert artist.name == "updated artist" @pytest.mark.anyio async def test_update_artist_fails_exists(update_artists, gen_artist): first = await DB.add(next(gen_artist)) second = await DB.add(next(gen_artist)) response = Response(await update_artists(second.id, {"name": first.name})) response.assert_is("NameExistsError") assert response.message == "Another Artist with this name exists" @pytest.mark.anyio async def test_update_artist_fails_not_found(update_artists): response = Response(await update_artists(1, {"name": "updated artist"})) response.assert_is("IDNotFoundError") assert response.id == 1 assert response.message == "Artist ID not found: '1'" @pytest.mark.anyio async def test_update_artists_cannot_bulk_edit_name(update_artists, gen_artist): first = await DB.add(next(gen_artist)) second = await DB.add(next(gen_artist)) response = Response(await update_artists([first.id, second.id], {"name": "unique"})) response.assert_is("InvalidParameterError") @pytest.mark.parametrize( "empty", [ None, "", ], ids=[ "none", "empty string", ], ) @pytest.mark.anyio async def test_update_artist_fails_empty_parameter(update_artists, gen_artist, empty): artist = await DB.add(next(gen_artist)) response = Response(await update_artists(artist.id, {"name": empty})) response.assert_is("InvalidParameterError") assert response.parameter == "name" assert response.message == "Invalid parameter 'name': cannot be empty" @pytest.mark.anyio async def test_update_artist_changes_updated_at(update_artists): original_artist = Artist(name="artist") original_artist.updated_at = dt(2023, 1, 1, tzinfo=timezone.utc) original_artist = await DB.add(original_artist) response = Response(await update_artists(original_artist.id, {"name": "updated"})) response.assert_is("UpdateSuccess") artist = await DB.get(Artist, original_artist.id) assert artist.updated_at > original_artist.updated_at