# Map Feature Test Plan — Canteen Asset Tracker

## Map Stack
- **Library:** Leaflet 1.9.4 (open-source)
- **Tiles:** OpenStreetMap (free, no API key)
- **Plugins:** Leaflet Draw (geofence polygons), Leaflet Heat (heatmap)
- **Linking:** Google Maps Directions link opens externally

## Test Areas

### Frontend (UI)
- [ ] Map tab loads with OpenStreetMap tiles visible
- [ ] Asset pins render from API data
- [ ] Pin popups show name, machine_id, category, status, address, Directions link, Details button
- [ ] Directions link opens Google Maps in new tab
- [ ] Pin toggle (show/hide) works
- [ ] Heatmap toggle works
- [ ] GPS center button centers map + shows blue dot
- [ ] GPS toast shown when no GPS available
- [ ] "Add Geofence" draw mode activates polygon drawing
- [ ] Drawing mode cancellation clears temp layers
- [ ] Saved geofence renders as colored polygon
- [ ] Geofence popup shows name + Edit/Delete buttons
- [ ] Edit geofence trigger
- [ ] Delete geofence trigger

### API (50 tests in tests/test_map_api.py — all passing)
- [x] GET /api/geofences returns all geofences with parsed points (sorted by name)
- [x] POST /api/geofences creates geofence (with default color, duplicate names allowed)
- [x] PUT /api/geofences/:id updates geofence (name, color, points, partial updates)
- [x] DELETE /api/geofences/:id deletes geofence (204, verify gone)
- [x] POST /api/geofences/check returns matching geofences for a point
- [x] GET /api/proximity returns assets near GPS point (radius_meters, sorted by distance, max 50)
- [x] GET /api/assets?limit=1000 returns assets with lat/lng for pins
- [x] GPS coordinates survive asset update (PATCH semantics: null = preserve)
- [ ] Asset pins refresh when new assets are added (frontend concern)

### Edge Cases
- [x] Asset with null lat/lng excluded from proximity/pins
- [x] Empty geofence list (no geofences) — returns []
- [x] Invalid geofence polygon (self-intersecting) — no crash
- [x] Duplicate geofence name — allowed, both returned
- [x] 404 on update/delete nonexistent geofence
- [x] 422 on missing required fields (name, points, lat, lng)
- [x] Proximity radius bounds (min=1, max=50000, default=200)
- [x] Asset partial coordinates (lat-only, lng-only)
- [ ] Very large number of pins (performance) — frontend concern
- [ ] Map container hidden then shown (invalidateSize) — frontend concern
