diff --git a/app/models/alerts.py b/app/models/alerts.py index 16d9b12..18152b1 100644 --- a/app/models/alerts.py +++ b/app/models/alerts.py @@ -67,7 +67,18 @@ class AlertHistoryRepository: raise AlertHistoryLoadError(self.history_path, f"Alert history could not be read: {exc}") from exc if not isinstance(data, list): raise AlertHistoryLoadError(self.history_path, "Alert history payload must be a list") - return [AlertEvent.from_dict(item) for item in data if isinstance(item, dict)] + events: list[AlertEvent] = [] + for index, item in enumerate(data): + if not isinstance(item, dict): + raise AlertHistoryLoadError(self.history_path, f"Alert history entry {index} must be an object") + try: + events.append(AlertEvent.from_dict(item)) + except (TypeError, ValueError) as exc: + raise AlertHistoryLoadError( + self.history_path, + f"Alert history entry {index} is invalid: {exc}", + ) from exc + return events def save(self, events: list[AlertEvent]) -> None: with self.history_path.open("w") as f: diff --git a/tests/test_alerts.py b/tests/test_alerts.py index 7859c55..84e0a6d 100644 --- a/tests/test_alerts.py +++ b/tests/test_alerts.py @@ -179,6 +179,24 @@ def test_alert_history_repository_raises_on_corrupt_history_file(tmp_path: Path) repository.load() +def test_alert_history_repository_raises_on_non_list_payload(tmp_path: Path) -> None: + history_path = tmp_path / "alert_history.json" + history_path.write_text('{"severity": "warning"}', encoding="utf-8") + repository = AlertHistoryRepository(history_path=history_path) + + with pytest.raises(AlertHistoryLoadError, match="Alert history payload must be a list"): + repository.load() + + +def test_alert_history_repository_raises_on_invalid_list_entry(tmp_path: Path) -> None: + history_path = tmp_path / "alert_history.json" + history_path.write_text('[{"severity": "warning"}]', encoding="utf-8") + repository = AlertHistoryRepository(history_path=history_path) + + with pytest.raises(AlertHistoryLoadError, match="Alert history entry 0 is invalid"): + repository.load() + + def test_alert_service_marks_history_unavailable_on_corrupt_storage(alert_service: AlertService) -> None: alert_service.repository.history_path.write_text("{not valid json", encoding="utf-8") config = PortfolioConfig( @@ -208,7 +226,7 @@ def test_alert_service_marks_history_unavailable_on_corrupt_storage(alert_servic def test_alert_service_preview_marks_history_unavailable_on_corrupt_storage(alert_service: AlertService) -> None: - alert_service.repository.history_path.write_text("{not valid json", encoding="utf-8") + alert_service.repository.history_path.write_text('[{"severity": "warning"}]', encoding="utf-8") config = PortfolioConfig( gold_value=215_000.0, entry_price=215.0,