test: add automated api tester

This commit is contained in:
truetype committed 2026-02-05 11:32:21 +01:00
1 parent 882efeb963
commit 572d551a2c
7 files changed
+113 -4

No files matched your search

+8
View File
@@ -56,6 +56,14 @@ L'URL viene rilevato dalla prima stringa che contiene un link HTTP/HTTPS nel log
La dashboard aggiorna automaticamente lo stato dei tunnel e mostra l'ultimo log per aiutare il debug quando l'URL non è disponibile.
## Push su Gitea con token
Se hai un personal access token Gitea, esportalo come `GITEA_TOKEN` (es. `export GITEA_TOKEN=...`) e lancia `scripts/push-gitea.sh` dalla root del progetto. Lo script leggerà la variabile e spingerà il branch `main` verso `https://gitea.solarpi.net/truetype/dashgradio_tunnel.git` senza richiedere prompt interattivi. Puoi passare un branch diverso come primo argomento (`scripts/push-gitea.sh feature-branch`) e lo script si occuperà di costruire l’URL con il token.
## Test automatico
Esiste uno script `scripts/auto-test.sh` che installa le dipendenze (`requirements.txt`) e lancia `pytest` contro le API principali (`/api/ports`, `/api/tunnels`). Basta eseguire `./scripts/auto-test.sh` dalla root del progetto; lo script fallirà se non trova `GITEA_TOKEN`/comment? Not needed. Sam lengths.
## Politica porte
La parte critica di sicurezza del progetto è la politica che decide quali porte possono essere esposte tramite tunnel. Ci sono due layer di configurazione, entrambi opzionali:
Binary file not shown.
Binary file not shown.
+5 -4
View File
@@ -1,4 +1,5 @@
fastapi==0.115.0
uvicorn==0.30.6
psutil==6.0.0
jinja2==3.1.4
fastapi==0.115.0
uvicorn==0.30.6
psutil==6.0.0
jinja2==3.1.4
pytest==8.4.2
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
echo "Installing dependencies..."
python -m pip install -r requirements.txt >/dev/null
echo "Running pytest..."
python -m pytest tests
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# Helper script that pushes the current branch to the Gitea remote using a personal
# access token stored in $GITEA_TOKEN. Keeps the token out of shell history.
if [[ -z "${GITEA_TOKEN:-}" ]]; then
echo "Missing GITEA_TOKEN (export it before running this script)." >&2
exit 1
fi
readonly REMOTE_URL="https://truetype:${GITEA_TOKEN}@gitea.solarpi.net/truetype/dashgradio_tunnel.git"
readonly BRANCH="${1:-main}"
echo "Pushing branch ${BRANCH} to Gitea..."
git push "${REMOTE_URL}" "${BRANCH}"
+74
View File
@@ -0,0 +1,74 @@
from fastapi.testclient import TestClient
from app import main as dashboard
from app.services import ServiceRecord
client = TestClient(dashboard.app)
class DummyTunnelInfo:
def __init__(self, port: int):
self.port = port
self.command = "gradio-tunneling --port %d" % port
self.pid = 42
self.url = "https://example.com/%d" % port
self.status = "running"
self.exit_code = None
self.last_output = "started"
def test_list_ports(monkeypatch):
monkeypatch.setattr(
dashboard.scanner,
"scan",
lambda: [
ServiceRecord(
port=4444,
protocol="tcp",
service="svc1",
pid=123,
user="alice",
command="cmd",
container="ctr",
local_address="0.0.0.0:4444",
allowed=True,
policy_reason=None,
),
ServiceRecord(
port=2222,
protocol="tcp",
service="svc2",
pid=321,
user="bob",
command="cmd2",
container=None,
local_address="0.0.0.0:2222",
allowed=False,
policy_reason="blocked",
),
],
)
response = client.get("/api/ports")
assert response.status_code == 200
assert response.json()[0]["port"] == 2222
assert response.json()[1]["port"] == 4444
def test_start_tunnel_blocked(monkeypatch):
monkeypatch.setattr(dashboard.policy, "is_port_allowed", lambda port: (False, "blocked"))
response = client.post("/api/tunnels", json={"port": 2222})
assert response.status_code == 403
assert "blocked" in response.json()["detail"]
def test_start_tunnel_success(monkeypatch):
monkeypatch.setattr(dashboard.policy, "is_port_allowed", lambda port: (True, None))
info = DummyTunnelInfo(3333)
monkeypatch.setattr(dashboard.manager, "start_tunnel", lambda port: info)
response = client.post("/api/tunnels", json={"port": 3333})
assert response.status_code == 200
payload = response.json()
assert payload["port"] == 3333
assert payload["url"] == info.url