from __future__ import annotations import pytest from yuxi.channels.adapters.whatsapp.analysis.pipeline import WhatsAppAnalysisPipeline from yuxi.channels.adapters.whatsapp.analysis.schemas import ( CodeIssue, FixProposal, GapAnalysisReport, GapItem, IssueSeverity, ) class TestGenerateStaticReport: def test_returns_report_instance(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert isinstance(report, GapAnalysisReport) def test_total_gaps_matches_list(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert report.total_gaps == len(report.gaps) def test_has_web_research_summary(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert len(report.web_research_summary) > 0 assert "Baileys" in report.web_research_summary def test_has_functionality_summary(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert len(report.functionality_summary) > 0 assert "14" in report.functionality_summary or "Python" in report.functionality_summary def test_has_code_issue_summary(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert len(report.code_issue_summary) > 0 def test_has_overall_assessment(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert len(report.overall_assessment) > 0 def test_all_gaps_have_required_fields(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() for gap in report.gaps: assert gap.category assert gap.title assert gap.description assert gap.severity in IssueSeverity assert gap.current_state assert gap.expected_state def test_has_missing_features(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() categories = {g.category for g in report.gaps} assert "消息类型支持" in categories def test_has_interface_gaps(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() titles = {g.title for g in report.gaps} assert any("receive" in t.lower() for t in titles) def test_has_performance_issues(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() categories = {g.category for g in report.gaps} assert "连接管理" in categories def test_critical_gaps_separated(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() for gap in report.critical_gaps: assert gap.severity in (IssueSeverity.CRITICAL, IssueSeverity.HIGH) def test_fix_proposals_have_required_fields(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() for fix in report.fix_proposals: assert fix.target_file assert fix.issue_title assert fix.description assert fix.proposed_code def test_module_path_is_set(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert len(report.module_path) > 0 assert "whatsapp" in report.module_path def test_report_generated_at_is_set(self): pipeline = WhatsAppAnalysisPipeline() report = pipeline.generate_static_report() assert report.generated_at is not None class TestPipelineGraph: @pytest.mark.skip(reason="Requires full agent framework (run in Docker)") def test_graph_builds_without_error(self): pipeline = WhatsAppAnalysisPipeline() graph = pipeline.graph assert graph is not None class TestGapItemModel: def test_valid_gap_item(self): gap = GapItem( category="测试", title="测试问题", description="这是一个测试描述", severity=IssueSeverity.HIGH, current_state="当前状态", expected_state="期望状态", references=["file.py:L1"], ) assert gap.category == "测试" assert gap.severity == IssueSeverity.HIGH class TestFixProposalModel: def test_valid_fix_proposal(self): fix = FixProposal( target_file="adapter.py", issue_title="测试修复", description="修复描述", current_code="old code", proposed_code="new code", rationale="修复原因", ) assert fix.target_file == "adapter.py" assert fix.test_coverage_needed is True class TestCodeIssueModel: def test_valid_code_issue(self): from yuxi.channels.adapters.whatsapp.analysis.schemas import CodeLocation issue = CodeIssue( severity=IssueSeverity.CRITICAL, category="bug", title="空指针", description="可能访问空对象", location=CodeLocation(file="bridge.py", line_start=74), snippet="self._http_session.post(...)", suggestion="添加空值检查", ) assert issue.severity == IssueSeverity.CRITICAL assert issue.location.file == "bridge.py"