bfc0050580
Phase L: Dashboard widget system - Migration 046: dashboard_configs table (user/tenant/role fallback cascade) - DashboardConfig model + dashboard_service with get/upsert per-user and tenant-default - API router: GET/PUT /api/dashboard/config, GET/PUT /api/dashboard/tenant-default - Frontend: 5 widget components (ProductionStats, QueueStatus, RecentRenders, CostOverview, WorkerStatus) - DashboardGrid with API-backed config, DashboardCustomizeModal (checkbox selection, save/cancel) - Dashboard.tsx: widget grid + analytics section (privileged users) - Admin.tsx: restructured with new section order and Maintenance 2-col grid Phase M: Test framework - Backend: pytest-asyncio + pytest-cov + factory-boy in pyproject.toml - conftest.py: excel_dir fixtures + async DB fixtures + mock storage/celery stubs - Domain tests: billing_service, cache_service, notifications_service, imports_sanity - Integration: test_api_health.py smoke test (requires running backend) - Frontend: vitest + @testing-library/react + msw added to package.json - vite.config.ts: test block (jsdom + globals + setupFiles) - tsconfig.json: exclude src/__tests__ from main tsc (test runner handles its own types) - MSW handlers for /api/auth/me, Billing.test.tsx, formatters.test.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Tests for STL conversion cache service (pure/unit — no DB needed)."""
|
|
import pytest
|
|
from pathlib import Path
|
|
from app.domains.products.cache_service import compute_step_hash, _cache_key
|
|
|
|
|
|
def test_compute_step_hash_stable(tmp_path):
|
|
"""Gleiche Datei → gleicher Hash."""
|
|
f = tmp_path / "test.stp"
|
|
f.write_bytes(b"STEP data content")
|
|
h1 = compute_step_hash(str(f))
|
|
h2 = compute_step_hash(str(f))
|
|
assert h1 == h2
|
|
assert len(h1) == 64 # SHA256 hex
|
|
|
|
|
|
def test_compute_step_hash_differs(tmp_path):
|
|
"""Andere Datei → anderer Hash."""
|
|
f1 = tmp_path / "a.stp"
|
|
f1.write_bytes(b"content A")
|
|
f2 = tmp_path / "b.stp"
|
|
f2.write_bytes(b"content B")
|
|
assert compute_step_hash(str(f1)) != compute_step_hash(str(f2))
|
|
|
|
|
|
def test_cache_key_format():
|
|
"""Cache-Key hat korrektes Format."""
|
|
key = _cache_key("abc123", "low")
|
|
assert key == "conversion-cache/abc123_low.stl"
|
|
|
|
|
|
def test_store_stl_cache_uses_path(tmp_path, mock_storage):
|
|
"""store_stl_cache übergibt Path-Objekt an storage.upload."""
|
|
from app.domains.products.cache_service import store_stl_cache
|
|
stl = tmp_path / "test.stl"
|
|
stl.write_bytes(b"fake stl")
|
|
store_stl_cache("abc123", "low", str(stl))
|
|
call_args = mock_storage.upload.call_args
|
|
assert call_args is not None
|
|
first_arg = call_args[0][0]
|
|
assert isinstance(first_arg, Path), f"Expected Path, got {type(first_arg)}"
|