"""Runner error handling test: reporters receive error notifications and summary collects errors.""" from __future__ import annotations from typing import Any, Dict, List from claudia.core import Document from claudia.spiders import BaseSpider from claudia.db import MemoryDB from claudia.scheduler import Runner from claudia.reporter import MemoryReporter class BoomSpider(BaseSpider): """Spider that intentionally raises to exercise Runner error handling.""" name = "boom" def build_payload(self, url: str) -> Dict[str, Any]: return {} def parse( self, url: str, content: str, payload: Dict[str, Any] ) -> List[Document]: # pragma: no cover return [] def fetch(self, url: str, payload: Dict[str, Any]) -> str: # pragma: no cover raise RuntimeError("boom!") def test_runner_handles_errors_and_reports(): """Runner should record errors and reporters should receive error notifications.""" spider = BoomSpider() db = MemoryDB() reporter = MemoryReporter() runner = Runner(db=db, reporters=[reporter]) summary = runner.run({spider: ["https://example.com/a"]}) assert summary.total_docs == 0 assert summary.errors and any("boom" in e for e in summary.errors) assert any(e.startswith("error:") for e in reporter.events)