"""Parser EV session z fn_planning_site_context (_ev_session_from_json). Bug 2026-06-13: session BEZ deadline (auto nad targetem / bez cíle) se v parseru zahazovala (None), takže plánovač neviděl zátěž auta ani oportunismus. Oprava: session bez deadline zůstává objektem s energy_needed_wh=0 a headroom. """ import unittest from services.planning.db_io import _ev_session_from_json class EvSessionParseTests(unittest.TestCase): def test_none_and_empty_return_none(self) -> None: self.assertIsNone(_ev_session_from_json(None)) self.assertIsNone(_ev_session_from_json([])) self.assertIsNone(_ev_session_from_json(123)) def test_session_without_deadline_kept_for_opportunism(self) -> None: sess = _ev_session_from_json( { "target_deadline": None, "energy_needed_wh": 0, "headroom_wh": 18000.0, "opportunistic_value_czk_kwh": 1.0, } ) self.assertIsNotNone(sess) assert sess is not None self.assertIsNone(sess.target_deadline) self.assertEqual(sess.energy_needed_wh, 0.0) self.assertEqual(sess.headroom_wh, 18000.0) self.assertEqual(sess.opportunistic_value_czk_kwh, 1.0) def test_session_with_deadline_and_need(self) -> None: sess = _ev_session_from_json( { "target_deadline": "2026-06-14T05:00:00+00:00", "energy_needed_wh": 12000.0, "headroom_wh": 6000.0, "opportunistic_value_czk_kwh": 1.0, } ) assert sess is not None self.assertIsNotNone(sess.target_deadline) self.assertEqual(sess.energy_needed_wh, 12000.0) def test_missing_needed_defaults_zero(self) -> None: sess = _ev_session_from_json( {"target_deadline": None, "headroom_wh": 1000.0} ) assert sess is not None self.assertEqual(sess.energy_needed_wh, 0.0) self.assertEqual(sess.opportunistic_value_czk_kwh, 0.0) def test_json_string_payload(self) -> None: sess = _ev_session_from_json( '{"target_deadline": null, "energy_needed_wh": 0, ' '"headroom_wh": 5000, "opportunistic_value_czk_kwh": 1.0}' ) assert sess is not None self.assertEqual(sess.headroom_wh, 5000.0) if __name__ == "__main__": unittest.main()