|
| 1 | +"""Tests for content chunk analysis (citation readiness). |
| 2 | +
|
| 3 | +Chunks are sections of markdown split by headings. |
| 4 | +Sweet spot: 50-150 words per chunk (2.3x more citations). |
| 5 | +""" |
| 6 | + |
| 7 | +from __future__ import annotations |
| 8 | + |
| 9 | +from aeo_cli.core.checks.content import check_content |
| 10 | + |
| 11 | + |
| 12 | +def test_no_headings_single_chunk(): |
| 13 | + """Content without headings is one chunk.""" |
| 14 | + md = " ".join(["word"] * 80) |
| 15 | + report = check_content(md) |
| 16 | + assert report.chunk_count == 1 |
| 17 | + assert report.avg_chunk_words == 80 |
| 18 | + assert report.chunks_in_sweet_spot == 1 # 80 is in 50-150 range |
| 19 | + |
| 20 | + |
| 21 | +def test_two_sections(): |
| 22 | + """Two heading sections should produce two chunks.""" |
| 23 | + sec1 = "# Section 1\n\n" + " ".join(["word"] * 60) |
| 24 | + sec2 = "# Section 2\n\n" + " ".join(["word"] * 100) |
| 25 | + md = sec1 + "\n\n" + sec2 |
| 26 | + report = check_content(md) |
| 27 | + assert report.chunk_count == 2 |
| 28 | + assert report.chunks_in_sweet_spot == 2 # 60 and 100 are both in range |
| 29 | + |
| 30 | + |
| 31 | +def test_avg_chunk_words(): |
| 32 | + """Average should be integer average of word counts per chunk.""" |
| 33 | + md = "# A\n\n" + " ".join(["word"] * 40) + "\n\n# B\n\n" + " ".join(["word"] * 60) |
| 34 | + report = check_content(md) |
| 35 | + assert report.chunk_count == 2 |
| 36 | + assert report.avg_chunk_words == 50 # (40+60)/2 = 50 |
| 37 | + |
| 38 | + |
| 39 | +def test_sweet_spot_boundaries(): |
| 40 | + """Exactly 50 and 150 words should be in sweet spot; 49 and 151 should not.""" |
| 41 | + sections = [] |
| 42 | + for count in [49, 50, 150, 151]: |
| 43 | + sections.append("# Heading\n\n" + " ".join(["word"] * count)) |
| 44 | + md = "\n\n".join(sections) |
| 45 | + report = check_content(md) |
| 46 | + assert report.chunk_count == 4 |
| 47 | + assert report.chunks_in_sweet_spot == 2 # 50 and 150 are in range |
| 48 | + |
| 49 | + |
| 50 | +def test_empty_content_zero_chunks(): |
| 51 | + """Empty markdown should have zero chunks.""" |
| 52 | + report = check_content("") |
| 53 | + assert report.chunk_count == 0 |
| 54 | + assert report.avg_chunk_words == 0 |
| 55 | + assert report.chunks_in_sweet_spot == 0 |
| 56 | + |
| 57 | + |
| 58 | +def test_heading_only_no_content(): |
| 59 | + """A heading with no body text should produce zero non-empty chunks.""" |
| 60 | + md = "# Just a heading\n\n" |
| 61 | + report = check_content(md) |
| 62 | + # The heading line is stripped; remaining content after heading may be empty |
| 63 | + # But there could be text before or after — in this case "Just a heading" part |
| 64 | + # is consumed by the split, leaving empty chunks |
| 65 | + assert report.chunk_count == 0 |
| 66 | + |
| 67 | + |
| 68 | +def test_content_before_first_heading(): |
| 69 | + """Text before the first heading should count as a chunk.""" |
| 70 | + md = "Some intro text with enough words.\n\n# First heading\n\nSection content here." |
| 71 | + report = check_content(md) |
| 72 | + assert report.chunk_count == 2 # intro + section after heading |
| 73 | + |
| 74 | + |
| 75 | +def test_multiple_heading_levels(): |
| 76 | + """H1, H2, H3 etc. should all split chunks.""" |
| 77 | + md = ( |
| 78 | + "# H1\n\n" + " ".join(["alpha"] * 30) + "\n\n" |
| 79 | + "## H2\n\n" + " ".join(["beta"] * 70) + "\n\n" |
| 80 | + "### H3\n\n" + " ".join(["gamma"] * 120) + "\n\n" |
| 81 | + ) |
| 82 | + report = check_content(md) |
| 83 | + assert report.chunk_count == 3 |
| 84 | + assert report.chunks_in_sweet_spot == 2 # 70 and 120 are in range, 30 is not |
| 85 | + |
| 86 | + |
| 87 | +def test_all_chunks_outside_sweet_spot(): |
| 88 | + """When all chunks are too small or too large, sweet spot count is 0.""" |
| 89 | + md = "# Short\n\n" + " ".join(["w"] * 10) + "\n\n# Long\n\n" + " ".join(["w"] * 200) |
| 90 | + report = check_content(md) |
| 91 | + assert report.chunk_count == 2 |
| 92 | + assert report.chunks_in_sweet_spot == 0 |
| 93 | + |
| 94 | + |
| 95 | +def test_large_document_many_chunks(): |
| 96 | + """A document with many headings should count all chunks.""" |
| 97 | + sections = [f"# Section {i}\n\n" + " ".join(["word"] * 75) for i in range(10)] |
| 98 | + md = "\n\n".join(sections) |
| 99 | + report = check_content(md) |
| 100 | + assert report.chunk_count == 10 |
| 101 | + assert report.chunks_in_sweet_spot == 10 # all 75 words = in sweet spot |
| 102 | + assert report.avg_chunk_words == 75 |
0 commit comments