From eb86d9b9c1d84cdd96cc5d386921c572e5fd3a84 Mon Sep 17 00:00:00 2001 From: Jonxslays <51417989+Jonxslays@users.noreply.github.com> Date: Sun, 24 Mar 2024 07:24:25 -0700 Subject: [PATCH] More tests --- tests/services/test_http.py | 39 +++++++- tests/services/test_names.py | 172 +++++++++++++++++++++++++++++++++ tests/services/test_records.py | 138 ++++++++++++++++++++++++++ 3 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 tests/services/test_names.py create mode 100644 tests/services/test_records.py diff --git a/tests/services/test_http.py b/tests/services/test_http.py index 4870a5b..60f6060 100644 --- a/tests/services/test_http.py +++ b/tests/services/test_http.py @@ -23,6 +23,8 @@ from unittest import mock +import pytest + from wom import HttpErrorResponse from wom import HttpService from wom import constants @@ -77,8 +79,43 @@ async def test_read_content_fails(_: mock.MagicMock, client_response: mock.Magic assert result.message == "Failed to read response content." +@mock.patch("wom.services.http.aiohttp.ClientSession") +async def test_get_request_func(session: mock.MagicMock) -> None: + service = HttpService(None, None, None) + get = mock.Mock() + session.return_value.get = get + + await service.start() + result = service._get_request_func("GET") # type: ignore + + session.assert_called_once() + assert result is get + + +@mock.patch("wom.services.http.aiohttp.ClientSession") +async def test_get_request_func_fails_w_no_start(session: mock.MagicMock) -> None: + service = HttpService(None, None, None) + + with pytest.raises(RuntimeError) as e: + _ = service._get_request_func("GET") # type: ignore + + session.assert_not_called() + assert e.exconly() == "RuntimeError: HttpService.start was never called, aborting..." + + +@mock.patch("wom.services.http.aiohttp.ClientSession") +async def test_get_request_func_fails_w_invalid_method(session: mock.MagicMock) -> None: + service = HttpService(None, None, None) + await service.start() + + with pytest.raises(KeyError) as e: + _ = service._get_request_func("EEP") # type: ignore + + session.assert_called_once() + assert e.exconly() == "KeyError: 'EEP'" + + # TODO: Add more http tests here for the public methods and also with mocks for: # - fetch -# - _get_request_func # - _init_session # - _request diff --git a/tests/services/test_names.py b/tests/services/test_names.py new file mode 100644 index 0000000..f5fa882 --- /dev/null +++ b/tests/services/test_names.py @@ -0,0 +1,172 @@ +# wom.py - An asynchronous wrapper for the Wise Old Man API. +# Copyright (c) 2023-present Jonxslays +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from __future__ import annotations + +import typing as t +from unittest import mock + +import wom +from wom import NameChangeService + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_search_name_changes( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.search_name_changes() + + generate_map.assert_called_once_with( + username=None, + status=None, + limit=None, + offset=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.NameChange]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_search_name_changes_w_username( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.search_name_changes("EEP") + + generate_map.assert_called_once_with( + username="EEP", + status=None, + limit=None, + offset=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.NameChange]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_search_name_changes_w_status( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.search_name_changes(status=wom.NameChangeStatus.Denied) + + generate_map.assert_called_once_with( + username=None, + status="denied", + limit=None, + offset=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.NameChange]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_search_name_changes_w_limit( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.search_name_changes(limit=69) + + generate_map.assert_called_once_with( + username=None, + status=None, + limit=69, + offset=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.NameChange]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_search_name_changes_w_offset( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.search_name_changes(offset=420) + + generate_map.assert_called_once_with( + username=None, + status=None, + limit=None, + offset=420, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.NameChange]) + + +@mock.patch("wom.services.names.routes.Route.compile") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_submit_name_change( + ok_or_err: mock.Mock, generate_map: mock.Mock, _compile: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + _compile.return_value = 123 + service = NameChangeService(http, mock.Mock()) + + await service.submit_name_change("old", "new") + + generate_map.assert_called_once_with(oldName="old", newName="new") + http.fetch.assert_awaited_once_with(123, payload=generate_map()) + ok_or_err.assert_called_once_with(b"[]", wom.NameChange) diff --git a/tests/services/test_records.py b/tests/services/test_records.py new file mode 100644 index 0000000..3c0b974 --- /dev/null +++ b/tests/services/test_records.py @@ -0,0 +1,138 @@ +# wom.py - An asynchronous wrapper for the Wise Old Man API. +# Copyright (c) 2023-present Jonxslays +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from __future__ import annotations + +import typing as t +from unittest import mock + +import wom +from wom import RecordService + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_get_global_leaderboards( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = RecordService(http, mock.Mock()) + + await service.get_global_leaderboards(wom.Metric.Thieving, wom.Period.Week) + + generate_map.assert_called_once_with( + metric="thieving", + period="week", + playerType=None, + playerBuild=None, + country=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.RecordLeaderboardEntry]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_get_global_leaderboards_w_player_type( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = RecordService(http, mock.Mock()) + + await service.get_global_leaderboards( + wom.Metric.Thieving, wom.Period.Week, player_type=wom.PlayerType.Ultimate + ) + + generate_map.assert_called_once_with( + metric="thieving", + period="week", + playerType="ultimate", + playerBuild=None, + country=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.RecordLeaderboardEntry]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_get_global_leaderboards_w_player_build( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = RecordService(http, mock.Mock()) + + await service.get_global_leaderboards( + wom.Metric.Thieving, wom.Period.Week, player_build=wom.PlayerBuild.Zerker + ) + + generate_map.assert_called_once_with( + metric="thieving", + period="week", + playerType=None, + playerBuild="zerker", + country=None, + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.RecordLeaderboardEntry]) + + +@mock.patch("wom.services.names.routes.CompiledRoute.with_params") +@mock.patch("wom.services.base.BaseService._generate_map") +@mock.patch("wom.services.base.BaseService._ok_or_err") +async def test_get_global_leaderboards_w_country( + ok_or_err: mock.Mock, generate_map: mock.Mock, with_params: mock.Mock +) -> None: + http = mock.Mock() + http.fetch = mock.AsyncMock() + http.fetch.return_value = b"[]" + with_params.return_value = 123 + service = RecordService(http, mock.Mock()) + + await service.get_global_leaderboards( + wom.Metric.Thieving, wom.Period.Week, country=wom.Country.Au + ) + + generate_map.assert_called_once_with( + metric="thieving", + period="week", + playerType=None, + playerBuild=None, + country="AU", + ) + + http.fetch.assert_awaited_once_with(123) + ok_or_err.assert_called_once_with(b"[]", t.List[wom.RecordLeaderboardEntry])