Spaces:
Running
Running
| """Smoke tests for onboarding commit and daily row seeding.""" | |
| import tempfile | |
| import unittest | |
| from datetime import date | |
| from pathlib import Path | |
| from db.database import close_connection, initialize_database, set_db_path | |
| from db import queries | |
| from llm.onboarding import validate_follow_up_response, validate_plan_response | |
| from vital_types.db import ( | |
| DailyLogSchemaField, | |
| MedicationRecord, | |
| PresenceConfig, | |
| ProfileInput, | |
| ScheduledJob, | |
| ) | |
| from vital_types.onboarding import ( | |
| ExercisePlan, | |
| MealPlanFramework, | |
| OnboardingCommitData, | |
| OnboardingPlan, | |
| WeeklyCheckStructure, | |
| ) | |
| class Day4SmokeTest(unittest.TestCase): | |
| """Verify onboarding validation, commit, and ensure_daily_rows.""" | |
| def setUp(self) -> None: | |
| """Use an isolated temporary database for each test.""" | |
| self.temp_dir = tempfile.TemporaryDirectory() | |
| db_path = Path(self.temp_dir.name) / "test_vital.db" | |
| close_connection() | |
| set_db_path(db_path) | |
| initialize_database() | |
| def tearDown(self) -> None: | |
| """Close the connection and remove the temporary database.""" | |
| close_connection() | |
| self.temp_dir.cleanup() | |
| def test_validate_follow_up_response_caps_at_three(self) -> None: | |
| """Follow-up validation should keep only the first three questions.""" | |
| payload = { | |
| "follow_up_questions": [ | |
| { | |
| "question_id": f"q_{index}", | |
| "question": f"Question {index}?", | |
| "type": "text", | |
| "reason": "test", | |
| } | |
| for index in range(5) | |
| ] | |
| } | |
| questions = validate_follow_up_response(payload) | |
| self.assertEqual(len(questions), 3) | |
| def test_validate_plan_response_normalizes_jobs(self) -> None: | |
| """Plan validation should infer daily_time schedule for timed jobs.""" | |
| payload = { | |
| "daily_log_fields": [ | |
| { | |
| "field_id": "pain_level", | |
| "label": "Pain level", | |
| "type": "scale_1_10", | |
| "options": [], | |
| "reason": "monitor pain", | |
| } | |
| ], | |
| "scheduled_jobs": [ | |
| { | |
| "job_id": "med_morning", | |
| "type": "medication", | |
| "time": "08:00", | |
| "days": "daily", | |
| "message": "Take folic acid", | |
| "tts": True, | |
| "context": "daily med", | |
| } | |
| ], | |
| "meal_plan_framework": { | |
| "nutrients_to_prioritise": ["folate"], | |
| "nutrients_to_moderate": ["sugar"], | |
| "meal_frequency": 3, | |
| "notes": "eat local foods", | |
| }, | |
| "exercise_plan": { | |
| "frequency": "daily", | |
| "intensity": "low", | |
| "session_duration_minutes": 20, | |
| "types": ["walking"], | |
| "avoid": ["sprints"], | |
| "notes": "stay safe", | |
| }, | |
| "weekly_check_structure": { | |
| "report_day": "Sunday", | |
| "report_time": "20:00", | |
| "replan_day": "Sunday", | |
| "replan_time": "20:30", | |
| }, | |
| "presence_check": { | |
| "enabled": True, | |
| "max_continuous_minutes": 30, | |
| "break_message": "Take a break", | |
| "break_duration_minutes": 5, | |
| }, | |
| "system_prompt_additions": "Hydration matters.", | |
| "coach_quick_questions": ["What should I eat?"], | |
| } | |
| plan = validate_plan_response(payload) | |
| self.assertEqual(plan.scheduled_jobs[0].schedule_type, "daily_time") | |
| self.assertEqual(plan.daily_log_fields[0].field_id, "pain_level") | |
| def test_commit_onboarding_plan_writes_all_sections(self) -> None: | |
| """Atomic onboarding commit should populate profile, schema, and settings.""" | |
| profile = ProfileInput( | |
| name="Amara", | |
| age=24, | |
| city="Port Harcourt", | |
| profession="Student", | |
| goal="Manage a health condition", | |
| conditions=["sickle cell disease"], | |
| medications=[ | |
| MedicationRecord(name="Folic acid", dose="5mg", time="08:00"), | |
| ], | |
| triggers=["dehydration"], | |
| wake_time="07:00", | |
| sleep_time="23:00", | |
| desk_worker=True, | |
| exercise_level="light", | |
| dietary_notes="Low sugar", | |
| local_foods="beans", | |
| ) | |
| plan = OnboardingPlan( | |
| daily_log_fields=[ | |
| DailyLogSchemaField( | |
| field_id="pain_level", | |
| label="Pain level", | |
| type="scale_1_10", | |
| display_order=0, | |
| reason="track pain", | |
| ) | |
| ], | |
| scheduled_jobs=[ | |
| ScheduledJob( | |
| job_id="folic_acid", | |
| type="medication", | |
| schedule_type="daily_time", | |
| time="08:00", | |
| interval_minutes=None, | |
| days="daily", | |
| message="Take folic acid", | |
| tts=True, | |
| active=True, | |
| context="daily supplement", | |
| ) | |
| ], | |
| meal_plan_framework=MealPlanFramework( | |
| nutrients_to_prioritise=["folate"], | |
| nutrients_to_moderate=["sugar"], | |
| meal_frequency=3, | |
| notes="local foods", | |
| ), | |
| exercise_plan=ExercisePlan( | |
| frequency="daily", | |
| intensity="low", | |
| session_duration_minutes=20, | |
| types=["walking"], | |
| avoid=["sprints"], | |
| notes="gentle movement", | |
| ), | |
| weekly_check_structure=WeeklyCheckStructure( | |
| report_day="Sunday", | |
| report_time="20:00", | |
| replan_day="Sunday", | |
| replan_time="20:30", | |
| ), | |
| presence_check=PresenceConfig( | |
| enabled=True, | |
| max_continuous_minutes=30, | |
| break_message="Stretch now", | |
| break_duration_minutes=5, | |
| ), | |
| system_prompt_additions="Hydration first.", | |
| coach_quick_questions=["Crisis signs?"], | |
| ) | |
| queries.commit_onboarding_plan(OnboardingCommitData(profile=profile, plan=plan)) | |
| self.assertTrue(queries.check_onboarding_status()) | |
| self.assertEqual(len(queries.get_daily_log_schema()), 1) | |
| self.assertEqual(len(queries.get_all_scheduled_jobs()), 1) | |
| self.assertEqual(queries.get_system_prompt_additions(), "Hydration first.") | |
| self.assertEqual(queries.get_coach_quick_questions(), ["Crisis signs?"]) | |
| def test_ensure_daily_rows_is_idempotent(self) -> None: | |
| """ensure_daily_rows should seed medication rows once per day.""" | |
| profile = ProfileInput( | |
| name="Amara", | |
| age=24, | |
| city="Port Harcourt", | |
| profession="Student", | |
| goal="Manage a health condition", | |
| conditions=[], | |
| medications=[ | |
| MedicationRecord(name="Folic acid", dose="5mg", time="08:00"), | |
| MedicationRecord(name="Vitamin C", dose="500mg", time="18:00"), | |
| ], | |
| triggers=[], | |
| wake_time="07:00", | |
| sleep_time="23:00", | |
| desk_worker=True, | |
| exercise_level="light", | |
| dietary_notes="", | |
| local_foods="", | |
| ) | |
| queries.save_profile(profile) | |
| queries.set_onboarding_complete(True) | |
| queries.ensure_daily_rows(date.today()) | |
| queries.ensure_daily_rows(date.today()) | |
| medications = queries.get_medications_for_date(date.today()) | |
| self.assertEqual(len(medications), 2) | |