dd2ebf863a
Security hardening: CORS lockdown, rate limiting middleware con sliding window e eviction IP stale, security headers (CSP, HSTS, X-Frame-Options), session cookie hardening, filename sanitization upload. i18n completion: internazionalizzati barcode.js e csv-export.js con bridge window.BARCODE_I18N/CSV_I18N, aggiornati .po IT/EN con 27 nuove stringhe. Tablet UX: touch target 44px per dispositivi coarse pointer. Test suite: 101 test totali (76 server + 25 client), copertura completa di tutti i router API, autenticazione, ruoli, CRUD, SPC, file upload, security integration. Infrastruttura SQLite async in-memory con fixtures. Fix critici: MissingGreenlet in recipe_service (selectinload eager), route ordering tasks.py, auth_service bcrypt diretto, Measurement.id Integer per SQLite. Documentazione: API.md (riferimento completo 40+ endpoint), DEPLOYMENT.md (guida produzione con Docker/Nginx/SSL), USER_GUIDE.md (manuale utente per ruolo). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
108 lines
3.2 KiB
Python
108 lines
3.2 KiB
Python
"""Tests for settings router (/api/settings)."""
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from models.setting import SystemSetting
|
|
from models.user import User
|
|
from tests.conftest import auth_headers
|
|
|
|
|
|
class TestGetSettings:
|
|
"""GET /api/settings/ tests."""
|
|
|
|
async def test_get_settings(
|
|
self,
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
db_session: AsyncSession,
|
|
):
|
|
"""Authenticated user can retrieve settings."""
|
|
# Seed a setting
|
|
setting = SystemSetting(
|
|
setting_key="test_setting",
|
|
setting_value="test_value",
|
|
setting_type="string",
|
|
)
|
|
db_session.add(setting)
|
|
await db_session.flush()
|
|
|
|
resp = await client.get(
|
|
"/api/settings/", headers=auth_headers(admin_user)
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert isinstance(data, dict)
|
|
assert data.get("test_setting") == "test_value"
|
|
|
|
async def test_get_settings_empty(
|
|
self, client: AsyncClient, maker_user: User
|
|
):
|
|
"""Empty settings returns empty dict."""
|
|
resp = await client.get(
|
|
"/api/settings/", headers=auth_headers(maker_user)
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json() == {} or isinstance(resp.json(), dict)
|
|
|
|
async def test_get_setting_by_key(
|
|
self,
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
db_session: AsyncSession,
|
|
):
|
|
"""Settings dict contains specific key after creation."""
|
|
setting = SystemSetting(
|
|
setting_key="csv_delimiter",
|
|
setting_value=";",
|
|
setting_type="string",
|
|
)
|
|
db_session.add(setting)
|
|
await db_session.flush()
|
|
|
|
resp = await client.get(
|
|
"/api/settings/", headers=auth_headers(admin_user)
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["csv_delimiter"] == ";"
|
|
|
|
|
|
class TestUpdateSettings:
|
|
"""PUT /api/settings/ tests."""
|
|
|
|
async def test_update_settings(
|
|
self, client: AsyncClient, admin_user: User
|
|
):
|
|
"""Admin can update/create settings."""
|
|
resp = await client.put(
|
|
"/api/settings/",
|
|
headers=auth_headers(admin_user),
|
|
json={
|
|
"company_name": "Tielogic Srl",
|
|
"csv_delimiter": ",",
|
|
},
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["message"].startswith("Updated")
|
|
assert "company_name" in data["updated_keys"]
|
|
assert "csv_delimiter" in data["updated_keys"]
|
|
|
|
# Verify persistence
|
|
get_resp = await client.get(
|
|
"/api/settings/", headers=auth_headers(admin_user)
|
|
)
|
|
settings = get_resp.json()
|
|
assert settings["company_name"] == "Tielogic Srl"
|
|
|
|
async def test_settings_require_admin(
|
|
self, client: AsyncClient, maker_user: User
|
|
):
|
|
"""Non-admin user cannot update settings."""
|
|
resp = await client.put(
|
|
"/api/settings/",
|
|
headers=auth_headers(maker_user),
|
|
json={"some_key": "some_value"},
|
|
)
|
|
assert resp.status_code == 403
|