diff options
Diffstat (limited to '')
-rw-r--r-- | tests/api/test_archive.py | 7 | ||||
-rw-r--r-- | tests/api/test_artist.py | 1 | ||||
-rw-r--r-- | tests/api/test_character.py | 1 | ||||
-rw-r--r-- | tests/api/test_circle.py | 1 | ||||
-rw-r--r-- | tests/api/test_comic.py | 13 | ||||
-rw-r--r-- | tests/api/test_comic_tag.py | 1 | ||||
-rw-r--r-- | tests/api/test_db.py | 23 | ||||
-rw-r--r-- | tests/api/test_filter.py | 100 | ||||
-rw-r--r-- | tests/api/test_image.py | 1 | ||||
-rw-r--r-- | tests/api/test_namespace.py | 1 | ||||
-rw-r--r-- | tests/api/test_page.py | 1 | ||||
-rw-r--r-- | tests/api/test_scraper_api.py | 5 | ||||
-rw-r--r-- | tests/api/test_sort.py | 79 | ||||
-rw-r--r-- | tests/api/test_statistics.py | 106 | ||||
-rw-r--r-- | tests/api/test_tag.py | 1 | ||||
-rw-r--r-- | tests/api/test_world.py | 1 |
16 files changed, 296 insertions, 46 deletions
diff --git a/tests/api/test_archive.py b/tests/api/test_archive.py index 0ef3425..6e6d0b7 100644 --- a/tests/api/test_archive.py +++ b/tests/api/test_archive.py @@ -2,13 +2,14 @@ import os from datetime import datetime as dt from pathlib import Path +import pytest +from conftest import DB, Response +from sqlalchemy import select + import hircine.config import hircine.db as database import hircine.thumbnailer as thumb -import pytest -from conftest import DB, Response from hircine.db.models import Archive, Comic, Image, Page -from sqlalchemy import select @pytest.fixture diff --git a/tests/api/test_artist.py b/tests/api/test_artist.py index 8cb2f1a..fa58012 100644 --- a/tests/api/test_artist.py +++ b/tests/api/test_artist.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import Artist diff --git a/tests/api/test_character.py b/tests/api/test_character.py index 567d2a4..3737d49 100644 --- a/tests/api/test_character.py +++ b/tests/api/test_character.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import Character diff --git a/tests/api/test_circle.py b/tests/api/test_circle.py index a03ba89..bea46d7 100644 --- a/tests/api/test_circle.py +++ b/tests/api/test_circle.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import Circle diff --git a/tests/api/test_comic.py b/tests/api/test_comic.py index d3fa51e..dcc5822 100644 --- a/tests/api/test_comic.py +++ b/tests/api/test_comic.py @@ -3,6 +3,7 @@ from datetime import datetime as dt import pytest from conftest import DB, Response + from hircine.db.models import ( Artist, Circle, @@ -1096,7 +1097,7 @@ async def test_upsert_comic_tags_uses_existing(upsert_comics, empty_comic): @pytest.mark.parametrize( - "key,list", + "key,items", [ ("artists", ["arty", "farty"]), ("tags", ["alien:medium", "human:tiny"]), @@ -1115,11 +1116,11 @@ async def test_upsert_comic_tags_uses_existing(upsert_comics, empty_comic): ], ) @pytest.mark.anyio -async def test_upsert_comic_creates(upsert_comics, empty_comic, key, list): +async def test_upsert_comic_creates(upsert_comics, empty_comic, key, items): original_comic = await DB.add(empty_comic) input = { - key: {"names": list, "options": {"onMissing": "CREATE"}}, + key: {"names": items, "options": {"onMissing": "CREATE"}}, } response = Response(await upsert_comics(original_comic.id, input)) response.assert_is("UpsertSuccess") @@ -1127,7 +1128,7 @@ async def test_upsert_comic_creates(upsert_comics, empty_comic, key, list): comic = await DB.get(Comic, original_comic.id, full=True) assert comic is not None - assert set(list) == set([o.name for o in getattr(comic, key)]) + assert set(items) == set([o.name for o in getattr(comic, key)]) @pytest.mark.anyio @@ -1184,7 +1185,9 @@ async def test_upsert_comic_fails_creating_invalid_tag(upsert_comics, gen_comic, response = Response(await upsert_comics(comic.id, input)) response.assert_is("InvalidParameterError") assert response.parameter == "name" - msg = "Invalid parameter 'name': ComicTag name must be specified as <namespace>:<tag>" # noqa: E501 + msg = ( + "Invalid parameter 'name': ComicTag name must be specified as <namespace>:<tag>" + ) assert response.message == msg diff --git a/tests/api/test_comic_tag.py b/tests/api/test_comic_tag.py index f536b79..d0878e2 100644 --- a/tests/api/test_comic_tag.py +++ b/tests/api/test_comic_tag.py @@ -2,6 +2,7 @@ from functools import partial import pytest from conftest import DB, Response + from hircine.db.models import Namespace, Tag diff --git a/tests/api/test_db.py b/tests/api/test_db.py index f53b90f..b030035 100644 --- a/tests/api/test_db.py +++ b/tests/api/test_db.py @@ -1,10 +1,16 @@ from datetime import datetime, timedelta, timezone +import pytest +from conftest import DB +from sqlalchemy.exc import StatementError +from sqlalchemy.orm import ( + Mapped, + mapped_column, +) + import hircine.db as database import hircine.db.models as models import hircine.db.ops as ops -import pytest -from conftest import DB from hircine.db.models import ( Artist, Base, @@ -16,11 +22,6 @@ from hircine.db.models import ( Tag, TagNamespaces, ) -from sqlalchemy.exc import StatementError -from sqlalchemy.orm import ( - Mapped, - mapped_column, -) class Date(MixinID, Base): @@ -66,8 +67,8 @@ async def test_models_retained_when_clearing_association( comic = await DB.add(comic) async with database.session() as s: - object = await s.get(Comic, comic.id) - setattr(object, key, []) + obj = await s.get(Comic, comic.id) + setattr(obj, key, []) await s.commit() assert await DB.get(assoccls, (comic.id, model.id)) is None @@ -86,8 +87,8 @@ async def test_models_retained_when_clearing_comictag(empty_comic): await DB.add(ct) async with database.session() as s: - object = await s.get(Comic, comic.id) - object.tags = [] + obj = await s.get(Comic, comic.id) + obj.tags = [] await s.commit() assert await DB.get(ComicTag, (comic.id, ct.namespace_id, ct.tag_id)) is None diff --git a/tests/api/test_filter.py b/tests/api/test_filter.py index 67a953f..6eb2934 100644 --- a/tests/api/test_filter.py +++ b/tests/api/test_filter.py @@ -1,5 +1,6 @@ import pytest from conftest import DB, Response + from hircine.db.models import Namespace, Tag @@ -420,51 +421,59 @@ async def test_field_presence(query_comic_filter, gen_comic, empty_comic, filter "filter,ids", [ ( - {"include": {"artists": {"empty": True}}}, + {"include": {"artists": {"count": {"value": 0}}}}, [100], ), ( - {"include": {"artists": {"empty": False}}}, - [1, 2], + {"include": {"artists": {"count": {"value": 0, "operator": "EQUAL"}}}}, + [100], ), ( - {"exclude": {"artists": {"empty": True}}}, - [1, 2], + { + "include": { + "artists": {"count": {"value": 1, "operator": "GREATER_THAN"}} + } + }, + [1], ), ( - {"exclude": {"artists": {"empty": False}}}, - [100], + {"include": {"artists": {"count": {"value": 3, "operator": "LOWER_THAN"}}}}, + [1, 2, 100], ), ( - {"include": {"tags": {"empty": True}}}, - [100], + {"exclude": {"artists": {"count": {"value": 0}}}}, + [1, 2], ), ( - {"include": {"tags": {"empty": False}}}, + {"exclude": {"artists": {"count": {"value": 0, "operator": "EQUAL"}}}}, [1, 2], ), ( - {"exclude": {"tags": {"empty": True}}}, - [1, 2], + { + "exclude": { + "artists": {"count": {"value": 1, "operator": "GREATER_THAN"}} + } + }, + [2, 100], ), ( - {"exclude": {"tags": {"empty": False}}}, - [100], + {"exclude": {"artists": {"count": {"value": 3, "operator": "LOWER_THAN"}}}}, + [], ), ], ids=[ - "includes artist empty", - "includes artist not empty", - "excludes artist empty", - "excludes artist not empty", - "includes tags empty", - "includes tags not empty", - "excludes tags empty", - "excludes tags not empty", + "include equal (default)", + "include equal (explicit)", + "include greater than", + "include lower than", + "exclude equal (default)", + "exclude equal (explicit)", + "exclude greater than", + "exclude lower than", ], ) @pytest.mark.anyio -async def test_assoc_presence(query_comic_filter, gen_comic, empty_comic, filter, ids): +async def test_assoc_counts(query_comic_filter, gen_comic, empty_comic, filter, ids): await DB.add(next(gen_comic)) await DB.add(next(gen_comic)) await DB.add(empty_comic) @@ -519,3 +528,48 @@ async def test_tag_assoc_filter(query_tag_filter, gen_namespace, gen_tag, filter response.assert_is("TagFilterResult") assert id_list(response.edges) == ids + + +@pytest.mark.parametrize( + "filter,expect", + [ + ({"include": {"comics": {"count": {"value": 1}}}}, [2, 3]), + ({"include": {"comics": {"count": {"value": 2, "operator": "EQUAL"}}}}, [1, 4]), + ( + { + "include": { + "comics": {"count": {"value": 3, "operator": "GREATER_THAN"}} + } + }, + [], + ), + ( + {"include": {"comics": {"count": {"value": 2, "operator": "LOWER_THAN"}}}}, + [2, 3], + ), + ( + {"exclude": {"comics": {"count": {"value": 1}}}}, + [1, 4], + ), + ( + {"exclude": {"comics": {"count": {"value": 1, "operator": "LOWER_THAN"}}}}, + [1, 2, 3, 4], + ), + ], + ids=[ + "include equal (default)", + "include equal (explicit)", + "include greater than", + "include lower than", + "exclude equal (default)", + "exclude lower than", + ], +) +@pytest.mark.anyio +async def test_count_filter(query_string_filter, gen_comic, filter, expect): + await DB.add_all(*gen_comic) + + response = Response(await query_string_filter(filter)) + response.assert_is("ArtistFilterResult") + + assert id_list(response.edges) == expect diff --git a/tests/api/test_image.py b/tests/api/test_image.py index c8c26b3..e0e9251 100644 --- a/tests/api/test_image.py +++ b/tests/api/test_image.py @@ -1,5 +1,6 @@ import pytest from conftest import DB + from hircine.api.types import Image diff --git a/tests/api/test_namespace.py b/tests/api/test_namespace.py index 450075b..2ffc118 100644 --- a/tests/api/test_namespace.py +++ b/tests/api/test_namespace.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import Namespace diff --git a/tests/api/test_page.py b/tests/api/test_page.py index debd69a..cb06e3e 100644 --- a/tests/api/test_page.py +++ b/tests/api/test_page.py @@ -2,6 +2,7 @@ from datetime import datetime, timezone import pytest from conftest import DB + from hircine.api.types import Page from hircine.db.models import Archive diff --git a/tests/api/test_scraper_api.py b/tests/api/test_scraper_api.py index 1edd74f..b917e39 100644 --- a/tests/api/test_scraper_api.py +++ b/tests/api/test_scraper_api.py @@ -1,8 +1,9 @@ +import pytest +from conftest import DB, Response + import hircine.enums as enums import hircine.plugins import hircine.scraper.types as scraped -import pytest -from conftest import DB, Response from hircine.scraper import ScrapeError, Scraper, ScrapeWarning diff --git a/tests/api/test_sort.py b/tests/api/test_sort.py index b3c8562..02a7ec3 100644 --- a/tests/api/test_sort.py +++ b/tests/api/test_sort.py @@ -1,6 +1,7 @@ import pytest from conftest import DB, Response -from hircine.db.models import Namespace + +from hircine.db.models import Namespace, Tag @pytest.fixture @@ -22,6 +23,24 @@ def query_comic_sort(execute_sort): @pytest.fixture +def query_artist_sort(execute_sort): + query = """ + query artists($sort: ArtistSortInput) { + artists(sort: $sort) { + __typename + count + edges { + id + name + } + } + } + """ + + return execute_sort(query) + + +@pytest.fixture def query_namespace_sort(execute_sort): query = """ query namespaces($sort: NamespaceSortInput) { @@ -87,6 +106,31 @@ async def test_query_comics_sort_tag_count(gen_comic, query_comic_sort, sort, re assert ids == [edge["id"] for edge in response.edges] +@pytest.mark.parametrize( + "sort,reverse,expect", + [ + ({"on": "COMIC_COUNT"}, False, [2, 3, 1, 4]), + ({"on": "COMIC_COUNT", "direction": "DESCENDING"}, True, [1, 4, 2, 3]), + ({"on": "COMIC_COUNT", "direction": "ASCENDING"}, False, [2, 3, 1, 4]), + ], + ids=[ + "ascending (default)", + "descending", + "ascending", + ], +) +@pytest.mark.anyio +async def test_query_artists_sort_comic_count( + gen_comic, query_artist_sort, sort, reverse, expect +): + await DB.add_all(*gen_comic) + + response = Response(await query_artist_sort(sort)) + response.assert_is("ArtistFilterResult") + + assert expect == [edge["id"] for edge in response.edges] + + @pytest.mark.anyio async def test_query_comics_sort_random(gen_comic, query_comic_sort): comics = await DB.add_all(*gen_comic) @@ -134,4 +178,35 @@ async def test_query_namespace_sort_sort_name(query_namespace_sort): response = Response(await query_namespace_sort({"on": "SORT_NAME"})) response.assert_is("NamespaceFilterResult") - assert ["two", "one"] == [edge["name"] for edge in response.edges] + assert [edge["name"] for edge in response.edges] == ["two", "one"] + + +@pytest.mark.parametrize( + "sort,reverse,expect", + [ + ({"on": "TAG_COUNT"}, False, [2, 1]), + ({"on": "TAG_COUNT", "direction": "DESCENDING"}, True, [1, 2]), + ({"on": "TAG_COUNT", "direction": "ASCENDING"}, False, [2, 1]), + ], + ids=[ + "ascending (default)", + "descending", + "ascending", + ], +) +@pytest.mark.anyio +async def test_query_namespace_sort_tag_count( + gen_comic, query_namespace_sort, sort, reverse, expect +): + namespace_foo = Namespace(id=1, name="foo") + namespace_bar = Namespace(id=2, name="bar") + + tag_foo = Tag(id=1, name="foo", namespaces=[namespace_foo]) + tag_bar = Tag(id=2, name="bar", namespaces=[namespace_foo, namespace_bar]) + + await DB.add_all(tag_foo, tag_bar) + + response = Response(await query_namespace_sort(sort)) + response.assert_is("NamespaceFilterResult") + + assert expect == [edge["id"] for edge in response.edges] diff --git a/tests/api/test_statistics.py b/tests/api/test_statistics.py new file mode 100644 index 0000000..98c8dc7 --- /dev/null +++ b/tests/api/test_statistics.py @@ -0,0 +1,106 @@ +import pytest +from conftest import DB, Response + +import hircine.plugins +from hircine.db.models import ( + Artist, + Character, + Circle, + Page, + Tag, + World, +) +from hircine.scraper import Scraper + +totals_fragment = """ + fragment Totals on Statistics { + total { + archives + artists + characters + circles + comics + namespaces + scrapers + tags + worlds + images + pages + comic { + artists + characters + circles + tags + worlds + } + } + } +""" + + +@pytest.fixture +def query_statistics(execute): + query = """ + query statistics { + statistics { + __typename + ... Totals + } + } + """ + + return execute(totals_fragment + query) + + +@pytest.mark.anyio +async def test_statistics_returns_totals( + gen_comic, gen_image, query_statistics, empty_plugins +): + comic = next(gen_comic) + await DB.add(comic) + await DB.add(Artist(name="foo")) + await DB.add(Character(name="foo")) + await DB.add(Circle(name="foo")) + await DB.add(World(name="foo")) + await DB.add(Tag(name="foo")) + + image = next(gen_image) + await DB.add(image) + await DB.add( + Page(id=100, index=100, path="100.png", image=image, archive=comic.archive) + ) + await DB.add( + Page(id=101, index=101, path="101.png", image=image, archive=comic.archive) + ) + + namespaces = set() + for tag in comic.tags: + namespaces.add(tag.namespace.id) + + class MockScraper(Scraper): + name = "Scraper" + + def scrape(self): + yield None + + hircine.plugins.register_scraper("mock", MockScraper) + + response = Response(await query_statistics()) + + response.assert_is("Statistics") + assert response.total["comics"] == 1 + assert response.total["archives"] == 1 + assert response.total["artists"] == len(comic.artists) + 1 + assert response.total["characters"] == len(comic.characters) + 1 + assert response.total["circles"] == len(comic.circles) + 1 + assert response.total["worlds"] == len(comic.worlds) + 1 + assert response.total["tags"] == len(comic.tags) + 1 + assert response.total["namespaces"] == len(namespaces) + assert response.total["images"] == len(comic.pages) + 1 + assert response.total["pages"] == len(comic.pages) + 2 + assert response.total["scrapers"] == 1 + assert response.total["comic"]["artists"] == len(comic.artists) + assert response.total["comic"]["characters"] == len(comic.characters) + assert response.total["comic"]["circles"] == len(comic.circles) + assert response.total["comic"]["tags"] == len(comic.tags) + assert response.total["comic"]["worlds"] == len(comic.worlds) diff --git a/tests/api/test_tag.py b/tests/api/test_tag.py index c863a00..7970f3d 100644 --- a/tests/api/test_tag.py +++ b/tests/api/test_tag.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import Namespace, Tag diff --git a/tests/api/test_world.py b/tests/api/test_world.py index a3926d1..3546c2c 100644 --- a/tests/api/test_world.py +++ b/tests/api/test_world.py @@ -3,6 +3,7 @@ from datetime import timezone import pytest from conftest import DB, Response + from hircine.db.models import World |