committed 06:10PM - 10 Jul 26 UTC
* test(frontend): add unit/e2e coverage for all pages, German locale, and click …flows
- Component tests for every page under app/pages/ (history, meteogram,
settings, widget), plus German-locale rendering assertions (not just i18n
key parity) since de is the app's defaultLocale.
- Real-browser e2e coverage for Forecast/History/Settings/Widget pages and a
full click-driven History fetch/expand/reset flow.
- Additional click-driven interaction tests (buttons, switches, collapsibles)
for Explorer and Climate Stripes.
- Removes tests/pages/* and tests/components/DateRangeSelector.test.ts: dead
files never picked up by vitest.config.ts's include globs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(explorer): remove provider/network preselection to match resolution/dataset
ParameterSelection defaulted an empty Explorer selection to dwd/observation,
while resolution/dataset/parameters were already left unset (previous commit
259403fa). That inconsistency nudged users toward a specific provider before
they'd looked at the options, and meant Explorer wasn't actually free-choice
on first load like the UI implied. Provider/network are now left unset too,
same as the other fields; History is unaffected since it forces dwd/observation
via its own restrict-provider/restrict-network props regardless.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(map): set window.L lazily so <LMap use-global-leaflet> actually works
A prior perf change removed the global Leaflet plugin, on the assumption
that <LMap use-global-leaflet> and useLMarkerCluster() (from @nuxtjs/leaflet)
set window.L themselves on mount. They don't -- both only read it, so with
nothing setting it, the map's mounted hook threw before rendering any tiles,
leaving a blank white box wherever a station map was shown.
window.L is now set as a side effect inside MapStations.vue itself, which is
already lazy-loaded (mounted only inside a ClientOnly + collapsible map
picker), so leaflet still only ships to pages that actually render a map --
this doesn't reintroduce the bundle-size regression the plugin removal fixed.
`leaflet` is also added as a direct dependency: it was only ever a transitive
dependency of @nuxtjs/leaflet/leaflet.markercluster, which pnpm's strict
node_modules linking doesn't expose for direct import from application code.
Verified via a real-Chromium Playwright probe: tiles now return 200 and
marker clusters render with real station counts; a map-less page (Impressum)
still fetches zero leaflet JS.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* perf(station-selection): fetch the station list lazily on picker open
/api/stations was fetched as soon as a dataset's parameters were valid, even
before the user opened the select menu or map to look at stations -- wasted
work for a potentially large list on every parameter change. It's now
fetched on first open of either picker instead, tracked via a stationsLoaded
flag reset whenever parameters change. The one exception: a station
preselected via a shared URL (initialStationIds) is still fetched eagerly,
since restoring that selection can't wait for the user to open anything.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(parameter-selection): don't silently drop an unavailable provider/network restriction
restrictProvider/restrictNetwork (used by History to lock to dwd/observation)
silently fell back to the full unrestricted provider/network list whenever
the restricted value wasn't actually present in the backend's coverage --
e.g. a stale restriction, or the provider requiring auth that isn't
configured. The disabled select would then show nothing selected while (if
ever enabled) listing every provider, with no indication anything was wrong.
`providers`/`networks` now always reflect backend reality, independent of any
restriction, so validity can be checked against it directly. New
providerItems/networkItems computeds are what the (disabled) selects actually
render: the restricted value only once confirmed available, otherwise empty.
A restrictedProviderAvailable/restrictedNetworkAvailable mismatch now shows an
explicit error via UAlert instead of a silently half-locked form.
Also fixes a latent test-isolation bug this surfaced: useFetch's payload
cache for /api/coverage is shared across mounts within a test file, so a
later test's registerEndpoint() mock could be shadowed by an earlier test's
cached response. clearNuxtData() in beforeEach resets it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(frontend): catch rejected router.replace() navigations to prevent unhandled rejections
CI's Unit & Component Tests job failed with an unhandled ReferenceError
(history is not defined) from vue-router's finalizeNavigation, surfaced by
tests/nuxt/pages/i18n-de.test.ts mounting HistoryPage. Its watcher fires
router.replace() fire-and-forget on every paramSel/stationIds/selectedSections
change (including ParameterSelection's own async init), with nothing handling
a rejected navigation -- a known Vue Router footgun (a replace() superseded by
a later one before it resolves rejects), not just a test-environment quirk.
Explorer, Stripes, and Meteogram have the identical pattern (fire-and-forget
router.replace() in a watcher, meteogram.vue's `void` only silences the
floating-promise lint rule, it doesn't handle rejection), so all four now
attach a no-op .catch().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(station-selection): reset loaded state on failed station fetch
Addresses a Copilot review comment on PR #1732: stationsLoaded was set to
true before refreshStations() resolved and never reset on failure, so a
failed /api/stations request (transient network/backend error) left the
picker stuck -- reopening it wouldn't retry, and the empty result looked
identical to a confirmed "no stations found" rather than a failed request.
fetchStations() now awaits the refresh and resets stationsLoaded if it
errored, and the template shows a distinct error message instead of "none
found" in that case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>