The Dockerfile copied PRD.md, which is not in the repository, so a clean clone could not build at all. It also installed node and npm from Ubuntu 24 (node 18) to build a Vite 8 front end that needs node 20.19 or newer, and it built the interface into a directory nothing served. The build is now two stages: node:22 builds the interface, the CUDA runtime image installs the package and carries the built files. The API serves them when ELY_EYE_UI_DIR points at a directory that exists, and refuses to start when it is set but empty, naming the build command. The front end already calls /api/... on its own origin, so same-origin serving needs no client change.
42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
"""The container story only holds if a built interface is actually served."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from ely_eye import api as api_module
|
|
from ely_eye.config import Settings
|
|
|
|
|
|
def _client(settings: Settings, monkeypatch) -> TestClient:
|
|
monkeypatch.setattr(api_module, "get_settings", lambda: settings)
|
|
return TestClient(api_module.create_app())
|
|
|
|
|
|
def test_a_built_interface_is_served_from_the_api_origin(tmp_path: Path, monkeypatch) -> None:
|
|
ui = tmp_path / "dist"
|
|
ui.mkdir()
|
|
(ui / "index.html").write_text("<html><body>ely-eye</body></html>", encoding="utf-8")
|
|
settings = Settings(home=tmp_path / "home", ui_dir=ui)
|
|
client = _client(settings, monkeypatch)
|
|
answer = client.get("/")
|
|
assert answer.status_code == 200 and "ely-eye" in answer.text
|
|
assert client.get("/api/status").status_code == 200
|
|
|
|
|
|
def test_a_ui_directory_that_was_never_built_names_the_fix(tmp_path: Path, monkeypatch) -> None:
|
|
settings = Settings(home=tmp_path / "home", ui_dir=tmp_path / "dist")
|
|
monkeypatch.setattr(api_module, "get_settings", lambda: settings)
|
|
with pytest.raises(SystemExit, match="npm run build"):
|
|
api_module.create_app()
|
|
|
|
|
|
def test_no_ui_directory_means_the_api_alone_answers(tmp_path: Path, monkeypatch) -> None:
|
|
settings = Settings(home=tmp_path / "home")
|
|
client = _client(settings, monkeypatch)
|
|
assert client.get("/").status_code == 404
|
|
assert client.get("/api/status").status_code == 200
|