fix(weather): one failed fetch no longer parks the badge on the dash (#2167)

failed was set once and never cleared, so a single hiccup kept the badge on its error dash while later fetches quietly delivered data. It resets with every new anchor.
This commit is contained in:
Maurice
2026-09-02 19:01:17 +02:00
committed by Maurice
parent 1428637694
commit 31fa8908fc
2 changed files with 45 additions and 0 deletions
@@ -208,4 +208,45 @@ describe('WeatherWidget', () => {
expect(weatherApi.get).toHaveBeenCalledWith(48.86, 2.35, '2025-06-01', 'de')
expect(sessionStorage.getItem('weather_48.86_2.35_2025-06-01_de')).not.toBeNull()
})
// The day-local anchor (#2167) moves whenever the day is edited, so a single
// failed lookup must not keep the badge on the dash for the widget's lifetime.
it('FE-COMP-WEATHERWIDGET-016: clears the error dash once a new anchor resolves', async () => {
vi.mocked(weatherApi.get).mockRejectedValueOnce(new Error('Network error'))
vi.mocked(weatherApi.get).mockResolvedValue(buildWeather({ temp: 21 }))
useSettingsStore.setState({ settings: { ...useSettingsStore.getState().settings, temperature_unit: 'celsius' } })
const { rerender } = render(<WeatherWidget lat={48.86} lng={2.35} date="2025-06-01" />)
await waitFor(() => {
expect(screen.getByText('—')).toBeInTheDocument()
})
rerender(<WeatherWidget lat={41.9} lng={12.5} date="2025-06-01" />)
await waitFor(() => {
expect(screen.getByText('21°C')).toBeInTheDocument()
})
expect(screen.queryByText('—')).not.toBeInTheDocument()
})
it('FE-COMP-WEATHERWIDGET-017: clears the error dash when the new anchor comes from cache', async () => {
vi.mocked(weatherApi.get).mockRejectedValue(new Error('Network error'))
sessionStorage.setItem(
'weather_41.9_12.5_2025-06-01_en',
JSON.stringify({ data: buildWeather({ temp: 24 }), fetchedAt: Date.now() }),
)
useSettingsStore.setState({ settings: { ...useSettingsStore.getState().settings, temperature_unit: 'celsius' } })
const { rerender } = render(<WeatherWidget lat={48.86} lng={2.35} date="2025-06-01" />)
await waitFor(() => {
expect(screen.getByText('—')).toBeInTheDocument()
})
rerender(<WeatherWidget lat={41.9} lng={12.5} date="2025-06-01" />)
await waitFor(() => {
expect(screen.getByText('24°C')).toBeInTheDocument()
})
expect(weatherApi.get).toHaveBeenCalledTimes(1)
})
})
@@ -63,6 +63,10 @@ export default function WeatherWidget({ lat, lng, date, compact = false, stacked
useEffect(() => {
if (!lat || !lng || !date) return
let cancelled = false
// Every anchor, date or language change is a fresh attempt, so a failure from
// the previous one must not outlive it. Since #2167 the anchor is day-local and
// moves with each edit, which would otherwise pin the badge on the error dash.
setFailed(false)
const rLat = Math.round(lat * 100) / 100
const rLng = Math.round(lng * 100) / 100
// The language is part of the key: descriptions come back localized, and the