From 675b8cfc09950326d168bcdc487bc81c7d5ea081 Mon Sep 17 00:00:00 2001 From: Nathaniel Landau Date: Tue, 7 Nov 2023 15:22:22 -0500 Subject: [PATCH] test: increase coverage --- poetry.lock | 54 ++++++------- pyproject.toml | 5 +- src/valentina/models/bot.py | 7 -- src/valentina/utils/autocomplete.py | 6 +- src/valentina/utils/database.py | 4 + tests/conftest.py | 20 ++++- tests/test_autocomplete.py | 118 ++++++++++++++++++++++++++++ 7 files changed, 173 insertions(+), 41 deletions(-) create mode 100644 tests/test_autocomplete.py diff --git a/poetry.lock b/poetry.lock index c0db35eb..acdc2747 100644 --- a/poetry.lock +++ b/poetry.lock @@ -231,29 +231,29 @@ test = ["asgi-lifespan (>=1.0.1)", "dnspython (>=2.1.0)", "fastapi (>=0.100)", " [[package]] name = "black" -version = "23.10.1" +version = "23.11.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, - {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, - {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, - {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, - {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, - {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, - {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, - {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, - {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, - {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, - {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, - {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, + {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"}, + {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"}, + {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"}, + {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"}, + {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"}, + {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"}, + {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"}, + {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"}, + {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"}, + {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"}, + {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"}, + {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"}, + {file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"}, + {file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"}, + {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, + {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, + {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, + {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, ] [package.dependencies] @@ -271,17 +271,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.28.78" +version = "1.28.80" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.28.78-py3-none-any.whl", hash = "sha256:ff8df4bb5aeb69acc64959a74b31042bfc52d64ca77dbe845a72c8062c48d179"}, - {file = "boto3-1.28.78.tar.gz", hash = "sha256:aa970b1571321846543a6e615848352fe7621f1cb96b4454e919421924af95f7"}, + {file = "boto3-1.28.80-py3-none-any.whl", hash = "sha256:2f43e032ab804a3c39996d524003d2b906e5d86856a32da3427e36912a22d2b7"}, + {file = "boto3-1.28.80.tar.gz", hash = "sha256:c48c6e04e43f894881b883a28fd032f16805f6cb2771b85f0c97f3fe34db0a41"}, ] [package.dependencies] -botocore = ">=1.31.78,<1.32.0" +botocore = ">=1.31.80,<1.32.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.7.0,<0.8.0" @@ -290,13 +290,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.31.78" +version = "1.31.80" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.31.78-py3-none-any.whl", hash = "sha256:a9ca8deeb3f47a10a25637859fee8d81cac2db37ace819d24471279e44879547"}, - {file = "botocore-1.31.78.tar.gz", hash = "sha256:320c70bc412157813c2cf60217a592b4b345f8e97e4bf3b1ce49b6be69ed8965"}, + {file = "botocore-1.31.80-py3-none-any.whl", hash = "sha256:1c693c0f8b2553fcbe0df223241191e6f9f60b4245d65c1822c08f659274fef2"}, + {file = "botocore-1.31.80.tar.gz", hash = "sha256:d43fe303530c12efca9be4ec3a9104e8a669f11d1ba9feb18f0284d751a9672c"}, ] [package.dependencies] @@ -2240,4 +2240,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "96fda828f5af3fb364a5145da583e61fb4d4778fddff6ed83369545af085a00b" +content-hash = "8012780a386bead7e2eac3439e30c646c5b15ed1d54984230e52a4b1b97d221c" diff --git a/pyproject.toml b/pyproject.toml index ab832e0f..b6af5d50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ aiofiles = "^23.2.1" arrow = "^1.3.0" beanie = "^1.23.1" - boto3 = "^1.28.78" + boto3 = "^1.28.80" inflect = "^7.0.0" loguru = "^0.7.2" numpy = "^1.26.1" @@ -45,7 +45,7 @@ pytest-xdist = "^3.3.1" [tool.poetry.group.dev.dependencies] - black = "^23.10.1" + black = "^23.11.0" commitizen = "^3.12.0" coverage = "^7.3.2" mypy = "^1.6.1" @@ -98,7 +98,6 @@ omit = [ "src/valentina/__version__.py", "src/valentina/bot.py", - "src/valentina/character/*", "src/valentina/cogs/*", "src/valentina/main.py", "src/valentina/views/*", diff --git a/src/valentina/models/bot.py b/src/valentina/models/bot.py index fba32aab..cefa585b 100644 --- a/src/valentina/models/bot.py +++ b/src/valentina/models/bot.py @@ -385,13 +385,6 @@ async def on_connect(self) -> None: # Initialize the mongodb database await init_database() - # TODO: BEGIN one-time migration code (remove after first run) - from valentina.utils.migrate_to_mongo import Migrate # noqa: PLC0415 - - migrate = Migrate(config=CONFIG) - await migrate.do_migration() - # TODO: END: Remove one-time migration code - # Connect to discord if not self.connected: logger.info(f"Logged in as {self.user.name} ({self.user.id})") diff --git a/src/valentina/utils/autocomplete.py b/src/valentina/utils/autocomplete.py index 1ebd6e2f..061aa97a 100644 --- a/src/valentina/utils/autocomplete.py +++ b/src/valentina/utils/autocomplete.py @@ -557,7 +557,7 @@ async def select_trait_category(ctx: discord.AutocompleteContext) -> list[Option return [ OptionChoice(category.name.title(), category.name) for category in TraitCategory - if category.name.lower().startswith(ctx.options["category"].lower()) + if category.name.startswith(ctx.options["category"].upper()) ][:MAX_OPTION_LIST_SIZE] @@ -574,7 +574,7 @@ async def select_vampire_clan(ctx: discord.AutocompleteContext) -> list[OptionCh list[str]: A list of vampire clan names for the autocomplete list. """ return [ - OptionChoice(c.name, c.name) + OptionChoice(c.name.title(), c.name) for c in VampireClan - if c.value.name.lower().startswith(ctx.options["vampire_clan"].lower()) + if c.name.startswith(ctx.options["vampire_clan"].upper()) ][:MAX_OPTION_LIST_SIZE] diff --git a/src/valentina/utils/database.py b/src/valentina/utils/database.py index 6d309772..c4f67257 100644 --- a/src/valentina/utils/database.py +++ b/src/valentina/utils/database.py @@ -1,6 +1,7 @@ """Database utilities for Valentina.""" from beanie import init_beanie +from loguru import logger from motor.motor_asyncio import AsyncIOMotorClient from valentina.constants import CONFIG @@ -23,6 +24,7 @@ async def init_database(client=None, database=None) -> None: # type: ignore [no client (AsyncIOMotorClient, optional): The database client. Defaults to None. database (AsyncIOMotorClient, optional): The database. Defaults to None. """ + logger.debug("DB: Initializing...") # Create Motor client if not client: client = AsyncIOMotorClient(f"{CONFIG['VALENTINA_MONGO_URI']}", tz_aware=True) @@ -43,3 +45,5 @@ async def init_database(client=None, database=None) -> None: # type: ignore [no RollProbability, ], ) + + logger.info("DB: Initialized") diff --git a/tests/conftest.py b/tests/conftest.py index 6b3211df..a2249279 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -41,6 +41,19 @@ async def _init_database(request): ### Mock discord.py objects ### +@pytest.fixture() +def mock_interaction1(mocker, mock_guild1, mock_member): + """A mock of a discord.Interaction object.""" + mock_interaction = mocker.MagicMock() + mock_interaction.id = 1 + mock_interaction.guild = mock_guild1 + mock_interaction.author = mock_member + + mock_interaction.__class__ = discord.Interaction + + return mock_interaction + + @pytest.fixture() def mock_member(mocker): """A mock of a discord.Member object.""" @@ -119,15 +132,20 @@ def mock_guild2(mocker): @pytest.fixture() -def mock_ctx1(mocker, mock_member, mock_guild1): +def mock_ctx1(mocker, mock_member, mock_guild1, mock_interaction1): """Create a mock context object with user 1.""" # Mock the ctx.bot object mock_bot = mocker.MagicMock() mock_bot.user_svc.update_or_add = MagicMock(return_value=mock_member) mock_bot.__class__ = commands.Bot + mock_options = mocker.MagicMock() + mock_options.__class__ = dict + mock_options = {} + # Mock the ctx object mock_ctx = mocker.MagicMock() + mock_ctx.interaction = mock_interaction1 mock_ctx.author = mock_member mock_ctx.bot = mock_bot mock_ctx.guild = mock_guild1 diff --git a/tests/test_autocomplete.py b/tests/test_autocomplete.py new file mode 100644 index 00000000..5b18c2d8 --- /dev/null +++ b/tests/test_autocomplete.py @@ -0,0 +1,118 @@ +# type: ignore +"""Test the autocomplete functions.""" + +import discord +import pytest +from discord.commands import OptionChoice +from rich import print + +from valentina.models import Campaign +from valentina.utils import autocomplete + +from .factories import * + + +@pytest.mark.drop_db() +async def test_select_campaign(campaign_factory, mock_ctx1): + """Test the select_campaign function.""" + # GIVEN a campaign in the database + campaign = campaign_factory.build(name="mock_campaign", guild=mock_ctx1.interaction.guild.id) + await campaign.insert() + + mock_ctx1.options = {"campaign": "mock_campaign"} + + # WHEN calling select_campaign + result = await autocomplete.select_campaign(mock_ctx1) + + # THEN the campaign is returned + assert len(result) == 1 + assert result[0].name == "mock_campaign" + assert result[0].value == str(campaign.id) + + +@pytest.mark.no_db() +async def test_select_vampire_clan(mock_ctx1): + """Test the select_vampire_clan function.""" + # GIVEN a mock context + mock_ctx1.options = {"vampire_clan": "Ventrue"} + + # WHEN calling select_vampire_clan + result = await autocomplete.select_vampire_clan(mock_ctx1) + + # THEN the clan is returned + assert len(result) == 1 + assert result[0].name == "Ventrue" + assert result[0].value == "VENTRUE" + + # GIVEN a mock context + mock_ctx1.options = {"vampire_clan": "some_thing"} + + # WHEN calling select_vampire_clan + result = await autocomplete.select_vampire_clan(mock_ctx1) + + # THEN the clan is returned + assert len(result) == 0 + + +@pytest.mark.no_db() +async def test_select_trait_category(mock_ctx1): + """Test the select_trait_category function.""" + # GIVEN a mock context + mock_ctx1.options = {"category": "physical"} + + # WHEN calling select_trait_category + result = await autocomplete.select_trait_category(mock_ctx1) + + # THEN the category is returned + assert len(result) == 1 + assert result[0].name == "Physical" + assert result[0].value == "PHYSICAL" + + # GIVEN a mock context + mock_ctx1.options = {"category": "some_thing"} + + # WHEN calling select_trait_category + result = await autocomplete.select_trait_category(mock_ctx1) + + # THEN the category is returned + assert len(result) == 0 + + +@pytest.mark.drop_db() +async def test_select_storyteller_character(mock_ctx1, character_factory): + """Test the select_storyteller_character function.""" + # GIVEN two characters in the database and a mock_ context + character1 = character_factory.build( + name_first="character1", + name_last="character1", + guild=mock_ctx1.interaction.guild.id, + type_storyteller=True, + type_player=False, + type_chargen=False, + is_alive=True, + traits=[], + ) + + character2 = character_factory.build( + name_first="character2", + name_last="character2", + guild=mock_ctx1.interaction.guild.id, + type_storyteller=False, + type_player=True, + type_chargen=False, + is_alive=True, + traits=[], + ) + + await character1.insert() + await character2.insert() + + mock_ctx1.value = "char" + + # WHEN calling select_storyteller_character + result = await autocomplete.select_storyteller_character(mock_ctx1) + + # THEN the storyteller character is returned + assert len(result) == 1 + assert result[0].name == "character1 character1" + assert result[0].value == str(character1.id)