LockedIn / tests /test_schema_validation.py
JermaineAI's picture
deployed progress
2818f92
import copy
import pytest
from pydantic import ValidationError
from app.schemas.requests import GenerateRoadmapRequest
from app.schemas.roadmap import Roadmap
from app.schemas.roadmap import ResourceType
from app.services.id_generator import assign_backend_ids
def valid_payload():
resource_a = {
"title": "Python for Beginners",
"url": "https://www.youtube.com/watch?v=kqtD5dpn9C8",
"type": "youtube_video",
"source": "YouTube",
"is_free": True,
}
resource_b = {
"title": "Python Tutorial",
"url": "https://www.w3schools.com/python/",
"type": "article",
"source": "Tavily",
"is_free": True,
}
phases = []
for phase_index in range(1, 4):
nodes = []
for node_index in range(1, 4):
nodes.append(
{
"title": f"Node {node_index}",
"description": "Learn the core idea with simple examples and short practice tasks.",
"estimated_completion_time": "2-3 hours",
"resources": [resource_a, resource_b],
}
)
phases.append(
{
"title": f"Phase {phase_index}",
"level": "beginner",
"goal": "Build practical beginner confidence.",
"estimated_duration": "2 weeks",
"nodes": nodes,
"project": {
"title": f"Project {phase_index}",
"brief": "Build a small practical project that demonstrates the phase skills.",
"tools_needed": ["Browser"],
"resources": [resource_a, resource_b],
},
}
)
payload = {
"skill": "Python for Beginners",
"overview": "A beginner roadmap with practical examples and projects for learning step by step.",
"estimated_total_duration": "6-8 weeks",
"phases": phases,
"metadata": {"model_used": "test", "resource_sources": ["test"], "cached": False},
}
return assign_backend_ids(payload, "python")
def test_valid_roadmap_passes():
roadmap = Roadmap.model_validate(valid_payload())
assert len(roadmap.phases) == 3
assert len(roadmap.phases[0].nodes) == 3
def test_fewer_than_three_phases_fails():
payload = valid_payload()
payload["phases"] = payload["phases"][:2]
payload["projects"] = payload["projects"][:2]
with pytest.raises(ValidationError):
Roadmap.model_validate(payload)
def test_node_with_fewer_than_two_resources_fails():
payload = valid_payload()
payload["phases"][0]["nodes"][0]["resources"] = payload["phases"][0]["nodes"][0]["resources"][:1]
with pytest.raises(ValidationError):
Roadmap.model_validate(payload)
def test_paid_resource_with_is_free_false_fails():
payload = valid_payload()
payload["phases"][0]["nodes"][0]["resources"][0]["is_free"] = False
with pytest.raises(ValidationError):
Roadmap.model_validate(payload)
def test_invalid_resource_type_fails():
payload = copy.deepcopy(valid_payload())
payload["phases"][0]["nodes"][0]["resources"][0]["type"] = "paid_course"
with pytest.raises(ValidationError):
Roadmap.model_validate(payload)
def test_request_defaults_include_all_resource_types():
request = GenerateRoadmapRequest(skill="Learn Python")
assert request.preferred_resource_types == list(ResourceType)