From 13de96b30198de1d5c25169a3d07346676e3421d Mon Sep 17 00:00:00 2001 From: JacobSampson Date: Sat, 6 Jun 2026 14:23:01 -0500 Subject: [PATCH] fix: style_function now reads depth_ft from feature properties in contour renderer (APR-169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the per-feature GeoJson loop (which used lambda x, s=style: s — ignoring x) with a single folium.GeoJson over the full FeatureCollection whose style_function extracts depth_ft from each feature's properties and calls _depth_to_color, the idiomatic Folium pattern. This ensures each contour line receives its correct depth-based color rather than a static style, fixing the identical-line rendering bug. Also simplify add_species_zone_overlay's lambda from lambda x, s=style: s to lambda x: style — the zone color is uniform so no per-feature extraction is needed, and the simpler form makes the intent clear. Add a regression test that verifies both depth-specific colors appear in the rendered HTML output. Co-Authored-By: Claude Sonnet 4.6 --- app/components/dnr_map.py | 21 +++++++++------------ tests/test_dnr_map_bathymetry.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/app/components/dnr_map.py b/app/components/dnr_map.py index b2feac0..aced6da 100644 --- a/app/components/dnr_map.py +++ b/app/components/dnr_map.py @@ -99,17 +99,14 @@ def add_depth_contours( fg = folium.FeatureGroup(name="Depth Contours", show=show) - for feature in geojson_data.get("features", []): - depth = feature.get("properties", {}).get("depth_ft", 0) - color = _depth_to_color(depth) - style = {**_CONTOUR_STYLE_BASE, "color": color} - tooltip = f"{depth:.0f} ft" - - folium.GeoJson( - feature, - style_function=lambda x, s=style: s, - tooltip=tooltip, - ).add_to(fg) + folium.GeoJson( + geojson_data, + style_function=lambda x: { + **_CONTOUR_STYLE_BASE, + "color": _depth_to_color(x["properties"].get("depth_ft", 0)), + }, + tooltip=folium.GeoJsonTooltip(fields=["depth_ft"], aliases=["Depth (ft):"]), + ).add_to(fg) fg.add_to(m) return fg @@ -148,7 +145,7 @@ def add_species_zone_overlay( folium.GeoJson( collection, - style_function=lambda x, s=style: s, + style_function=lambda x: style, tooltip=f"{species_name}: {depth_range[0]:.0f}-{depth_range[1]:.0f} ft preferred", ).add_to(fg) diff --git a/tests/test_dnr_map_bathymetry.py b/tests/test_dnr_map_bathymetry.py index eb502f2..9b01906 100644 --- a/tests/test_dnr_map_bathymetry.py +++ b/tests/test_dnr_map_bathymetry.py @@ -2,6 +2,7 @@ from __future__ import annotations import json +import re from pathlib import Path from typing import Any, Dict @@ -10,6 +11,7 @@ try: import folium from components.dnr_map import ( + _depth_to_color, add_depth_contours, add_species_zone_overlay, build_lake_map, @@ -70,6 +72,18 @@ def test_returns_none_when_no_data(self, tmp_path): fg = add_depth_contours(m, "Nonexistent Lake", bathymetry_dir=tmp_path) assert fg is None + def test_style_function_reads_depth_from_properties(self, sample_contour_geojson): + """style_function must extract depth_ft from feature properties, producing distinct + colors for different depths — not a static style that ignores feature properties.""" + m = folium.Map(location=[45.3, -94.1], zoom_start=10) + add_depth_contours(m, "Clearwater", bathymetry_dir=sample_contour_geojson) + html = m._repr_html_() + color_10ft = _depth_to_color(10.0) + color_25ft = _depth_to_color(25.0) + assert color_10ft != color_25ft, "test requires two distinct depth colors" + assert color_10ft in html, f"expected color for 10 ft ({color_10ft}) not found in rendered HTML" + assert color_25ft in html, f"expected color for 25 ft ({color_25ft}) not found in rendered HTML" + class TestAddSpeciesZoneOverlay: def test_adds_zone_for_matching_depths(self, sample_contour_geojson):