Explorar o código

tests: gate live service-api tests behind ROOM_CAL_LIVE_TESTS=1

Tests marked 'live' hit real service APIs and need credentials dev
systems only sometimes have (especially 2FA-gated backends). They now
skip by default; set ROOM_CAL_LIVE_TESTS=1 to run them.

Marked: test_refresh_cookies (module), test_services (module — does
live price writes), test_fetch_reservations, test_get_thread_live,
test_fetch_prices_syncs_api_prices_to_caldav,
test_diff_returns_complete_structure.

Default suite drops from ~3.5m to ~7s on a machine with live creds.
ZiB hai 4 meses
pai
achega
9e728f3193

+ 3 - 0
pyproject.toml

@@ -46,3 +46,6 @@ packages = ["room_cal"]
 pythonpath = ["."]
 asyncio_mode = "auto"
 addopts = "-n auto --dist=loadfile"
+markers = [
+  "live: makes live service-api calls; skipped unless ROOM_CAL_LIVE_TESTS=1",
+]

+ 15 - 0
tests/conftest.py

@@ -1,4 +1,5 @@
 import dataclasses
+import os
 import socket
 import subprocess
 import sys
@@ -8,6 +9,20 @@ import httpx
 import pytest
 
 
+def pytest_collection_modifyitems(config, items):
+  """Skip tests marked 'live' unless ROOM_CAL_LIVE_TESTS=1.
+
+  Live tests hit real service APIs and need credentials that dev systems
+  only sometimes have (especially for 2FA-gated backends).
+  """
+  if os.environ.get('ROOM_CAL_LIVE_TESTS'):
+    return
+  skip_live = pytest.mark.skip(reason='live service-api test; set ROOM_CAL_LIVE_TESTS=1 to run')
+  for item in items:
+    if 'live' in item.keywords:
+      item.add_marker(skip_live)
+
+
 def _free_port() -> int:
   with socket.socket() as s:
     s.bind(('127.0.0.1', 0))

+ 2 - 0
tests/test_action_chains.py

@@ -159,6 +159,7 @@ async def test_fetch_closed_writes_and_removes_closed_events():
 
 
 @pytest.mark.asyncio
+@pytest.mark.live
 async def test_fetch_prices_syncs_api_prices_to_caldav():
   """fetch_prices writes API list prices (converted to net) to the calendar."""
   from room_cal.service_api import ServiceAPI
@@ -284,6 +285,7 @@ async def test_apply_discounts_pushes_discounted_prices():
 
 
 @pytest.mark.asyncio
+@pytest.mark.live
 @pytest.mark.usefixtures('require_user_cal')
 async def test_diff_returns_complete_structure():
   """diff() on a past window returns all expected keys with valid list/dict shapes."""

+ 1 - 0
tests/test_actions.py

@@ -24,6 +24,7 @@ async def test_fetch_feed_fire():
     assert result.services, f"Empty closed_services on {d}"
 
 
+@pytest.mark.live
 async def test_fetch_reservations():
   api = ServiceAPI()
   scan_start = date.today() - timedelta(days=90)

+ 1 - 0
tests/test_chat.py

@@ -218,6 +218,7 @@ async def test_post_message_success(client):
 # ── live integration ───────────────────────────────────────────────────────────
 
 @pytest.mark.asyncio
+@pytest.mark.live
 async def test_get_thread_live():
   """Fetch a real thread using chat_id from a recent CalDAV reservation."""
   from datetime import date, timedelta

+ 2 - 0
tests/test_refresh_cookies.py

@@ -14,6 +14,8 @@ import pytest
 from room_cal._utils import data_home as _data_home, get_config
 from room_cal.service_api.types import ServiceAuthError
 
+pytestmark = pytest.mark.live
+
 
 def _ts_dir() -> Path:
   return Path(str(files('room_cal.service_api').joinpath('typescript')))

+ 2 - 0
tests/test_services.py

@@ -4,6 +4,8 @@ import pytest
 
 from room_cal.service_api import ServiceAPI
 
+pytestmark = pytest.mark.live
+
 
 async def test_price_roundtrip():
   api = ServiceAPI()