import json import pytest from fastapi import HTTPException from app.dynamic_fields import render_custom_value, validate_raw_value from app.models import CustomFieldDefinition, CustomFieldValue def definition(input_type="text", required=False, options=None): return CustomFieldDefinition( field_key="custom_test", label="测试字段", input_type=input_type, is_required=required, is_active=True, is_public=True, options_json=json.dumps(options or []), sort_order=0, created_by=1, ) def test_required_dynamic_field_rejects_empty_value(): with pytest.raises(HTTPException) as error: validate_raw_value(definition(required=True), None) assert error.value.status_code == 422 def test_select_rejects_value_outside_current_options(): with pytest.raises(HTTPException): validate_raw_value(definition("select", options=["A", "B"]), "历史选项") def test_type_change_preserves_incompatible_raw_value_for_display(): item = CustomFieldValue(raw_value="High") item.definition = definition("number") rendered = render_custom_value(item) assert rendered["raw_value"] == "High" assert rendered["display_value"] == "High" assert rendered["compatible"] is False def test_compatible_number_is_processed_for_display(): item = CustomFieldValue(raw_value="12.5") item.definition = definition("number") rendered = render_custom_value(item) assert rendered["value"] == 12.5 assert rendered["compatible"] is True