#!/usr/bin/env python3 """ Unit tests for archive_references.py's slugify() and the minimal bib parser, covering the edge cases that are easy to get wrong silently: CJK topic names and nested-brace LaTeX field values (e.g. \\ensuremath{\\epsilon}). Run: python -m unittest discover -s .claude/skills/literature-search-verify/scripts """ import os import sys import tempfile import unittest sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) import archive_references as ar class TestSlugify(unittest.TestCase): def test_ascii_topic(self): self.assertEqual(ar.slugify("UAV aeromagnetic compensation"), "uav_aeromagnetic_compensation") def test_chinese_topic_is_preserved_not_collapsed_to_generic_name(self): slug = ar.slugify("无人机磁补偿") self.assertNotEqual(slug, "references") self.assertIn("补偿", slug) def test_mixed_chinese_and_english(self): slug = ar.slugify("无人机磁补偿 Tolles-Lawson") self.assertTrue(slug.endswith("tolles_lawson")) def test_blank_topic_falls_back_to_references(self): self.assertEqual(ar.slugify(" "), "references") def test_truncated_to_60_chars(self): self.assertEqual(len(ar.slugify("a" * 100)), 60) class TestParseBibEntries(unittest.TestCase): def _write_bib(self, content): fd, path = tempfile.mkstemp(suffix=".bib") with os.fdopen(fd, "w", encoding="utf-8") as f: f.write(content) self.addCleanup(os.remove, path) return path def test_nested_braces_in_field_value_do_not_truncate_it(self): bib = ( "@article{wu2017,\n" " title = {Aeromagnetic gradient compensation using \\ensuremath{\\epsilon}-SVR},\n" " journal = {Journal of Applied Remote Sensing},\n" " year = {2017},\n" " doi = {10.1117/1.jrs.11.025012},\n" "}" ) entries = ar.parse_bib_entries(self._write_bib(bib)) self.assertEqual(len(entries), 1) self.assertIn("\\ensuremath{\\epsilon}-SVR", entries[0]["title"]) self.assertEqual(entries[0]["year"], "2017") def test_multiple_entries_and_optional_fields(self): bib = ( "@article{a2020,\n" " title = {First paper},\n" " year = {2020},\n" "}\n\n" "@article{b2021,\n" " title = {Second paper},\n" " year = {2021},\n" " note = {some note},\n" "}" ) entries = ar.parse_bib_entries(self._write_bib(bib)) self.assertEqual([e["key"] for e in entries], ["a2020", "b2021"]) self.assertNotIn("note", entries[0]) self.assertEqual(entries[1]["note"], "some note") class TestYearSortKey(unittest.TestCase): def test_entries_without_a_parseable_year_sort_last(self): entries = [{"key": "b", "year": ""}, {"key": "a", "year": "1999"}] entries.sort(key=ar.year_sort_key) self.assertEqual([e["key"] for e in entries], ["a", "b"]) class TestBuildReadme(unittest.TestCase): def test_omits_optional_sections_when_not_given(self): readme = ar.build_readme("Topic", [], 0, [], None) self.assertNotIn("Flagged during search", readme) self.assertNotIn("Search coverage notes", readme) def test_includes_suspect_and_notes_when_given(self): readme = ar.build_readme("Topic", [], 0, ["Bad title|dubious venue"], "coverage notes here") self.assertIn("Bad title", readme) self.assertIn("dubious venue", readme) self.assertIn("coverage notes here", readme) if __name__ == "__main__": unittest.main()