"""Test delle rotte /visore/*.js di camera_service e della pagina che le usa (#122). Uso: python -m pytest scripts/tests/test_visore_rotte.py -q Dipende da: venv con fastapi, httpx, opencv (come test_camera_service.py). image_viewer.js lo scrive un altro piano (V1): se manca nei sorgenti il test della rotta usa una cartella temporanea con file finti. """ import importlib.util import re from pathlib import Path import pytest from fastapi.testclient import TestClient MODULO = Path(__file__).resolve().parents[1] / "camera_service.py" NOMI = ("image_viewer.js", "save_image.js", "vision_overlay.js") def _carica(): spec = importlib.util.spec_from_file_location("camera_service", MODULO) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod @pytest.fixture def client(tmp_path): mod = _carica() with TestClient(mod.create_app(tmp_path)) as c: c.mod = mod yield c @pytest.fixture def cartella_finta(client, tmp_path): # file finti in una cartella temporanea: la rotta si prova senza dipendere da image_viewer.js del frontend d = tmp_path / "js" d.mkdir() for n in NOMI: (d / n).write_text("/* finto " + n + " */\n", encoding="utf-8") client.mod._CARTELLE_VISORE[:] = [d] return d @pytest.mark.parametrize("nome", NOMI) def test_rotta_serve_il_file(client, cartella_finta, nome): r = client.get("/visore/" + nome) assert r.status_code == 200 assert r.headers["content-type"].startswith("application/javascript") assert r.content == (cartella_finta / nome).read_bytes() @pytest.mark.parametrize("nome", ["altro.js", "camera_service.py", "..%2Fcamera_service.py", "image_viewer.JS", "image_viewer.js.map"]) def test_altri_nomi_danno_404(client, cartella_finta, nome): assert client.get("/visore/" + nome).status_code == 404 def test_file_mancante_nella_cartella_da_404(client, tmp_path): client.mod._CARTELLE_VISORE[:] = [tmp_path / "vuota"] assert client.get("/visore/save_image.js").status_code == 404 def test_cartelle_di_default_sono_static_js_del_frontend(client): # sviluppo: sorgenti del frontend; pacchetto Nuitka: static/ accanto al modulo (build.ps1 la include) cartelle = _carica()._CARTELLE_VISORE assert any(c.parts[-5:] == ("src", "frontend", "flask_app", "static", "js") for c in cartelle) assert any(c.parts[-2:] == ("static", "js") and c.parent.parent == MODULO.parent for c in cartelle) @pytest.mark.parametrize("nome", ("save_image.js", "vision_overlay.js", "image_viewer.js")) def test_file_reali_del_frontend(client, nome): reale = next((c / nome for c in client.mod._CARTELLE_VISORE if (c / nome).is_file()), None) if reale is None: pytest.skip(nome + " non e' ancora nei sorgenti del frontend (lo scrive il piano V1)") r = client.get("/visore/" + nome) assert r.status_code == 200 and r.content == reale.read_bytes() @pytest.mark.parametrize("rotta", ("/acquisizione", "/calibrazione")) def test_pagina_usa_quattro_visori_e_i_tre_script(client, rotta): html = client.get(rotta).text assert html.count("