44"""
55import pytest
66from fastapi .testclient import TestClient
7- from app .main import _request_counts
87import sys , os
98sys .path .insert (0 , os .path .dirname (os .path .dirname (__file__ )))
10- from app . main import app
9+ from app import main as app_main
1110
12- client = TestClient (app )
11+ client = TestClient (app_main .app )
12+
13+
14+ @pytest .fixture (autouse = True )
15+ def reset_rate_limit_state ():
16+ app_main ._request_counts .clear ()
17+ yield
18+ app_main ._request_counts .clear ()
1319
1420
1521# ── Fixtures ──────────────────────────────────────────────────────────────────
@@ -152,6 +158,29 @@ def test_health():
152158 assert r .json ()["status" ] == "ok"
153159
154160
161+ def test_rate_limit_headers_on_success_response ():
162+ r = client .get ("/" )
163+ assert r .status_code == 200
164+ assert r .headers ["X-RateLimit-Limit" ] == str (app_main .RATE_LIMIT )
165+ assert r .headers ["X-RateLimit-Remaining" ] == str (app_main .RATE_LIMIT )
166+
167+
168+ def test_rate_limit_returns_429_with_retry_after_header ():
169+ payload = {"code" : "print('hello')" , "language" : "python" }
170+
171+ for expected_remaining in range (app_main .RATE_LIMIT - 1 , - 1 , - 1 ):
172+ r = client .post ("/debugging/" , json = payload )
173+ assert r .status_code == 200
174+ assert r .headers ["X-RateLimit-Limit" ] == str (app_main .RATE_LIMIT )
175+ assert r .headers ["X-RateLimit-Remaining" ] == str (expected_remaining )
176+
177+ r = client .post ("/debugging/" , json = payload )
178+ assert r .status_code == 429
179+ assert r .headers ["Retry-After" ] == str (app_main .RATE_LIMIT_WINDOW_SECONDS )
180+ assert r .headers ["X-RateLimit-Limit" ] == str (app_main .RATE_LIMIT )
181+ assert r .headers ["X-RateLimit-Remaining" ] == "0"
182+
183+
155184# ── Explanation ───────────────────────────────────────────────────────────────
156185def test_explanation_python ():
157186 r = client .post ("/explanation/" , json = {"code" : PYTHON_CLEAN , "language" : "python" })
@@ -194,7 +223,7 @@ def test_explanation_empty_code():
194223def test_explanation_too_long ():
195224 r = client .post ("/explanation/" , json = {"code" : "x" * 60000 })
196225 assert r .status_code == 422
197-
226+
198227def test_explanation_typescript ():
199228 r = client .post ("/explanation/" , json = {"code" : TS_CODE , "language" : "typescript" })
200229 assert r .status_code == 200
@@ -422,6 +451,6 @@ def test_unicode_code():
422451 assert r .status_code == 200
423452
424453
425- _request_counts . clear ()
454+ def test_single_line_code ():
426455 r = client .post ("/analyze/" , json = {"code" : "print('hello')" })
427- assert r .status_code == 200
456+ assert r .status_code == 200
0 commit comments