# ABOUTME: Unit tests for DSL facet pills template component. # ABOUTME: Tests HTML generation for facet pill structure and HTMX attributes. from fasthtml.common import to_xml from animaltrack.repositories.animals import FacetCounts class TestDslFacetPills: """Test the dsl_facet_pills component.""" def test_facet_pills_renders_with_counts(self): """Facet pills component renders species counts as pills.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5, "goose": 3}, by_sex={"female": 4, "male": 3, "unknown": 1}, by_life_stage={"adult": 6, "juvenile": 2}, by_location={"loc1": 5, "loc2": 3}, ) locations = [] species_list = [] result = dsl_facet_pills(facets, "filter", locations, species_list) html = to_xml(result) # Should have container with proper ID assert 'id="dsl-facet-pills"' in html # Should have data attributes for JavaScript assert 'data-facet-field="species"' in html assert 'data-facet-value="duck"' in html assert 'data-facet-value="goose"' in html def test_facet_pills_has_htmx_attributes_for_refresh(self): """Facet pills container has HTMX attributes for dynamic refresh.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5}, by_sex={}, by_life_stage={}, by_location={}, ) result = dsl_facet_pills(facets, "filter", [], []) html = to_xml(result) # Should have HTMX attributes for updating facets assert "hx-get" in html assert "/api/facets" in html assert "hx-trigger" in html assert "#filter" in html # References the filter input def test_facet_pills_renders_all_facet_sections(self): """Facet pills renders species, sex, life_stage, and location sections.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5}, by_sex={"female": 3}, by_life_stage={"adult": 4}, by_location={"loc1": 5}, ) result = dsl_facet_pills(facets, "filter", [], []) html = to_xml(result) # Should have all section headers assert "Species" in html assert "Sex" in html assert "Life Stage" in html assert "Location" in html def test_facet_pills_includes_counts_in_pills(self): """Each pill shows the count alongside the label.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 12}, by_sex={}, by_life_stage={}, by_location={}, ) result = dsl_facet_pills(facets, "filter", [], []) html = to_xml(result) # Should show count 12 assert ">12<" in html or ">12 " in html or " 12<" in html def test_facet_pills_uses_location_names(self): """Location facets use human-readable names from location list.""" from animaltrack.models.reference import Location from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={}, by_sex={}, by_life_stage={}, by_location={"01ARZ3NDEKTSV4RRFFQ69G5FAV": 5}, ) locations = [ Location( id="01ARZ3NDEKTSV4RRFFQ69G5FAV", name="Strip 1", active=True, created_at_utc=0, updated_at_utc=0, ) ] result = dsl_facet_pills(facets, "filter", locations, []) html = to_xml(result) # Should display location name assert "Strip 1" in html def test_facet_pills_uses_species_names(self): """Species facets use human-readable names from species list.""" from animaltrack.models.reference import Species from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5}, by_sex={}, by_life_stage={}, by_location={}, ) species_list = [ Species( code="duck", name="Duck", active=True, created_at_utc=0, updated_at_utc=0, ) ] result = dsl_facet_pills(facets, "filter", [], species_list) html = to_xml(result) # Should display species name assert "Duck" in html def test_facet_pills_empty_facets_not_shown(self): """Empty facet sections are not rendered.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5}, by_sex={}, # Empty by_life_stage={}, # Empty by_location={}, # Empty ) result = dsl_facet_pills(facets, "filter", [], []) html = to_xml(result) # Should show Species but not empty sections assert "Species" in html # Sex section header should not appear since no sex facets # (we count section headers, not raw word occurrences) def test_facet_pills_onclick_calls_javascript(self): """Pill click handler uses JavaScript to update filter.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills facets = FacetCounts( by_species={"duck": 5}, by_sex={}, by_life_stage={}, by_location={}, ) result = dsl_facet_pills(facets, "filter", [], []) html = to_xml(result) # Should have onclick or similar handler assert "onclick" in html or "hx-on:click" in html class TestFacetPillsSection: """Test the facet_pill_section helper function.""" def test_section_sorts_by_count_descending(self): """Pills are sorted by count in descending order.""" from animaltrack.web.templates.dsl_facets import facet_pill_section counts = {"a": 1, "b": 5, "c": 3} result = facet_pill_section("Test", counts, "filter", "field") html = to_xml(result) # "b" (count 5) should appear before "c" (count 3) which appears before "a" (count 1) pos_b = html.find('data-facet-value="b"') pos_c = html.find('data-facet-value="c"') pos_a = html.find('data-facet-value="a"') assert pos_b < pos_c < pos_a, "Pills should be sorted by count descending" def test_section_returns_none_for_empty_counts(self): """Empty counts returns None (no section rendered).""" from animaltrack.web.templates.dsl_facets import facet_pill_section result = facet_pill_section("Test", {}, "filter", "field") assert result is None def test_section_applies_label_map(self): """Label map transforms values to display labels.""" from animaltrack.web.templates.dsl_facets import facet_pill_section counts = {"val1": 5} label_map = {"val1": "Display Label"} result = facet_pill_section("Test", counts, "filter", "field", label_map) html = to_xml(result) assert "Display Label" in html class TestDslFacetPillsScript: """Test the JavaScript for facet pills interaction.""" def test_script_included_in_component(self): """Facet pills component includes the JavaScript for interaction.""" from animaltrack.web.templates.dsl_facets import dsl_facet_pills_script result = dsl_facet_pills_script("filter") html = to_xml(result) # Should be a script element assert "