import pytest from pydantic import ValidationError from control_backend.schemas.program import Goal, Norm, Phase, PhaseData, Program, Trigger def base_norm() -> Norm: return Norm( id="norm1", name="testNorm", value="you should act nice", ) def base_goal() -> Goal: return Goal( id="goal1", name="testGoal", description="you should act nice", achieved=False, ) def base_trigger() -> Trigger: return Trigger( id="trigger1", label="testTrigger", type="keyword", value=["Stop", "Exit"], ) def base_phase_data() -> PhaseData: return PhaseData( norms=[base_norm()], goals=[base_goal()], triggers=[base_trigger()], ) def base_phase() -> Phase: return Phase( id="phase1", name="basephase", nextPhaseId="phase2", phaseData=base_phase_data(), ) def base_program() -> Program: return Program(phases=[base_phase()]) def invalid_program() -> dict: # wrong types inside phases list (not Phase objects) return { "phases": [ {"id": "phase1"}, # incomplete {"not_a_phase": True}, ] } def test_valid_program(): program = base_program() validated = Program.model_validate(program) assert isinstance(validated, Program) assert validated.phases[0].phaseData.norms[0].name == "testNorm" def test_valid_deepprogram(): program = base_program() validated = Program.model_validate(program) # validate nested components directly phase = validated.phases[0] assert isinstance(phase.phaseData, PhaseData) assert isinstance(phase.phaseData.goals[0], Goal) assert isinstance(phase.phaseData.triggers[0], Trigger) assert isinstance(phase.phaseData.norms[0], Norm) def test_invalid_program(): bad = invalid_program() with pytest.raises(ValidationError): Program.model_validate(bad)