poolcoach / tests /test_static_cache.py
masterdanh's picture
deploy: snapshot for HF Space
78738de
Raw
History Blame Contribute Delete
2.17 kB
"""Contract Cache-Control của tầng static (31/07/2026 — việc C, gate G5.3).
Nguyên nhân gốc bug tối 30/07: ``app.js`` bị trình duyệt cache hàng giờ sau
deploy → alt không có quỹ đạo cho tới Ctrl+F5. Fix là header
``Cache-Control: no-cache`` trên ``.js``/``.css``/``.html`` — NO-CACHE chứ
không phải no-store: vẫn cho revalidate 304, chỉ cấm dùng bản cũ không hỏi.
Test đọc FILE THẬT trong ``app/static/`` (không cần pooltool — tầng static
không đụng sim), nên nó cũng khoá luôn việc ba file FE còn tồn tại.
"""
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from app import main as app_main
@pytest.fixture
def client():
return TestClient(app_main.app)
@pytest.mark.parametrize("path", ["/", "/app.js", "/style.css"])
def test_static_js_css_html_co_no_cache(client, path):
"""G5.3: ``curl -I`` một file ``.js`` và ``/`` → ``Cache-Control: no-cache``.
``/`` đi qua nhánh html=True (index.html) — nhánh resolve KHÁC file thẳng,
phải kiểm riêng."""
r = client.get(path)
assert r.status_code == 200
assert r.headers.get("cache-control") == "no-cache"
def test_304_van_mang_no_cache(client):
"""no-cache sống bằng revalidate: trình duyệt gửi If-None-Match mỗi lần.
Nếu response 304 rơi mất header thì một số cache trung gian coi như hết
chỉ thị và bug cũ quay lại đúng ở lần thứ hai."""
first = client.get("/app.js")
etag = first.headers.get("etag")
assert etag, "starlette phải trả ETag để revalidate được"
r = client.get("/app.js", headers={"If-None-Match": etag})
assert r.status_code == 304
assert r.headers.get("cache-control") == "no-cache"
def test_api_khong_bi_dinh_header_static(client):
"""Header thuộc TẦNG STATIC, không phải toàn app — /api/health không được
lây (nó là JSON động, chính sách cache của nó là chuyện khác)."""
r = client.get("/api/health")
assert r.status_code == 200
assert r.headers.get("cache-control") != "no-cache"