"""P2 단계 누적 게이지 파생(build_session_progress) 테스트.""" from __future__ import annotations import unittest from .services import state_machine from .session_read_model import build_session_progress class SessionProgressTest(unittest.TestCase): def test_initial_state_gauges(self) -> None: state = state_machine.SessionState() progress = build_session_progress(state) self.assertEqual([s.stage for s in progress.stages], ["라포", "탐색", "개입", "정리"]) self.assertEqual(progress.stages[0].percent, 0) self.assertFalse(progress.stages[0].achieved) self.assertEqual(progress.stages[1].percent, 0) self.assertEqual(progress.rapport_percent, 0) self.assertEqual(progress.rapport_delta_percent, 0) def test_current_stage_gauge_scales_with_rapport(self) -> None: state = state_machine.SessionState(rapport_credit=0.15) progress = build_session_progress(state) # 라포 전이 임계 0.30 → 0.15는 절반 = 약 50 (99 스케일 반올림 50) self.assertAlmostEqual(progress.stages[0].percent, 50, delta=2) self.assertFalse(progress.stages[0].achieved) def test_current_stage_gauge_caps_at_99_until_transition(self) -> None: state = state_machine.SessionState(rapport_credit=0.9) progress = build_session_progress(state) self.assertEqual(progress.stages[0].percent, 99) def test_passed_stage_is_100_and_achieved(self) -> None: state = state_machine.SessionState( stage=state_machine.Stage.EXPLORE, rapport_credit=0.32, ) progress = build_session_progress(state) self.assertEqual(progress.stages[0].percent, 100) self.assertTrue(progress.stages[0].achieved) # 탐색 임계 0.45 → 0.32/0.45*99 ≈ 70 self.assertAlmostEqual(progress.stages[1].percent, 70, delta=2) self.assertEqual(progress.stages[2].percent, 0) def test_close_stage_entry_is_100(self) -> None: state = state_machine.SessionState( stage=state_machine.Stage.CLOSE, rapport_credit=0.6, ) progress = build_session_progress(state) self.assertTrue(all(s.percent == 100 for s in progress.stages)) self.assertTrue(progress.stages[3].achieved) def test_goal_flag_and_delta_from_carry(self) -> None: state = state_machine.SessionState(rapport_credit=0.33) progress = build_session_progress( state, prev_rapport_credit=0.11, goal_stages=["라포", "탐색"], ) self.assertTrue(progress.stages[0].is_goal) self.assertTrue(progress.stages[1].is_goal) self.assertFalse(progress.stages[2].is_goal) # 0.33/0.55=60%, 0.11/0.55=20% → 이번 회기 +40%p self.assertEqual(progress.rapport_percent, 60) self.assertEqual(progress.rapport_delta_percent, 40) def test_detail_metrics_are_percentages(self) -> None: state = state_machine.SessionState( resistance=0.65, effective_openness=0.42, ) progress = build_session_progress(state) self.assertEqual(progress.resistance_percent, 65) self.assertEqual(progress.openness_percent, 42) if __name__ == "__main__": unittest.main()