Skip to content

Commit 5392fb3

Browse files
committed
test(http): pin the edges the caching and forwarding fixes actually changed
test_json_caching uses a dict body, so it passes under the old `if self._json_data is None` sentinel. Add a `null`-body case and a non-JSON `is_json` case, which do not. Also cover OutboundApplicationByToken: it builds its own key-less client, and dropping the forwarded verbose/store arguments left the suite green.
1 parent 4677961 commit 5392fb3

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

tests/management/test_outbound_application.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,3 +958,60 @@ async def test_fetch_tenant_token_failure(self, client_factory):
958958
"tenant789",
959959
)
960960
)
961+
962+
963+
class TestOutboundApplicationByTokenVerbose:
964+
async def test_by_token_response_reaches_client_get_last_response(self, client_factory):
965+
"""The by-token client builds its own key-less HTTPClient.
966+
967+
It has to be handed the owning client's verbose flag and last-response store,
968+
or its responses are invisible to DescopeClient.get_last_response().
969+
"""
970+
client = client_factory.make(
971+
PROJECT_ID,
972+
PUBLIC_KEY_DICT,
973+
False,
974+
management_key="test-mgmt-key",
975+
verbose=True,
976+
)
977+
if client_factory.mode == "async":
978+
client._raw._license_attempted = True
979+
980+
response = make_response(TOKEN_RESPONSE)
981+
response.headers = {"cf-ray": "by-token-ray"}
982+
983+
with client.mock_mgmt_by_token_post(response):
984+
await client.invoke(
985+
client.mgmt.outbound_application_by_token.fetch_token_by_scopes(
986+
DUMMY_TOKEN,
987+
"app123",
988+
"user456",
989+
["read"],
990+
)
991+
)
992+
993+
last_resp = client.get_last_response()
994+
assert last_resp is not None
995+
assert last_resp.headers.get("cf-ray") == "by-token-ray"
996+
997+
async def test_by_token_not_captured_when_verbose_disabled(self, client_factory):
998+
client = client_factory.make(
999+
PROJECT_ID,
1000+
PUBLIC_KEY_DICT,
1001+
False,
1002+
management_key="test-mgmt-key",
1003+
)
1004+
if client_factory.mode == "async":
1005+
client._raw._license_attempted = True
1006+
1007+
with client.mock_mgmt_by_token_post(make_response(TOKEN_RESPONSE)):
1008+
await client.invoke(
1009+
client.mgmt.outbound_application_by_token.fetch_token_by_scopes(
1010+
DUMMY_TOKEN,
1011+
"app123",
1012+
"user456",
1013+
["read"],
1014+
)
1015+
)
1016+
1017+
assert client.get_last_response() is None

tests/test_http_client.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,39 @@ def test_json_caching(self):
6464
# json() should only be called once on the underlying response
6565
assert mock_response.json.call_count == 1
6666

67+
def test_null_json_body_parses_once(self):
68+
"""A `null` body is a real cached value, not a miss to retry.
69+
70+
The old `if self._json_data is None` sentinel re-parsed on every access here,
71+
which test_json_caching cannot catch because its body is a dict.
72+
"""
73+
mock_response = Mock()
74+
mock_response.json.return_value = None
75+
76+
resp = DescopeResponse(mock_response)
77+
78+
assert resp.json() is None
79+
assert resp.json() is None
80+
assert mock_response.json.call_count == 1
81+
82+
def test_is_json_does_not_reparse_non_json_body(self):
83+
"""is_json probes by parsing, so an unparseable body must not re-probe."""
84+
body = "<html>502</html>"
85+
mock_response = Mock()
86+
mock_response.json.side_effect = json.JSONDecodeError("Expecting value", body, 0)
87+
mock_response.text = body
88+
89+
resp = DescopeResponse(mock_response)
90+
91+
assert resp.is_json is False
92+
assert resp.is_json is False
93+
assert resp.is_json is False
94+
assert mock_response.json.call_count == 1
95+
96+
# A failed parse is not cached, so json() itself still raises every time.
97+
with self.assertRaises(json.JSONDecodeError):
98+
resp.json()
99+
67100
def test_dict_like_values_items(self):
68101
"""Test that values() and items() work correctly."""
69102
mock_response = Mock()

0 commit comments

Comments
 (0)