Files
laser-data-hub/tests/conftest.py
T
broccoliandClaude Fable 5 edfb216561 激光材料数据平台 1.3.0
公开数据看板、四位 Key 录入面板、管理后台与三级权限、动态字段配置、
PostgreSQL/SQLite 双支持、数据库备份,以及本版新增的成品图上传与预览。

图片相关:
- 录入表单支持相册选图与手机端直接拍照,每条记录最多 6 张
- 浏览器内压缩到最长边 1600 并剥离 EXIF,入库统一为 JPG/PNG
- 二进制直接入库,现有备份自动覆盖图片,部署无需新增卷
- 详情页缩略图宫格与全屏 lightbox,公开看板同样可见

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:06:02 +08:00

73 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""接口测试用的独立环境:必须在导入 app 之前写好环境变量,配置是冻结的 dataclass。"""
from __future__ import annotations
import os
import struct
import tempfile
import zlib
from pathlib import Path
import pytest
os.environ.setdefault("APP_SECRET", "test-secret-0123456789abcdefghijkl")
os.environ.setdefault("ADMIN_USERNAME", "admin")
os.environ.setdefault("ADMIN_PASSWORD", "TestAdmin12345")
os.environ["DATABASE_URL"] = f"sqlite:///{Path(tempfile.mkdtemp(prefix='laser-test-')) / 'test.db'}"
def png_bytes(width: int = 24, height: int = 16) -> bytes:
"""不依赖 Pillow 手工拼一张真实可解码的 PNG。"""
def chunk(tag: bytes, payload: bytes) -> bytes:
return struct.pack(">I", len(payload)) + tag + payload + struct.pack(">I", zlib.crc32(tag + payload))
raw = b"".join(b"\x00" + b"\x20\x60\x90" * width for _ in range(height))
header = chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0))
return b"\x89PNG\r\n\x1a\n" + header + chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b"")
def jpeg_bytes(width: int = 32, height: int = 20) -> bytes:
"""只含 SOI/APP0/SOF0/EOI 的最小 JPEG,足以走完服务端的文件头校验。"""
app0 = b"\xff\xe0" + struct.pack(">H", 16) + b"JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00"
sof0 = b"\xff\xc0" + struct.pack(">HBHHB", 11, 8, height, width, 1) + b"\x01\x11\x00"
return b"\xff\xd8" + app0 + sof0 + b"\xff\xd9"
def record_payload(experiment_id: str = "LAS-TEST-001", **overrides) -> dict:
payload = {
"experiment_id": experiment_id, "test_date": "2026-07-01", "material_category": "木材", "material_name": "椴木板",
"material_thickness": 3, "actual_output_power": 8.5, "display_current": 2, "scanning_speed": 100,
"pulse_frequency": 20, "pulse_width": 5, "defocus_amount": 0, "scan_line_spacing": 0.1,
"filling_method": "双向填充", "processing_size": "20×20", "is_cut_through": True,
"carbonized_edge_width": 0.2, "etching_depth": 30, "is_fire_smolder": False,
"pattern_clarity_score": 9, "presentation_balance_score": 8,
"finished_image_filename": "LAS-TEST-001.jpg", "remarks": "测试记录",
}
payload.update(overrides)
return payload
@pytest.fixture(scope="session")
def client():
from fastapi.testclient import TestClient
from app.main import app
with TestClient(app) as test_client:
yield test_client
@pytest.fixture()
def admin(client):
"""返回带管理员会话的客户端和对应 CSRF 令牌。"""
import hashlib
import hmac
from app.config import settings
from app.main import SESSION_COOKIE
client.cookies.clear()
response = client.post("/api/auth/login", data={"username": settings.admin_username, "password": settings.admin_password})
assert response.status_code == 200, response.text
token = client.cookies.get(SESSION_COOKIE)
csrf = hmac.new(settings.secret.encode(), token.encode(), hashlib.sha256).hexdigest()
return client, {"X-CSRF-Token": csrf}