"""Tests for src/cmos/parser.py — extract the bibliography section from a draft. v1 scope: locate a ``## Bibliography`` heading (case-insensitive) and return the prose before it, the list of entries inside it, and the prose after it. The section ends at the next ``##`` (level-2) heading or end of file. Blank lines and bullet markers (``- `` or ``* ``) are stripped from entries. v2 (notes) parser scope: find pandoc-style markdown footnote definitions ``[^marker]: text`` anywhere in the document. Single-line definitions only; multi-line continuation is deferred to a later chunk. """ import pytest from cmos.parser import NoBibliographyError, find_notes, split_bibliography def test_three_entries_under_bibliography_heading(): draft = """\ Some prose here. More prose. ## Bibliography yu, charles. interior chinatown. New York: Pantheon Books, 2020. Kwon, Hyeyoung. "inclusion work." American Journal of Sociology 127, no. 6 (2022): 1818-1859. google, "privacy policy," privacy & terms, nov 15 2023, policies.google.com/privacy """ result = split_bibliography(draft) assert len(result.entries) == 3 assert result.entries[0].startswith("yu, charles") assert result.entries[1].startswith("Kwon, Hyeyoung") assert result.entries[2].startswith("google") assert "Some prose here." in result.before assert result.after == "" def test_section_ends_at_next_level_two_heading(): draft = """\ ## Bibliography First entry. Second entry. ## Appendix Appendix content here. """ result = split_bibliography(draft) assert result.entries == ["First entry.", "Second entry."] assert "## Appendix" in result.after assert "Appendix content here." in result.after def test_bullet_prefixes_stripped(): draft = """\ ## Bibliography - First entry. - Second entry. * Third entry. """ result = split_bibliography(draft) assert result.entries == ["First entry.", "Second entry.", "Third entry."] def test_heading_match_is_case_insensitive(): draft = """\ ## bibliography Only entry. """ result = split_bibliography(draft) assert result.entries == ["Only entry."] def test_no_bibliography_raises(): with pytest.raises(NoBibliographyError): split_bibliography("## Introduction\n\nJust prose.\n") # --- find_notes (v2 parser, pandoc-style markdown footnote definitions) ---- def test_find_notes_single_definition(): draft = """\ Some prose with a citation.[^1] [^1]: Charles Yu, *Interior Chinatown* (Pantheon Books, 2020), 45. """ result = find_notes(draft) assert len(result.definitions) == 1 assert result.definitions[0].marker == "1" assert result.definitions[0].text == "Charles Yu, *Interior Chinatown* (Pantheon Books, 2020), 45." def test_find_notes_multiple_definitions_in_order(): draft = """\ Prose.[^1] More prose.[^2] And again.[^3] [^1]: First note. [^2]: Second note. [^3]: Third note. """ result = find_notes(draft) assert len(result.definitions) == 3 assert [d.marker for d in result.definitions] == ["1", "2", "3"] assert [d.text for d in result.definitions] == [ "First note.", "Second note.", "Third note.", ] def test_find_notes_named_marker(): draft = """\ Citation.[^smith2020] [^smith2020]: Smith, J. (2020). Some work. """ result = find_notes(draft) assert len(result.definitions) == 1 assert result.definitions[0].marker == "smith2020" assert result.definitions[0].text == "Smith, J. (2020). Some work." def test_find_notes_returns_empty_when_no_definitions(): draft = "Just prose with no footnote definitions.\n" result = find_notes(draft) assert result.definitions == [] def test_find_notes_records_line_number(): draft = """\ Line zero. Line one. [^1]: Note on line three. """ result = find_notes(draft) assert len(result.definitions) == 1 assert result.definitions[0].line_number == 3 def test_find_notes_strips_trailing_whitespace_from_text(): draft = "[^1]: Note text with trailing spaces. \n" result = find_notes(draft) assert result.definitions[0].text == "Note text with trailing spaces." def test_find_notes_definition_can_appear_before_reference(): # Pandoc allows definitions anywhere in the doc, not just at the bottom. draft = """\ [^1]: A definition before the reference. Some prose that cites it.[^1] """ result = find_notes(draft) assert len(result.definitions) == 1 assert result.definitions[0].text == "A definition before the reference."