diff --git a/engine/apps/api/tests/test_schedule_export.py b/engine/apps/api/tests/test_schedule_export.py index f747067e60..1990024546 100644 --- a/engine/apps/api/tests/test_schedule_export.py +++ b/engine/apps/api/tests/test_schedule_export.py @@ -7,8 +7,6 @@ from apps.auth_token.models import ScheduleExportAuthToken from apps.schedules.models import OnCallScheduleICal -ICAL_URL = "https://calendar.google.com/calendar/ical/amixr.io_37gttuakhrtr75ano72p69rt78%40group.calendar.google.com/private-1d00a680ba5be7426c3eb3ef1616e26d/basic.ics" # noqa - @pytest.mark.django_db @pytest.mark.parametrize( @@ -32,7 +30,7 @@ def test_get_schedule_export_token( organization, schedule_class=OnCallScheduleICal, name="test_ical_schedule", - ical_url_primary=ICAL_URL, + ical_url_primary="https://example.com", ) ScheduleExportAuthToken.create_auth_token(user=user, organization=organization, schedule=schedule) @@ -68,7 +66,7 @@ def test_schedule_export_token_not_found( organization, schedule_class=OnCallScheduleICal, name="test_ical_schedule", - ical_url_primary=ICAL_URL, + ical_url_primary="https://example.com", ) url = reverse("api-internal:schedule-export-token", kwargs={"pk": schedule.public_primary_key}) @@ -102,7 +100,7 @@ def test_schedule_create_export_token( organization, schedule_class=OnCallScheduleICal, name="test_ical_schedule", - ical_url_primary=ICAL_URL, + ical_url_primary="https://example.com", ) url = reverse("api-internal:schedule-export-token", kwargs={"pk": schedule.public_primary_key}) @@ -136,7 +134,7 @@ def test_schedule_delete_export_token( organization, schedule_class=OnCallScheduleICal, name="test_ical_schedule", - ical_url_primary=ICAL_URL, + ical_url_primary="https://example.com", ) instance, _ = ScheduleExportAuthToken.create_auth_token(user=user, organization=organization, schedule=schedule) diff --git a/engine/apps/api/tests/test_schedules.py b/engine/apps/api/tests/test_schedules.py index 8efcb6b236..5c4e9bbf01 100644 --- a/engine/apps/api/tests/test_schedules.py +++ b/engine/apps/api/tests/test_schedules.py @@ -23,7 +23,20 @@ from apps.slack.models import SlackUserGroup from common.api_helpers.utils import create_engine_url, serialize_datetime_as_utc_timestamp -ICAL_URL = "https://calendar.google.com/calendar/ical/amixr.io_37gttuakhrtr75ano72p69rt78%40group.calendar.google.com/private-1d00a680ba5be7426c3eb3ef1616e26d/basic.ics" +ICAL_URL = "https://example.com" + + +@pytest.fixture(autouse=True) +def patch_fetch_ical_file(): + """ + NOTE: we patch this method for all tests in this file to avoid making actual HTTP requests.. we don't really need + to test the actual fetching of the ical file in these tests, so just simply mock out the response as an empty string + + Alternatively, if we really needed to, we could save .ical files locally here, and read/return those as the + return_value + """ + with patch("apps.schedules.ical_utils.fetch_ical_file", return_value=""): + yield @pytest.fixture() @@ -64,7 +77,7 @@ def schedule_internal_api_setup( def test_get_list_schedules( schedule_internal_api_setup, make_escalation_chain, make_escalation_policy, make_user_auth_headers ): - user, token, calendar_schedule, ical_schedule, web_schedule, slack_channel = schedule_internal_api_setup + user, token, calendar_schedule, ical_schedule, web_schedule, _ = schedule_internal_api_setup client = APIClient() url = reverse("api-internal:schedule-list") diff --git a/engine/apps/api/tests/test_user_schedule_export.py b/engine/apps/api/tests/test_user_schedule_export.py index eec82fa0da..7ebcd884d7 100644 --- a/engine/apps/api/tests/test_user_schedule_export.py +++ b/engine/apps/api/tests/test_user_schedule_export.py @@ -6,8 +6,6 @@ from apps.api.permissions import LegacyAccessControlRole from apps.auth_token.models import UserScheduleExportAuthToken -ICAL_URL = "https://calendar.google.com/calendar/ical/amixr.io_37gttuakhrtr75ano72p69rt78%40group.calendar.google.com/private-1d00a680ba5be7426c3eb3ef1616e26d/basic.ics" # noqa - @pytest.mark.django_db @pytest.mark.parametrize( diff --git a/engine/apps/auth_token/tests/test_plugin_auth.py b/engine/apps/auth_token/tests/test_plugin_auth.py index a44bd3777d..44440e73f7 100644 --- a/engine/apps/auth_token/tests/test_plugin_auth.py +++ b/engine/apps/auth_token/tests/test_plugin_auth.py @@ -1,4 +1,5 @@ import json +from unittest.mock import patch import pytest from django.utils import timezone @@ -79,8 +80,12 @@ def test_plugin_authentication_fail(authorization, instance_context): request = APIRequestFactory().get("/", **headers) - with pytest.raises(AuthenticationFailed): - PluginAuthentication().authenticate(request) + class MockCheckTokenResponse: + organization = None + + with patch("apps.auth_token.auth.check_token", return_value=MockCheckTokenResponse): + with pytest.raises(AuthenticationFailed): + PluginAuthentication().authenticate(request) @pytest.mark.django_db diff --git a/engine/apps/grafana_plugin/tests/test_sync_v2.py b/engine/apps/grafana_plugin/tests/test_sync_v2.py index 8f1a9271aa..59291a7ba9 100644 --- a/engine/apps/grafana_plugin/tests/test_sync_v2.py +++ b/engine/apps/grafana_plugin/tests/test_sync_v2.py @@ -142,6 +142,7 @@ def test_sync_v2_content_encoding( mock_sync.assert_called() +@patch("apps.grafana_plugin.helpers.client.GrafanaAPIClient.check_token", return_value=(None, {"connected": True})) @pytest.mark.parametrize( "irm_enabled,expected", [ @@ -151,6 +152,9 @@ def test_sync_v2_content_encoding( ) @pytest.mark.django_db def test_sync_v2_irm_enabled( + # mock this out so that we're not making a real network call, the sync v2 endpoint ends up calling + # user_management.sync._sync_organization which calls GrafanaApiClient.check_token + _mock_grafana_api_client_check_token, make_organization_and_user_with_plugin_token, make_user_auth_headers, settings, diff --git a/engine/requirements-dev.in b/engine/requirements-dev.in index 7d599ee8d2..ce5f71426a 100644 --- a/engine/requirements-dev.in +++ b/engine/requirements-dev.in @@ -8,6 +8,7 @@ mypy==1.4.1 pre-commit==2.15.0 pytest==8.2.2 pytest-django==4.8.0 +pytest-socket==0.7.0 pytest-xdist[psutil]==3.6.1 pytest_factoryboy==2.7.0 types-beautifulsoup4==4.12.0.5 diff --git a/engine/requirements-dev.txt b/engine/requirements-dev.txt index 16256b89d2..03cf4606a6 100644 --- a/engine/requirements-dev.txt +++ b/engine/requirements-dev.txt @@ -91,11 +91,14 @@ pytest==8.2.2 # -r requirements-dev.in # pytest-django # pytest-factoryboy + # pytest-socket # pytest-xdist pytest-django==4.8.0 # via -r requirements-dev.in pytest-factoryboy==2.7.0 # via -r requirements-dev.in +pytest-socket==0.7.0 + # via -r requirements-dev.in pytest-xdist==3.6.1 # via -r requirements-dev.in python-dateutil==2.8.2 @@ -111,9 +114,7 @@ requests==2.32.3 # -c requirements.txt # djangorestframework-stubs setuptools==75.3.0 - # via - # -c requirements.txt - # nodeenv + # via nodeenv six==1.16.0 # via # -c requirements.txt diff --git a/engine/tox.ini b/engine/tox.ini index 908559ba5e..be2959bbe7 100644 --- a/engine/tox.ini +++ b/engine/tox.ini @@ -14,7 +14,14 @@ banned-modules = # # --dist no = temporarily disable xdist as it's leading to flaky tests :( # https://github.com/grafana/oncall-private/issues/2733 -addopts = --dist no --no-migrations --color=yes --showlocals + +# From pytest-socket docs (https://github.com/miketheman/pytest-socket): +# A plugin to use with Pytest to disable or restrict socket calls during tests to ensure network calls are prevented +# --disable-socket = tests should fail on any access to socket or libraries using socket with a SocketBlockedErro +# --allow-hosts = allow connections to the given hostnames/IPs. +# - localhost = our tests on CI use localhost as the host to connect to databases running locally in docker container +# - oncall-dev-mariadb = if you're running things locally, with a MariaDB instance running, there's a good chance the hostname will be this +addopts = --dist no --no-migrations --color=yes --showlocals --disable-socket --allow-hosts=localhost,oncall-dev-mariadb # https://pytest-django.readthedocs.io/en/latest/faq.html#my-tests-are-not-being-found-why python_files = tests.py test_*.py *_tests.py