from datetime import date import pytest from pydantic import ValidationError from app.schemas import EntryRecordSubmission, MaterialRecordInput def valid_payload(): return { "experiment_id": "LAS-2026-001", "test_date": date(2026, 7, 17), "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": .1, "filling_method": "双向", "processing_size": "20×20", "is_cut_through": True, "carbonized_edge_width": .2, "etching_depth": 30, "is_fire_smolder": False, "pattern_clarity_score": 9, "presentation_balance_score": 8, "finished_image_filename": "LAS-2026-001.jpg", "remarks": "正常", } def test_all_optional_physical_properties_may_be_empty(): record = MaterialRecordInput(**valid_payload()) assert record.apparent_density is None assert record.hardness is None assert len(record.model_fields) - 3 == 32 # 32 fixed fields plus the dynamic-field map and the two image lists def test_scores_are_limited_to_ten(): payload = valid_payload() payload["pattern_clarity_score"] = 10.1 with pytest.raises(ValidationError): MaterialRecordInput(**payload) def test_percentage_is_limited_to_hundred(): payload = valid_payload() payload["moisture_content"] = 101 with pytest.raises(ValidationError): MaterialRecordInput(**payload) def test_entry_submission_requires_confirmation_username(): payload = valid_payload() with pytest.raises(ValidationError): EntryRecordSubmission(**payload) assert EntryRecordSubmission(**payload, confirm_username="operator").confirm_username == "operator"