maris-ai-master / core-python /tests /test_huggingface_human_training_space.py
MarisUK's picture
Maris AI model sync
f440f03 verified
"""Tests for the standalone Maris human training Space app."""
from __future__ import annotations
import importlib
import json
import sys
import tempfile
from pathlib import Path
from fastapi.testclient import TestClient
REPO_ROOT = Path(__file__).resolve().parents[2]
if str(REPO_ROOT) not in sys.path:
sys.path.insert(0, str(REPO_ROOT))
human_training_space_app = importlib.import_module("huggingface_human_training_space.app")
def test_index_contains_private_space_entry_and_role_sections() -> None:
client = TestClient(human_training_space_app.app)
response = client.get("/")
assert response.status_code == 200
assert "Maris AI Human Training" in response.text
assert "Maris AI logo" in response.text
assert "Private Space" in response.text
assert "Workspace ir atvērts uzreiz" in response.text
assert 'id="login-form"' not in response.text
assert 'id="register-form"' not in response.text
assert 'id="register-role"' not in response.text
assert "owner" in response.text
assert "secretary" in response.text
assert "trainee" in response.text
assert "Platformas dokumentācija" in response.text
assert 'class="section active" id="workspace-shell"' in response.text
assert 'id="human_hub_model_id"' in response.text
assert 'id="human_continue_from_latest_artefact"' in response.text
assert 'id="human-template-select"' in response.text
assert 'id="human-publish-button"' in response.text
assert "Ātra starta vadība" in response.text
assert "Staging pārskats" in response.text
def test_runtime_endpoint_exposes_roles_and_docs() -> None:
client = TestClient(human_training_space_app.app)
response = client.get("/api/runtime")
assert response.status_code == 200
body = response.json()
assert body["service"] == "maris-human-training-space"
assert set(body["roles"]) == {"owner", "secretary", "trainee", "user"}
assert any(item["title"] == "Onboarding guide" for item in body["documentation"])
assert "customer-support-lv" in body["templates"]
assert body["templates"]["customer-support-lv"]["payload"]["profile_facts"]
assert body["training"]["defaults"]["hub_model_id"] == "MarisUK/maris-ai-text"
assert isinstance(body["training"]["model_choices"], list)
assert body["training"]["model_choices"][0]["id"]
assert body["training"]["model_choices"][0]["label"]
assert body["auth_required"] is False
assert body["private_session"]["user"]["role"] == "owner"
def test_maybe_start_automatic_training_starts_with_human_space_defaults(
monkeypatch, tmp_path: Path
) -> None:
calls: list[dict[str, object]] = []
monkeypatch.setenv("MARIS_HUMAN_TRAINING_AUTO_TRAIN", "true")
monkeypatch.setattr(human_training_space_app, "PERSISTENT_DIR", tmp_path)
monkeypatch.setattr(
human_training_space_app,
"has_completed_training_artifacts",
lambda output_dir: False,
)
monkeypatch.setattr(
human_training_space_app,
"_start_training_process",
lambda request: (
calls.append(request.model_dump()) or {"pid": 77, "log_path": "/tmp/human-train.log"}
),
)
human_training_space_app._maybe_start_automatic_training()
assert len(calls) == 1
assert calls[0]["dataset_repo"] == human_training_space_app.DEFAULT_DATASET_REPO
assert calls[0]["model_repo"] == human_training_space_app.DEFAULT_HUB_MODEL_ID
assert calls[0]["model_preset"] == "balanced"
assert calls[0]["continue_from_latest_artifact"] is True
def test_register_and_login_flow(monkeypatch, tmp_path: Path) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(
human_training_space_app,
"USERS_FILE",
tmp_path / "human-training-users.json",
)
human_training_space_app.SESSION_STORE.clear()
register_response = client.post(
"/api/auth/register",
json={
"full_name": "Māris Ozols",
"email": "maris@example.com",
"password": "drosha-parole-123",
"role": "owner",
},
)
assert register_response.status_code == 200
register_body = register_response.json()
assert register_body["user"]["role"] == "owner"
assert register_body["role_guide"]["label"] == "Owner"
assert register_body["token"]
login_response = client.post(
"/api/auth/login",
json={
"email": "maris@example.com",
"password": "drosha-parole-123",
},
)
assert login_response.status_code == 200
login_body = login_response.json()
assert login_body["user"]["email"] == "maris@example.com"
assert login_body["platform"]["examples"]
def test_register_with_storage_fallback(monkeypatch) -> None:
client = TestClient(human_training_space_app.app)
original_users_file = human_training_space_app.USERS_FILE
fallback_root = (
Path(tempfile.gettempdir()) / human_training_space_app.USER_STORE_FALLBACK_DIRNAME
)
fallback_file = fallback_root / original_users_file.name
if fallback_file.exists():
fallback_file.unlink()
original_path_mkdir = Path.mkdir
def fail_default_data_mkdir(self: Path, *args, **kwargs) -> None:
if self == original_users_file.parent:
raise PermissionError("read-only")
return original_path_mkdir(self, *args, **kwargs)
monkeypatch.setattr(human_training_space_app, "USERS_FILE", original_users_file)
monkeypatch.setattr(Path, "mkdir", fail_default_data_mkdir)
human_training_space_app.SESSION_STORE.clear()
response = client.post(
"/api/auth/register",
json={
"full_name": "Māris Ozols",
"email": "maris-fallback@example.com",
"password": "drosha-parole-123",
"role": "owner",
},
)
assert response.status_code == 200
assert fallback_file.exists()
payload = json.loads(fallback_file.read_text(encoding="utf-8"))
assert payload["maris-fallback@example.com"]["role"] == "owner"
def test_login_rejects_invalid_password(monkeypatch, tmp_path: Path) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(
human_training_space_app,
"USERS_FILE",
tmp_path / "human-training-users.json",
)
human_training_space_app.SESSION_STORE.clear()
client.post(
"/api/auth/register",
json={
"full_name": "Māris Ozols",
"email": "maris@example.com",
"password": "drosha-parole-123",
"role": "owner",
},
)
response = client.post(
"/api/auth/login",
json={
"email": "maris@example.com",
"password": "nepareiza-parole",
},
)
assert response.status_code == 401
assert response.json()["detail"] == "Nepareizs e-pasts vai parole."
def test_human_training_build_allows_private_space_without_session(
monkeypatch, tmp_path: Path
) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(human_training_space_app, "PERSISTENT_DIR", tmp_path)
response = client.post(
"/api/human-training/build",
json={
"dataset_repo": "example-user/memory-dataset",
"hub_model_id": "example-user/custom-model",
"profile_facts": ["Man vajag profesionālu latviešu valodu."],
},
)
assert response.status_code == 200
assert (
response.json()["manifest"]["training_request"]["hub_model_id"]
== "example-user/custom-model"
)
def test_human_training_build_requires_session_when_auth_enabled(
monkeypatch, tmp_path: Path
) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(human_training_space_app, "AUTH_REQUIRED", True)
monkeypatch.setattr(
human_training_space_app, "USERS_FILE", tmp_path / "human-training-users.json"
)
monkeypatch.setattr(human_training_space_app, "PERSISTENT_DIR", tmp_path)
human_training_space_app.SESSION_STORE.clear()
response = client.post(
"/api/human-training/build",
json={
"dataset_repo": "example-user/memory-dataset",
"hub_model_id": "example-user/custom-model",
"profile_facts": ["Man vajag profesionālu latviešu valodu."],
},
)
assert response.status_code == 401
def test_human_training_build_stages_manifest_for_private_space(
monkeypatch, tmp_path: Path
) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(human_training_space_app, "PERSISTENT_DIR", tmp_path)
response = client.post(
"/api/human-training/build",
json={
"dataset_repo": "example-user/memory-dataset",
"hub_model_id": "example-user/custom-model",
"continue_model_path": "runs/latest",
"profile_facts": ["Man vajag profesionālu latviešu valodu."],
},
)
assert response.status_code == 200
body = response.json()
assert body["manifest"]["training_request"]["hub_model_id"] == "example-user/custom-model"
assert body["manifest"]["training_request"]["continue_model_path"] == "runs/latest"
def test_human_training_build_stages_manifest_for_logged_in_user_when_auth_enabled(
monkeypatch, tmp_path: Path
) -> None:
client = TestClient(human_training_space_app.app)
monkeypatch.setattr(human_training_space_app, "AUTH_REQUIRED", True)
monkeypatch.setattr(
human_training_space_app, "USERS_FILE", tmp_path / "human-training-users.json"
)
monkeypatch.setattr(human_training_space_app, "PERSISTENT_DIR", tmp_path)
human_training_space_app.SESSION_STORE.clear()
register_response = client.post(
"/api/auth/register",
json={
"full_name": "Māris Ozols",
"email": "maris@example.com",
"password": "drosha-parole-123",
"role": "owner",
},
)
token = register_response.json()["token"]
response = client.post(
"/api/human-training/build",
headers={"X-Session-Token": token},
json={
"dataset_repo": "example-user/memory-dataset",
"hub_model_id": "example-user/custom-model",
"continue_model_path": "runs/latest",
"profile_facts": ["Man vajag profesionālu latviešu valodu."],
},
)
assert response.status_code == 200
body = response.json()
assert body["manifest"]["training_request"]["hub_model_id"] == "example-user/custom-model"
assert body["manifest"]["training_request"]["continue_model_path"] == "runs/latest"