Skip to content

Commit 92af2a0

Browse files
committed
fix: resolve __init__ complexity and harden analytics_url tests
Extract _ensure_trailing_slash to bring Flagsmith.__init__ back under the flake8 C901 limit that pre-commit.ci flagged. Add an integration test for the default analytics endpoint, and filter both analytics tests by exact URL so they no longer depend on the global session's cross-test traffic.
1 parent 77e99d4 commit 92af2a0

2 files changed

Lines changed: 62 additions & 19 deletions

File tree

‎flagsmith/flagsmith.py‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,13 @@ def __init__(
178178
self.session.proxies.update(proxies or {})
179179
retries = retries or Retry(total=3, backoff_factor=0.1)
180180

181-
api_url = api_url or DEFAULT_API_URL
182-
self.api_url = api_url if api_url.endswith("/") else f"{api_url}/"
183-
184-
realtime_api_url = realtime_api_url or DEFAULT_REALTIME_API_URL
185-
self.realtime_api_url = (
186-
realtime_api_url
187-
if realtime_api_url.endswith("/")
188-
else f"{realtime_api_url}/"
181+
self.api_url = self._ensure_trailing_slash(api_url or DEFAULT_API_URL)
182+
self.realtime_api_url = self._ensure_trailing_slash(
183+
realtime_api_url or DEFAULT_REALTIME_API_URL
184+
)
185+
self.analytics_url = (
186+
self._ensure_trailing_slash(analytics_url) if analytics_url else None
189187
)
190-
191-
if analytics_url and not analytics_url.endswith("/"):
192-
analytics_url = f"{analytics_url}/"
193-
self.analytics_url = analytics_url
194188

195189
self.request_timeout_seconds = request_timeout_seconds
196190
self.session.mount(self.api_url, HTTPAdapter(max_retries=retries))
@@ -219,6 +213,10 @@ def __init__(
219213
event_processor_config=event_processor_config,
220214
)
221215

216+
@staticmethod
217+
def _ensure_trailing_slash(url: str) -> str:
218+
return url if url.endswith("/") else f"{url}/"
219+
222220
def _initialise_analytics(
223221
self,
224222
environment_key: str,

‎tests/test_flagsmith.py‎

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,14 +1216,59 @@ def test_flagsmith_posts_analytics_to_analytics_url_when_set(
12161216

12171217
# Then exactly one analytics POST landed on the override host (with the
12181218
# trailing slash applied), carried the tracked feature payload, and the
1219-
# Edge Proxy never received an analytics request.
1220-
analytics_calls = [
1221-
call for call in responses.calls if call.request.method == "POST"
1219+
# Edge Proxy never received an analytics request. We filter by the exact
1220+
# analytics URL rather than counting all POSTs, because the module-global
1221+
# analytics session can leak background requests from other tests.
1222+
analytics_posts = [
1223+
call
1224+
for call in responses.calls
1225+
if call.request.method == "POST" and call.request.url == expected_analytics_url
12221226
]
1223-
assert len(analytics_calls) == 1
1224-
request = analytics_calls[0].request
1225-
assert request.url == expected_analytics_url
1226-
assert "edge-proxy" not in request.url
1227+
assert len(analytics_posts) == 1
1228+
request = analytics_posts[0].request
12271229
assert request.body is not None
12281230
assert json.loads(request.body) == {"some_feature": 1}
12291231
assert request.headers["X-Environment-Key"] == api_key
1232+
assert not [
1233+
call
1234+
for call in responses.calls
1235+
if call.request.method == "POST" and "edge-proxy" in call.request.url
1236+
]
1237+
1238+
1239+
@responses.activate()
1240+
def test_flagsmith_posts_analytics_to_api_url_when_analytics_url_unset(
1241+
api_key: str, flags_json: str, mocker: MockerFixture
1242+
) -> None:
1243+
# Given a Flagsmith client with analytics enabled but no analytics_url
1244+
# override. This is the backwards-compatible default: analytics must keep
1245+
# posting to <api_url>/analytics/flags/, derived from api_url alone.
1246+
#
1247+
# As above, swap the FuturesSession for a synchronous requests.Session so
1248+
# the analytics POST is observable on the test thread.
1249+
mocker.patch("flagsmith.analytics.session", requests.Session())
1250+
flagsmith = Flagsmith(
1251+
environment_key=api_key,
1252+
api_url="http://core-api.flagsmith.com/api/v1/",
1253+
enable_analytics=True,
1254+
)
1255+
1256+
expected_analytics_url = "http://core-api.flagsmith.com/api/v1/analytics/flags/"
1257+
responses.add(method="GET", url=flagsmith.environment_flags_url, body=flags_json)
1258+
responses.add(method="POST", url=expected_analytics_url, status=200)
1259+
1260+
# When the evaluation API is exercised and analytics flushed deterministically.
1261+
flags = flagsmith.get_environment_flags()
1262+
assert flags.is_feature_enabled("some_feature") is True
1263+
assert flagsmith._analytics_processor is not None
1264+
flagsmith._analytics_processor.flush()
1265+
1266+
# Then exactly one analytics POST landed on the api_url-derived endpoint.
1267+
# Filter by the exact URL to stay robust against background requests leaked
1268+
# by the module-global analytics session in other tests.
1269+
analytics_posts = [
1270+
call
1271+
for call in responses.calls
1272+
if call.request.method == "POST" and call.request.url == expected_analytics_url
1273+
]
1274+
assert len(analytics_posts) == 1

0 commit comments

Comments
 (0)