"""Tests for generated regions - the delimiters that replaced heading matching. The whole point is that a region's *identity* stops depending on its heading text. Everything here is about the two questions the old approach answered by guessing: where does the region start, and where does it stop. """ from __future__ import annotations from chemenu import blocks PROSE = "# Page\n\n## Beschreibung\n\nProse.\n" def _links(heading="Beziehungen", lines=("- **uses:** [[X]]",)): return blocks.render(blocks.LINKS, heading, list(lines)) def test_a_region_round_trips(): body = blocks.replace(PROSE, blocks.LINKS, _links()) assert blocks.find(body, blocks.LINKS) == "## Beziehungen\n\n- **uses:** [[X]]" assert blocks.strip(body, blocks.LINKS) == PROSE def test_replacing_does_not_append_a_second_region(): body = blocks.replace(PROSE, blocks.LINKS, _links()) again = blocks.replace(body, blocks.LINKS, _links(lines=["- **uses:** [[Y]]"])) assert again.count(blocks.open_marker(blocks.LINKS)) == 1 assert "[[X]]" not in again and "[[Y]]" in again def test_the_heading_inside_a_region_is_not_how_it_is_found(): """A page whose region carries a heading the instance never declared - an unconverted page, a hand-edit, another language - is still located exactly. Under heading matching this was the case that silently created a second section.""" body = blocks.replace(PROSE, blocks.LINKS, _links(heading="Something Else Entirely")) assert "[[X]]" in blocks.find(body, blocks.LINKS) assert blocks.strip(body, blocks.LINKS) == PROSE def test_content_after_a_region_survives_a_rewrite(): """The eight-page bug, as a test. The old block ran to the next heading - and before that to the end of the file - so anything sitting after it was deleted on the next write.""" body = blocks.replace(PROSE, blocks.LINKS, _links()) + "\n## Afterwards\n\nKeep me.\n" rewritten = blocks.replace(body, blocks.LINKS, _links(lines=["- **uses:** [[Z]]"])) assert "Keep me." in rewritten assert rewritten.count("## Afterwards") == 1 def test_two_regions_coexist_without_reading_each_other(): body = blocks.replace(PROSE, blocks.LINKS, _links()) body = blocks.replace( body, blocks.FOOTNOTES, blocks.render(blocks.FOOTNOTES, "Fußnoten", ["[^s-x]: [[Source - X]]"]), ) assert "[[X]]" in blocks.find(body, blocks.LINKS) assert "[^s-x]" in blocks.find(body, blocks.FOOTNOTES) assert blocks.marker_pairs(body) == {"links": 1, "footnotes": 1} def test_an_empty_region_is_no_region_at_all(): """A page that cites nothing must not carry an empty Footnotes heading.""" assert blocks.render(blocks.LINKS, "Beziehungen", []) == "" body = blocks.replace(PROSE, blocks.LINKS, _links()) assert blocks.replace(body, blocks.LINKS, "") == PROSE def test_an_absent_region_reads_as_none_not_as_empty(): """None and "" have to stay distinguishable: one means the page has no region, the other that it has one holding nothing.""" assert blocks.find(PROSE, blocks.LINKS) is None def test_a_dropped_marker_is_detectable(): """An agent rewriting prose at the boundary can lose one. Silent otherwise: the region becomes ordinary prose and the next write appends a second one beside it.""" body = blocks.replace(PROSE, blocks.LINKS, _links()) assert blocks.unbalanced_markers(body) == [] assert blocks.unbalanced_markers(body.replace(blocks.close_marker(blocks.LINKS), "")) == ["links"] assert blocks.unbalanced_markers(body.replace(blocks.open_marker(blocks.LINKS), "")) == ["links"] def test_marker_pairs_counts_rather_than_sets(): """A page that went from one region to two has the same set of names and a different count - which is why `migrate verify` compares counts.""" body = blocks.replace(PROSE, blocks.LINKS, _links()) doubled = body + "\n" + _links() + "\n" assert blocks.marker_pairs(doubled) == {"links": 2}