Skip to content

Commit 30c102a

Browse files
committed
[CHANGE] Block tests from accessing the network and make live calls
1 parent 757008e commit 30c102a

6 files changed

Lines changed: 108 additions & 61 deletions

File tree

‎sovtimer/providers.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
# AA Sovereignty Timer
99
from sovtimer import (
10-
__app_name_useragent__,
10+
__app_name_verbose__,
1111
__esi_compatibility_date__,
1212
__github_url__,
1313
__version__,
@@ -18,7 +18,7 @@
1818
# Use the latest compatibility date, see https://esi.evetech.net/meta/compatibility-dates
1919
compatibility_date=__esi_compatibility_date__,
2020
# User agent for the ESI client
21-
ua_appname=__app_name_useragent__,
21+
ua_appname=__app_name_verbose__,
2222
ua_version=__version__,
2323
ua_url=__github_url__,
2424
)

‎sovtimer/tests/__init__.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,41 @@
11
"""
22
Initializing our tests
33
"""
4+
5+
# Standard Library
6+
import socket
7+
8+
# Django
9+
from django.test import TestCase
10+
11+
12+
class SocketAccessError(Exception):
13+
"""Error raised when a test script accesses the network"""
14+
15+
16+
class BaseTestCase(TestCase):
17+
"""Variation of Django's TestCase class that prevents any network use.
18+
19+
Example:
20+
21+
.. code-block:: python
22+
23+
class TestMyStuff(BaseTestCase):
24+
def test_should_do_what_i_need(self): ...
25+
26+
"""
27+
28+
@classmethod
29+
def setUpClass(cls):
30+
cls.socket_original = socket.socket
31+
socket.socket = cls.guard
32+
return super().setUpClass()
33+
34+
@classmethod
35+
def tearDownClass(cls):
36+
socket.socket = cls.socket_original
37+
return super().tearDownClass()
38+
39+
@staticmethod
40+
def guard(*args, **kwargs):
41+
raise SocketAccessError("Attempted to access network")

‎sovtimer/tests/test_ajax_calls.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from http import HTTPStatus
88

99
# Django
10-
from django.test import RequestFactory, TestCase
10+
from django.test import RequestFactory
1111
from django.urls import reverse
1212

1313
# Alliance Auth
@@ -17,12 +17,13 @@
1717
from app_utils.testing import add_character_to_user, create_user_from_evecharacter
1818

1919
# AA Sovereignty Timer
20+
from sovtimer.tests import BaseTestCase
2021
from sovtimer.tests.fixtures.load_allianceauth import load_allianceauth
2122
from sovtimer.tests.fixtures.load_sovtimer import load_sovtimer
2223
from sovtimer.views import dashboard_data
2324

2425

25-
class TestAjaxCalls(TestCase):
26+
class TestAjaxCalls(BaseTestCase):
2627
"""
2728
Test the ajax calls
2829
"""

‎sovtimer/tests/test_app_settings.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
"""
44

55
# Django
6-
from django.test import TestCase, override_settings
6+
from django.test import override_settings
77

88
# AA Sovereignty Timer
99
from sovtimer.app_settings import debug_enabled
10+
from sovtimer.tests import BaseTestCase
1011

1112

12-
class TestAppSettings(TestCase):
13+
class TestAppSettings(BaseTestCase):
1314
"""
1415
Tests for App Settings
1516
"""

‎sovtimer/tests/test_tasks.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
update_sov_campaigns,
2020
update_sov_structures,
2121
)
22+
from sovtimer.tests import BaseTestCase
2223

2324

24-
class TestRunSovCampaignUpdatesTask(TestCase):
25+
class TestRunSovCampaignUpdatesTask(BaseTestCase):
2526
"""
2627
Test the run_sov_campaign_updates task.
2728
"""

‎sovtimer/tests/test_user_agent.py‎

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,80 +3,86 @@
33
"""
44

55
# Standard Library
6-
from unittest.mock import MagicMock, PropertyMock, patch
6+
from unittest.mock import MagicMock, patch
77

88
# Third Party
9-
import requests_mock
9+
import httpx
1010

1111
# Django
1212
from django.conf import settings
13-
from django.test import TestCase
1413

1514
# Alliance Auth
1615
from esi import __url__ as esi_url
1716
from esi import __version__ as esi_version
17+
from esi.openapi_clients import ESIClientProvider
18+
from esi.tests.test_openapi import SPEC_PATH
1819

1920
# AA Sovereignty Timer
20-
from sovtimer import __app_name_useragent__, __github_url__, __version__
21-
from sovtimer.providers import esi
21+
from sovtimer import (
22+
__app_name_verbose__,
23+
__esi_compatibility_date__,
24+
__github_url__,
25+
__version__,
26+
)
27+
from sovtimer.tests import BaseTestCase
2228

