da236643f2
Post-M2 self-walkthrough polish, batched into one commit. Map / heat: - fix heat-layer white-screen crash after login (add layer to map before setLatLngs; an off-map leaflet.heat layer has a null _map and throws) - normalize each heat layer to the densest pixel cell visible in the CURRENT viewport (maxZoom:0 so intensity factor f=1) and recompute on moveend/zoomend, so sparse poo data reaches red and stays normalized at any zoom level - dark CARTO basemap tiles when the color scheme is dark UI: - dark-mode toggle in the top-right, beside the settings gear - switch top-right nav (records / theme / settings / logout) to Feather icons with hover tooltips - home: Grafana-style quick time-range presets + back/forward shift buttons, placed between the From/To pickers and Apply; fix Select/tooltip z-index (Leaflet stacking) and the shift-button height alignment API client: - stop flooding GET /api/session with 401s: the session probe and the login endpoint own their 401s (no global redirect), which fixes the logout hang and the spinning login page Compose: - rename docker-compose.override.yml -> docker-compose.dev.yml as an explicit, non-auto-layered dev stack (8001, -dev container names, prod-copy ./data DB); update tests/test_deployment.py (read dev.yml, tolerate the !override tag) and the README "Docker Compose" section Tests: - pixel-grid peak counter, time-range presets, heat-layer ordering regression, and 401-redirect regression
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
/**
|
|
* Tests for peakGridCount — the pure pixel-grid peak counter used to normalize
|
|
* each heat layer to the densest cell visible in the current viewport.
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest'
|
|
import { peakGridCount } from './mapUtils'
|
|
|
|
describe('peakGridCount', () => {
|
|
it('returns 1 for empty input (no divide-by-zero)', () => {
|
|
expect(peakGridCount([], 10)).toBe(1)
|
|
})
|
|
|
|
it('counts coords sharing a grid cell and returns the peak', () => {
|
|
const coords: Array<[number, number]> = [
|
|
[0, 0],
|
|
[3, 4], // same 10px cell as [0,0]
|
|
[9, 9], // same 10px cell
|
|
[100, 100], // different cell
|
|
]
|
|
expect(peakGridCount(coords, 10)).toBe(3)
|
|
})
|
|
|
|
it('separates coords into different cells by cellSize', () => {
|
|
const coords: Array<[number, number]> = [
|
|
[0, 0],
|
|
[10, 0], // next cell over at cellSize 10
|
|
[20, 0], // next again
|
|
]
|
|
expect(peakGridCount(coords, 10)).toBe(1)
|
|
})
|
|
|
|
it('a denser cluster yields a larger peak (drives per-layer normalization)', () => {
|
|
const dense: Array<[number, number]> = Array.from({ length: 12 }, () => [5, 5] as [number, number])
|
|
const sparse: Array<[number, number]> = [
|
|
[5, 5],
|
|
[5, 5],
|
|
]
|
|
expect(peakGridCount(dense, 10)).toBe(12)
|
|
expect(peakGridCount(sparse, 10)).toBe(2)
|
|
})
|
|
})
|