from __future__ import annotations import json import sys import tempfile import unittest from pathlib import Path MODULE_DIR = Path(__file__).resolve().parents[1] / "meeting_minutes_tool" sys.path.insert(0, str(MODULE_DIR)) import meeting_minutes_tool as tool # noqa: E402 class TranscriptIndexTests(unittest.TestCase): def test_index_extracts_navigation_and_flags_regression(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) transcript = root / "sample.txt" transcript.write_text( "\n".join( [ "甲 共享音频(00:00:10): 正式开始,政治局政策与算力网投资约21.4%。", "甲 共享音频(00:00:20): 请问华为和半导体公司怎么看?", "甲 共享音频(00:00:05): 这个数字大概需要核对,不构成投资建议。", "甲 共享音频(00:00:30): 一段足够长并且会重复出现的测试内容用于重复检测。", "甲 共享音频(00:00:40): 一段足够长并且会重复出现的测试内容用于重复检测。", ] ), encoding="utf-8", ) result = tool.build_transcript_index(transcript, root / "index", max_items=20) self.assertEqual(result["source"]["line_count"], 5) self.assertEqual(result["sequence_check"]["timestamp_regression_count"], 1) self.assertEqual( result["sequence_check"]["exact_normalized_duplicate_group_count"], 1 ) self.assertGreater( result["category_total_counts"]["numbers_and_time_windows"], 0 ) self.assertTrue((root / "index" / "transcript-index.json").is_file()) self.assertTrue((root / "index" / "transcript-index.md").is_file()) def test_missing_transcript_fails_fast(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) with self.assertRaises(FileNotFoundError): tool.build_transcript_index(root / "missing.txt", root / "index") class PdfPipelineTests(unittest.TestCase): SAMPLE_MARKDOWN = """# 2026年度超长标题会议纪要【第6场:政策与产业链深度解读和后续跟踪安排】 > **免责声明:内容为会议观点记录,不构成投资建议。** ## 一、核心结论 1. 这是第一条核心结论。 2. 这是第二条核心结论。 ## 二、主体内容 ### 2.1 政策与产业 - 算力网与新型电网需要结合订单验证。 - 无法确认的数据需要标记为待核对。 | 行业 | 观点 | 风险 | |---|---|---| | 算力 | 关注订单和交付 | 估值与技术迭代 | | 电网 | 关注招标与资本开支 | 项目节奏 | ## 三、问答环节重点 ### 3.1 如何判断? - 回答:结合基本面、价格和风险承受能力判断。 ## 四、后续跟踪清单 1. 跟踪订单。 2. 跟踪正式政策。 """ def test_pdf_and_qa_roundtrip(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) markdown = root / "minutes.md" pdf = root / "minutes.pdf" qa_dir = root / "qa" markdown.write_text(self.SAMPLE_MARKDOWN, encoding="utf-8") pdf_result = tool.render_markdown_pdf(markdown, pdf) qa_result = tool.run_pdf_qa(markdown, pdf, qa_dir, dpi=96) self.assertGreater(pdf_result["pdf_bytes"], 10_000) self.assertTrue(pdf.is_file()) self.assertTrue(qa_result["automated_checks_passed"]) self.assertTrue(qa_result["manual_visual_review_required"]) self.assertEqual( qa_result["pdf"]["page_count"], len(qa_result["render"]["page_images"]), ) self.assertTrue((qa_dir / "qa-report.json").is_file()) self.assertTrue((qa_dir / "qa-report.md").is_file()) payload = json.loads((qa_dir / "qa-report.json").read_text(encoding="utf-8")) self.assertEqual(payload["schema_version"], "meeting-minutes-pdf-qa.v1") def test_invalid_markdown_does_not_leave_pdf(self) -> None: with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) markdown = root / "invalid.md" pdf = root / "invalid.pdf" markdown.write_text("没有一级标题。", encoding="utf-8") with self.assertRaises(ValueError): tool.render_markdown_pdf(markdown, pdf) self.assertFalse(pdf.exists()) if __name__ == "__main__": unittest.main()