import json from pathlib import Path from backend.app.core import interview_flow def _write_state(tmp_path: Path, session_id: str, state: dict) -> None: session_dir = tmp_path / session_id session_dir.mkdir(parents=True, exist_ok=True) (session_dir / "interview_state.json").write_text(json.dumps(state), encoding="utf-8") def test_next_write_returns_existing_active_question_for_concurrent_followup(tmp_path): session_id = "session-a" active_followup = { "id": "followup_python_4", "question": "Could you give me a concrete example of working with Python?", "skill_target": "Python", } state = { "session_id": session_id, "completed": False, "cursor": {"stage": "technical", "last_question_id": "technical_1"}, "questions_asked": [active_followup], "answers": {}, "turns": [ { "role": "interviewer", "id": active_followup["id"], "text": active_followup["question"], "skill_target": "Python", } ], } _write_state(tmp_path, session_id, state) stale_decision = { "action": "followup", "original_q": {"id": "technical_1", "question": "Explain Python.", "skill_target": "Python"}, "original_q_id": "technical_1", "depth": 1, } result = interview_flow._decide_next_write( tmp_path, session_id, {"questions": []}, stale_decision, active_followup["question"], ) assert result["id"] == active_followup["id"] assert result["question"] == active_followup["question"] def test_duplicate_followup_text_uses_alternate_not_completed(tmp_path): session_id = "session-b" duplicate_text = "Could you give me a concrete example of working with Python?" state = { "session_id": session_id, "completed": False, "followup_count": 1, "cursor": {"stage": "technical", "last_question_id": "technical_1"}, "questions_asked": [ {"id": "technical_1", "question": "Explain Python.", "skill_target": "Python"}, {"id": "followup_python_2", "question": duplicate_text, "skill_target": "Python"}, ], "answers": { "technical_1": {"answer": "Python answer", "score": 5}, "followup_python_2": {"answer": "Follow-up answer", "score": 5}, }, "turns": [ {"role": "interviewer", "id": "technical_1", "text": "Explain Python."}, {"role": "candidate", "id": "technical_1", "text": "Python answer", "score": 5}, {"role": "interviewer", "id": "followup_python_2", "text": duplicate_text}, {"role": "candidate", "id": "followup_python_2", "text": "Follow-up answer", "score": 5}, ], } _write_state(tmp_path, session_id, state) decision = { "action": "followup", "original_q": {"id": "technical_1", "question": "Explain Python.", "skill_target": "Python"}, "original_q_id": "technical_1", "depth": 2, } plan = { "questions": [ {"id": "technical_1", "type": "technical", "question": "Explain Python."}, {"id": "technical_2", "type": "technical", "question": "Explain APIs."}, ] } result = interview_flow._decide_next_write( tmp_path, session_id, plan, decision, duplicate_text, ) assert result["id"].startswith("followup_python_") assert result["question"] != duplicate_text assert "completed" not in result