"""Tests for create_listing.py.""" from unittest.mock import patch import pytest import create_listing class TestCharacterGrouping: """Test file grouping by first character.""" def test_alpha_files_grouped_by_first_char(self, tmp_path, make_png, monkeypatch): """Verify files starting with letters are grouped under their first char.""" monkeypatch.chdir(tmp_path) a1 = make_png(tmp_path, "apple.png") a2 = make_png(tmp_path, "avocado.png") b1 = make_png(tmp_path, "banana.png") create_listing.generate_readme([a1, a2, b1]) content = (tmp_path / "README.md").read_text() assert "## a" in content assert "## b" in content def test_non_alpha_grouped_as_special(self, tmp_path, make_png, monkeypatch): """Verify non-alphabetic filenames are grouped into the special category.""" monkeypatch.chdir(tmp_path) f1 = make_png(tmp_path, "1emoji.png") f2 = make_png(tmp_path, "_underscore.png") create_listing.generate_readme([f1, f2]) content = (tmp_path / "README.md").read_text() assert r"\[^a-zA-Z:\]" in content def test_numeric_file_grouped_as_special(self, tmp_path, make_png, monkeypatch): """Verify files starting with digits go into the special group.""" monkeypatch.chdir(tmp_path) f1 = make_png(tmp_path, "9lives.png") create_listing.generate_readme([f1]) content = (tmp_path / "README.md").read_text() assert r"\[^a-zA-Z:\]" in content class TestSorting: """Test sort order of groups.""" def test_special_group_sorts_before_alpha(self, tmp_path, make_png, monkeypatch): """Verify the special characters group appears before alphabetical groups.""" monkeypatch.chdir(tmp_path) f_special = make_png(tmp_path, "1first.png") f_alpha = make_png(tmp_path, "zebra.png") create_listing.generate_readme([f_special, f_alpha]) content = (tmp_path / "README.md").read_text() special_pos = content.index(r"\[^a-zA-Z:\]") z_pos = content.index("## z") assert special_pos < z_pos class TestRowChunking: """Test that files are split into rows of PER_ROW.""" def test_files_chunked_into_rows(self, tmp_path, make_png, monkeypatch): """Verify 25 files produce 3 table rows (10 per row).""" monkeypatch.chdir(tmp_path) files = [make_png(tmp_path, f"a{i:02d}.png", color=(i, 0, 0, 255)) for i in range(25)] create_listing.generate_readme(files) content = (tmp_path / "README.md").read_text() assert content.count("") == 3 def test_single_file_one_row(self, tmp_path, make_png, monkeypatch): """Verify a single file produces exactly one table row.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "alone.png") create_listing.generate_readme([f]) content = (tmp_path / "README.md").read_text() assert content.count("") == 1 class TestUrlEncoding: """Test URL encoding of filenames.""" def test_space_in_filename(self, tmp_path, make_png, monkeypatch): """Verify spaces are percent-encoded as %20.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "my emoji.png") create_listing.generate_readme([f]) content = (tmp_path / "README.md").read_text() assert "my%20emoji.png" in content def test_plus_in_filename(self, tmp_path, make_png, monkeypatch): """Verify plus signs are percent-encoded as %2B.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "a+b.png") create_listing.generate_readme([f]) content = (tmp_path / "README.md").read_text() assert "a%2Bb.png" in content def test_hash_in_filename(self, tmp_path, make_png, monkeypatch): """Verify hash symbols are percent-encoded as %23.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "c#sharp.png") create_listing.generate_readme([f]) content = (tmp_path / "README.md").read_text() assert "c%23sharp.png" in content class TestGenerateReadme: """Test generate_readme output structure.""" def test_produces_markdown_table(self, tmp_path, make_png, monkeypatch): """Verify output contains markdown heading, table, and image tags.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "test.png") create_listing.generate_readme([f]) content = (tmp_path / "README.md").read_text() assert content.startswith("# Emotes") assert "" in content assert 'id="search"' in content assert "test.png" in content def test_data_keyword_attribute(self, tmp_path, make_png, monkeypatch): """Verify emoji divs have data-keyword attributes for search.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "happy.png") create_listing.generate_html([f]) content = (tmp_path / "index.html").read_text() assert 'data-keyword="happy"' in content def test_special_group_header(self, tmp_path, make_png, monkeypatch): """Verify the # group displays as '0-9 / Special'.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "1number.png") create_listing.generate_html([f]) content = (tmp_path / "index.html").read_text() assert "0-9 / Special" in content def test_hash_group_sorts_first(self, tmp_path, make_png, monkeypatch): """Verify the special group appears before alphabetical groups in HTML.""" monkeypatch.chdir(tmp_path) f_special = make_png(tmp_path, "1first.png") f_alpha = make_png(tmp_path, "zebra.png") create_listing.generate_html([f_special, f_alpha]) content = (tmp_path / "index.html").read_text() special_pos = content.index("0-9 / Special") z_pos = content.index(">Z<") assert special_pos < z_pos def test_dark_theme(self, tmp_path, make_png, monkeypatch): """Verify the HTML uses dark theme background color.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "test.png") create_listing.generate_html([f]) content = (tmp_path / "index.html").read_text() assert "#1a1a1a" in content def test_emoji_count_shown(self, tmp_path, make_png, monkeypatch): """Verify the total emoji count is displayed.""" monkeypatch.chdir(tmp_path) files = [make_png(tmp_path, f"e{i}.png", color=(i, 0, 0, 255)) for i in range(3)] create_listing.generate_html(files) content = (tmp_path / "index.html").read_text() assert "3 emojis" in content def test_html_escapes_name(self, tmp_path, make_png, monkeypatch): """Verify HTML special characters in filenames are escaped.""" monkeypatch.chdir(tmp_path) f = make_png(tmp_path, "a