feat: vendor ghostty-web UMD build and WASM binary

- Copy ghostty-web UMD build (638 KB) to muxplex/frontend/vendor/ghostty-web.js
- Copy ghostty-vt WASM binary (413 KB) to muxplex/frontend/vendor/ghostty-vt.wasm
- Add .wasm to _STATIC_EXTENSIONS in auth.py to bypass auth for WASM files
- Add test_vendor_ghostty.py with 5 tests for file existence, size, MIME type, and HTTP serving

Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
This commit is contained in:
Ken
2026-05-28 06:12:49 +00:00
parent b72d82624d
commit 29aabcfd4f
4 changed files with 111 additions and 0 deletions
+1
View File
@@ -155,6 +155,7 @@ _STATIC_EXTENSIONS = {
".woff2", ".woff2",
".ttf", ".ttf",
".map", ".map",
".wasm",
} }
# Socket-level localhost addresses — cannot be forged via HTTP headers # Socket-level localhost addresses — cannot be forged via HTTP headers
BIN
View File
Binary file not shown.
File diff suppressed because one or more lines are too long
+97
View File
@@ -0,0 +1,97 @@
"""
Tests for vendored ghostty-web files.
Verifies that the ghostty-web UMD build and WASM binary are present
in the vendor directory and servable by the static file server.
"""
import mimetypes
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from muxplex.main import app
_VENDOR_DIR = Path(__file__).resolve().parent.parent / "frontend" / "vendor"
# ---------------------------------------------------------------------------
# File-existence tests (no server required)
# ---------------------------------------------------------------------------
def test_ghostty_web_js_exists():
"""muxplex/frontend/vendor/ghostty-web.js must exist."""
path = _VENDOR_DIR / "ghostty-web.js"
assert path.is_file(), f"Expected vendored JS at {path}"
def test_ghostty_vt_wasm_exists():
"""muxplex/frontend/vendor/ghostty-vt.wasm must exist."""
path = _VENDOR_DIR / "ghostty-vt.wasm"
assert path.is_file(), f"Expected vendored WASM at {path}"
def test_ghostty_vt_wasm_size():
"""ghostty-vt.wasm should be approximately 400-450 KB."""
path = _VENDOR_DIR / "ghostty-vt.wasm"
if not path.is_file():
pytest.skip("WASM file not yet vendored")
size_kb = path.stat().st_size / 1024
assert 350 < size_kb < 500, (
f"WASM file size {size_kb:.0f} KB outside expected range 350-500 KB"
)
# ---------------------------------------------------------------------------
# MIME type test (Python mimetypes module — used by Starlette)
# ---------------------------------------------------------------------------
def test_wasm_mime_type_registered():
"""Python mimetypes must map .wasm to application/wasm."""
mime, _ = mimetypes.guess_type("file.wasm")
assert mime == "application/wasm", f"Expected application/wasm, got {mime}"
# ---------------------------------------------------------------------------
# Static-serving tests (requires test client)
# ---------------------------------------------------------------------------
@pytest.fixture()
def client(tmp_path, monkeypatch):
"""Authenticated TestClient that patches startup paths."""
tmp_state_dir = tmp_path / "state"
tmp_state_path = tmp_state_dir / "state.json"
monkeypatch.setattr("muxplex.state.STATE_DIR", tmp_state_dir)
monkeypatch.setattr("muxplex.state.STATE_PATH", tmp_state_path)
tmp_pid_dir = tmp_path / "ttyd"
tmp_pid_path = tmp_pid_dir / "ttyd.pid"
monkeypatch.setattr("muxplex.ttyd.TTYD_PID_DIR", tmp_pid_dir)
monkeypatch.setattr("muxplex.ttyd.TTYD_PID_PATH", tmp_pid_path)
async def _mock_kill_orphan():
return False
monkeypatch.setattr("muxplex.main.kill_orphan_ttyd", _mock_kill_orphan)
async def noop_poll_loop() -> None:
pass
monkeypatch.setattr("muxplex.main._poll_loop", noop_poll_loop)
with TestClient(app) as c:
yield c
def test_ghostty_vt_wasm_served_with_correct_mime(client):
"""GET /vendor/ghostty-vt.wasm must return application/wasm content-type."""
wasm_path = _VENDOR_DIR / "ghostty-vt.wasm"
if not wasm_path.is_file():
pytest.skip("WASM file not yet vendored")
resp = client.get("/vendor/ghostty-vt.wasm")
assert resp.status_code == 200, f"Expected 200, got {resp.status_code}"
assert "application/wasm" in resp.headers.get("content-type", "")