2329

24-
class TestUserAgent(TestCase):
30+
class TestUserAgent(BaseTestCase):
2531
"""
2632
Test suite for verifying the `User-Agent` header in ESI requests.
2733
"""
2834

29-
@requests_mock.Mocker()
30-
def test_user_agent_header(self, requests_mocker):
35+
@patch.object(httpx.Client, "send")
36+
def test_user_agent_header(self, send: MagicMock):
3137
"""
32-
Test the `User-Agent` header for ESI requests.
38+
Test that the `User-Agent` header is correctly set in ESI requests.
3339
34-
This test ensures that the `User-Agent` header in the request matches
35-
the expected format. It uses mocking to avoid making live API calls
36-
and verifies the header construction.
40+
This test verifies that the `User-Agent` header in HTTP requests made by the ESI client
41+
is constructed correctly based on the provided application name, version, and other metadata.
3742
38-
:param requests_mocker: A mocker object provided by the `requests_mock` library
39-
to intercept HTTP requests.
40-
:type requests_mocker: requests_mock.mocker.Mocker
41-
:return: None
43+
Args:
44+
send (MagicMock): A mocked `httpx.Client.send` method to intercept HTTP requests and provide a controlled response.
45+
46+
Assertions:
47+
- The `User-Agent` header in the HTTP request matches the expected format.
48+
- The `players` field in the response JSON is correctly parsed and matches the expected value.
4249
"""
4350

44-
# Create a mock response object with the expected `User-Agent` header
45-
mock_response = MagicMock()
46-
mock_response.request.headers = {
47-
"User-Agent": (
48-
f"{__app_name_useragent__}/{__version__} "
51+
# Initialize the ESI client provider with test-specific metadata
52+
esi = ESIClientProvider(
53+
ua_appname=__app_name_verbose__, # Application name for the User-Agent header
54+
ua_url=__github_url__, # Application URL for the User-Agent header
55+
ua_version=__version__, # Application version for the User-Agent header
56+
compatibility_date=__esi_compatibility_date__, # Compatibility date for the ESI spec
57+
spec_file=SPEC_PATH, # Path to the OpenAPI specification file
58+
)
59+
60+
# Mock the HTTP response returned by the `send` method
61+
send.return_value = httpx.Response(
62+
status_code=200, # HTTP status code for the response
63+
json={ # Mocked JSON response body
64+
"players": 1234,
65+
"server_version": "1234",
66+
"start_time": "2029-09-19T11:02:08Z",
67+
},
68+
request=httpx.Request(method="GET", url="test"), # Mocked HTTP request
69+
)
70+
71+
# Perform the ESI client request and retrieve the status
72+
status = esi.client.Status.GetStatus().result()
73+
74+
# Retrieve the arguments passed to the mocked `send` method
75+
call_args, call_kwargs = send.call_args
76+
77+
# Assert that the `User-Agent` header matches the expected format
78+
self.assertEqual(
79+
first=call_args[0].headers["user-agent"],
80+
second=(
81+
f"AaSovereigntyTimer/{__version__} "
4982
f"({settings.ESI_USER_CONTACT_EMAIL}; +{__github_url__}) "
50-
f"Django-ESI/{esi_version} (+{esi_url})"
51-
)
52-
}
53-
# Mock the result of the API call
54-
mock_result = (None, mock_response)
55-
56-
# Create a mock `Status` object and configure its `GetStatus` method
57-
mock_status = MagicMock()
58-
mock_status.GetStatus.return_value.result.return_value = mock_result
59-
60-
# Create a mock `client` object and assign the mock `Status` object to it
61-
mock_client = MagicMock()
62-
mock_client.Status = mock_status
63-
64-
# Patch the `client` property of the `ESIClientProvider` class to use the mock client
65-
with patch(
66-
target="esi.openapi_clients.ESIClientProvider.client",
67-
new_callable=PropertyMock,
68-
) as mock_client_prop:
69-
mock_client_prop.return_value = mock_client
70-
71-
# Call the mocked `GetStatus` method and retrieve the response
72-
_, response = esi.client.Status.GetStatus().result(return_response=True)
73-
74-
# Assert that the `User-Agent` header in the response matches the expected value
75-
self.assertEqual(
76-
first=response.request.headers["User-Agent"],
77-
second=(
78-
f"{__app_name_useragent__}/{__version__} "
79-
f"({settings.ESI_USER_CONTACT_EMAIL}; +{__github_url__}) "
80-
f"Django-ESI/{esi_version} (+{esi_url})"
81-
),
82-
)
83+
f"DjangoEsi/{esi_version} (+{esi_url})"
84+
),
85+
)
86+
87+
# Assert that the `players` field in the response matches the expected value
88+
self.assertEqual(first=status.players, second=1234)

0 commit comments

Comments
 (0)