File size: 2,168 Bytes
78738de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""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"