mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-11-10 20:07:16 +01:00
Booleaness asserts, hoisted imports, fixture(name=...) instead of shadowing arguments, explicit encodings, snake_case names, comparison of bound methods, dead protected-access disables. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWYdwRAtMg7ki6TKxuU
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""Tests for _web_server static serving: SPA fallback and traversal guard.
|
|
|
|
Split out of test_web_server.py for the 250-line cap; the server harness and
|
|
the real_loopback fixture stay in that module and are imported here.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from screen_locker.tests.test_web_server import (
|
|
_PKG,
|
|
_get,
|
|
_make_dist,
|
|
_running,
|
|
real_loopback_fixture,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
__all__ = ["real_loopback_fixture"]
|
|
|
|
|
|
class TestStaticServing:
|
|
"""The built bundle is served with an SPA fallback and a traversal guard."""
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _network(self, real_loopback: None) -> None:
|
|
"""Every test in this class talks to the server over real HTTP."""
|
|
|
|
def test_index_is_served_at_the_root(self, tmp_path: Path) -> None:
|
|
"""/ serves index.html."""
|
|
with patch(f"{_PKG}.WEB_DIST", _make_dist(tmp_path)), _running() as port:
|
|
status, body, ctype = _get(port, "/")
|
|
assert status == 200
|
|
assert b"INDEX" in body
|
|
assert ctype.startswith("text/html")
|
|
|
|
def test_an_asset_is_served_with_its_own_type(self, tmp_path: Path) -> None:
|
|
"""A real file is served rather than the SPA fallback."""
|
|
with patch(f"{_PKG}.WEB_DIST", _make_dist(tmp_path)), _running() as port:
|
|
status, body, ctype = _get(port, "/app.css")
|
|
assert status == 200
|
|
assert body == b"body{}"
|
|
assert ctype.startswith("text/css")
|
|
|
|
def test_a_binary_asset_gets_no_charset(self, tmp_path: Path) -> None:
|
|
"""A charset on image/png would be wrong; only text types get one."""
|
|
with patch(f"{_PKG}.WEB_DIST", _make_dist(tmp_path)), _running() as port:
|
|
status, body, ctype = _get(port, "/icon.png")
|
|
assert status == 200
|
|
assert body.startswith(b"\x89PNG")
|
|
assert ctype == "image/png"
|
|
|
|
def test_an_unknown_route_falls_back_to_index(self, tmp_path: Path) -> None:
|
|
"""SPA routes are handled by the bundle, not by the server."""
|
|
with patch(f"{_PKG}.WEB_DIST", _make_dist(tmp_path)), _running() as port:
|
|
status, body, _ = _get(port, "/why/2026-08-29")
|
|
assert status == 200
|
|
assert b"INDEX" in body
|
|
|
|
def test_traversal_never_escapes_the_bundle(self, tmp_path: Path) -> None:
|
|
"""A ../ path is refused, not resolved against the filesystem."""
|
|
secret = tmp_path / "secret.txt"
|
|
secret.write_text("do not serve me", encoding="utf-8")
|
|
with patch(f"{_PKG}.WEB_DIST", _make_dist(tmp_path)), _running() as port:
|
|
status, body, _ = _get(port, "/../secret.txt")
|
|
assert status == 200
|
|
assert b"do not serve me" not in body
|
|
|
|
def test_missing_bundle_says_how_to_build_it(self, tmp_path: Path) -> None:
|
|
"""404 carries the build command instead of an empty page."""
|
|
dist = _make_dist(tmp_path, with_index=False)
|
|
with patch(f"{_PKG}.WEB_DIST", dist), _running() as port:
|
|
status, body, _ = _get(port, "/")
|
|
assert status == 404
|
|
assert b"npm --prefix web run build" in body
|