import { describe, it, expect, beforeEach, vi } from 'vitest' import { NotificationStore } from '../../../src/lib/stores/notifications.svelte.js' import { app } from '../../../src/lib/stores/app.svelte.js' // We need to mock app.forecastData and app.settings for alert analysis describe('NotificationStore', () => { let notifications beforeEach(() => { notifications = new NotificationStore() notifications.alerts = [] notifications.dismissedIds.clear() }) function setForecast(overrides = {}) { app.forecastData = { current: { weather_code: 0, ...overrides.current, }, daily: { time: ['2026-07-22', '2026-07-23', '2026-07-24'], precipitation_probability_max: [10, 5, 0], weather_code: [0, 1, 2], temperature_2m_max: [25, 27, 28], temperature_2m_min: [15, 16, 17], uv_index_max: [3, 4, 5], wind_speed_10m_max: [15, 12, 10], ...overrides.daily, }, } app.settings = { alertsEnabled: true, windUnit: 'kmh', alertThresholds: { precip: 70, windGust: 40, uvIndex: 6, tempHigh: 35, tempLow: 0, thunderstorm: true, }, } } it('does not generate alerts when disabled', () => { setForecast() app.settings.alertsEnabled = false notifications.analyze() expect(notifications.alerts).toHaveLength(0) }) it('generates no alerts for calm weather', () => { setForecast() notifications.analyze() expect(notifications.alerts).toHaveLength(0) }) it('generates precipitation alert when threshold exceeded', () => { setForecast({ daily: { precipitation_probability_max: [85, 30, 10] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'precip')).toBe(true) }) it('generates thunderstorm alert for severe codes in forecast', () => { setForecast({ daily: { weather_code: [95, 0, 0] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'storm')).toBe(true) }) it('generates thunderstorm alert for current conditions', () => { setForecast({ current: { weather_code: 95 }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.id === 'storm-now')).toBe(true) }) it('generates heat alert', () => { setForecast({ daily: { temperature_2m_max: [38, 35, 32] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'heat')).toBe(true) }) it('generates cold alert', () => { setForecast({ daily: { temperature_2m_min: [-5, 0, 5] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'cold')).toBe(true) }) it('generates UV alert', () => { setForecast({ daily: { uv_index_max: [8, 5, 3] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'uv')).toBe(true) }) it('generates wind alert', () => { setForecast({ daily: { wind_speed_10m_max: [50, 20, 15] }, }) notifications.analyze() expect(notifications.alerts.some((a) => a.type === 'wind')).toBe(true) }) it('dismisses an alert', () => { setForecast({ daily: { precipitation_probability_max: [85, 30, 10] }, }) notifications.analyze() const precipAlert = notifications.alerts.find((a) => a.type === 'precip') expect(precipAlert).toBeTruthy() notifications.dismiss(precipAlert.id) expect(notifications.alerts.find((a) => a.id === precipAlert.id)).toBeUndefined() }) it('resets dismissed alerts', () => { setForecast({ daily: { precipitation_probability_max: [85, 30, 10] }, }) notifications.analyze() const alertCount = notifications.alerts.length notifications.dismiss(notifications.alerts[0].id) notifications.resetDismissed() notifications.analyze() expect(notifications.alerts.length).toBe(alertCount) }) it('filters alerts for only first 3 days', () => { setForecast({ daily: { time: ['2026-07-22', '2026-07-23', '2026-07-24', '2026-07-25', '2026-07-26', '2026-07-27', '2026-07-28'], precipitation_probability_max: [80, 80, 80, 80, 80, 80, 80], weather_code: [0, 0, 0, 0, 0, 0, 0], temperature_2m_max: [25, 25, 25, 25, 25, 25, 25], temperature_2m_min: [15, 15, 15, 15, 15, 15, 15], uv_index_max: [3, 3, 3, 3, 3, 3, 3], wind_speed_10m_max: [15, 15, 15, 15, 15, 15, 15], }, }) notifications.analyze() const precipAlerts = notifications.alerts.filter((a) => a.type === 'precip') // Should only alert for the first 3 days (i < 3) expect(precipAlerts.length).toBeLessThanOrEqual(3) }) })