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