From 57ccbf16c1e027fa758e9afd0ccc52507f45d616 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Fri, 22 May 2026 10:17:52 +0200 Subject: [PATCH 1/3] Handle api_key alias in flags token assertions --- src/posthog_test_harness/actions.py | 8 +++++++- tests/test_feature_flag_support.py | 24 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/posthog_test_harness/actions.py b/src/posthog_test_harness/actions.py index c971670..71d0f8f 100644 --- a/src/posthog_test_harness/actions.py +++ b/src/posthog_test_harness/actions.py @@ -784,13 +784,19 @@ async def execute(self, params: Dict[str, Any], ctx: "TestContext") -> Any: # Support dot notation for nested fields (e.g., "person_properties.$device_id") parts = field.split(".") current = body - for part in parts: + for index, part in enumerate(parts): if not isinstance(current, dict): raise AssertionError( f"Cannot traverse into non-dict at '{part}' in field path '{field}'. " f"Value is: {current!r}" ) if part not in current: + # The /flags endpoint accepts api_key as an alias for token. + # Keep the contract's default assertion on token while allowing + # SDKs that send api_key to satisfy the same check. + if index == 0 and part == "token" and "api_key" in current: + current = current["api_key"] + continue raise AssertionError( f"Field '{part}' not found in /flags request body at path '{field}'. " f"Available keys: {list(current.keys())}" diff --git a/tests/test_feature_flag_support.py b/tests/test_feature_flag_support.py index a840b1b..9aaad50 100644 --- a/tests/test_feature_flag_support.py +++ b/tests/test_feature_flag_support.py @@ -8,6 +8,7 @@ AssertActionResultAction, AssertEventCountWithNameAction, AssertEventPropertyInNamedEventAction, + AssertFlagsRequestFieldAction, AssertFlagsRequestQueryParamAction, GetFeatureFlagAction, ) @@ -179,10 +180,31 @@ def test_feature_flag_contract_asserts_top_level_distinct_id_on_flags_request() ) +@pytest.mark.asyncio +@pytest.mark.parametrize("auth_field", ["token", "api_key"]) +async def test_assert_flags_request_field_accepts_token_aliases(auth_field: str) -> None: + ctx = _ctx( + _FakeMockServer( + [ + _make_recorded( + "/flags/", + body_decompressed=json.dumps({auth_field: "phc_test_key"}), + ) + ] + ) + ) + + await AssertFlagsRequestFieldAction().execute( + {"field": "token", "expected": "phc_test_key"}, + ctx, + ) + + def _make_recorded( path: str, query_params: dict | None = None, parsed_events: list | None = None, + body_decompressed: str | None = None, ) -> RecordedRequest: return RecordedRequest( timestamp_ms=0, @@ -191,7 +213,7 @@ def _make_recorded( headers={}, query_params=query_params or {}, body_raw=b"", - body_decompressed=None, + body_decompressed=body_decompressed, parsed_events=parsed_events, response_status=200, response_headers={}, From 0aa95888e2401c57ac518f5a90e1f74fcba2d9b1 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Fri, 22 May 2026 10:21:02 +0200 Subject: [PATCH 2/3] Bump version for flags token alias fix --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- uv.lock | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d58f5b..aa90b86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.5.2] - 2026-05-22 + +### Fixed + +- `/flags` request field assertions now accept `api_key` as an alias for `token`, matching the endpoint's accepted authentication fields. + ## [0.5.1] - 2026-05-04 ### Changed diff --git a/pyproject.toml b/pyproject.toml index a86fb09..1be813c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "posthog-sdk-test-harness" -version = "0.5.1" +version = "0.5.2" description = "Language-agnostic test harness for validating PostHog SDK compliance" readme = "README.md" requires-python = "==3.12.12" diff --git a/uv.lock b/uv.lock index aac720d..f983cdc 100644 --- a/uv.lock +++ b/uv.lock @@ -333,7 +333,7 @@ wheels = [ [[package]] name = "posthog-sdk-test-harness" -version = "0.5.1" +version = "0.5.2" source = { editable = "." } dependencies = [ { name = "aiohttp" }, From b8f5391908321b217069e434aa6f5d249025c8b9 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Fri, 22 May 2026 10:23:22 +0200 Subject: [PATCH 3/3] Add negative tests for flags auth alias --- tests/test_feature_flag_support.py | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/test_feature_flag_support.py b/tests/test_feature_flag_support.py index 9aaad50..0e898b5 100644 --- a/tests/test_feature_flag_support.py +++ b/tests/test_feature_flag_support.py @@ -200,6 +200,46 @@ async def test_assert_flags_request_field_accepts_token_aliases(auth_field: str) ) +@pytest.mark.asyncio +async def test_assert_flags_request_field_requires_token_or_api_key() -> None: + ctx = _ctx( + _FakeMockServer( + [ + _make_recorded( + "/flags/", + body_decompressed=json.dumps({}), + ) + ] + ) + ) + + with pytest.raises(AssertionError, match="Field 'token' not found"): + await AssertFlagsRequestFieldAction().execute( + {"field": "token", "expected": "phc_test_key"}, + ctx, + ) + + +@pytest.mark.asyncio +async def test_assert_flags_request_field_rejects_mismatched_api_key_alias() -> None: + ctx = _ctx( + _FakeMockServer( + [ + _make_recorded( + "/flags/", + body_decompressed=json.dumps({"api_key": "wrong_key"}), + ) + ] + ) + ) + + with pytest.raises(AssertionError, match="Expected token='phc_test_key', got 'wrong_key'"): + await AssertFlagsRequestFieldAction().execute( + {"field": "token", "expected": "phc_test_key"}, + ctx, + ) + + def _make_recorded( path: str, query_params: dict | None = None,