Files
kapteins-daagbok/server/src/utils/tideProvider.test.ts
T

121 lines
3.9 KiB
TypeScript

import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
import * as bshTides from './bshTides.js'
import * as openMeteoTides from './openMeteoTides.js'
import { fetchTidesForCoordinates, fetchTidesForPlace } from './tideProvider.js'
describe('fetchTidesForCoordinates', () => {
beforeEach(() => {
vi.restoreAllMocks()
})
afterEach(() => {
vi.restoreAllMocks()
})
it('returns BSH data when station is within range', async () => {
vi.spyOn(bshTides, 'fetchBshTidesForCoordinates').mockResolvedValue({
distanceKm: 8,
location: {
name: 'Norderney, Riffgat',
lat: 53.696389,
lon: 7.157778,
source: 'bsh_station',
stationId: 'norderney_riffgat'
},
tides: {
data: {
timezone: 'Europe/Berlin',
datum: 'gauge',
source: 'BSH',
extrema: [
{
time: '2026-06-12T07:20:00.000Z',
date: '2026-06-12',
height: 6.16,
isHigh: true
}
]
}
}
})
const result = await fetchTidesForCoordinates(53.62, 7.15)
expect(result.distanceKm).toBe(8)
expect(result.location.source).toBe('bsh_station')
expect(result.fallback).toBeUndefined()
})
it('falls back to Open-Meteo when BSH station is too far', async () => {
vi.spyOn(bshTides, 'fetchBshTidesForCoordinates').mockRejectedValue(
Object.assign(new Error('bsh_station_too_far'), { distanceKm: 120 })
)
vi.spyOn(openMeteoTides, 'fetchTidesForCoordinates').mockResolvedValue({
location: { lat: 62, lon: 5, source: 'coordinates' },
tides: {
data: {
timezone: 'Europe/Oslo',
datum: 'MSL',
source: 'Open-Meteo Marine',
extrema: [
{
time: '2026-06-12T10:00:00.000Z',
date: '2026-06-12',
height: 1.2,
isHigh: true
}
]
}
}
})
const result = await fetchTidesForCoordinates(62, 5)
expect(result.fallback).toBe('open_meteo')
expect(result.tides.data.source).toContain('Fallback')
})
})
describe('fetchTidesForPlace', () => {
beforeEach(() => {
vi.restoreAllMocks()
})
afterEach(() => {
vi.restoreAllMocks()
})
it('matches BSH station directly by name startsWith', async () => {
vi.spyOn(bshTides, 'loadBshStationIndex').mockResolvedValue([
{ id: 'buesum_schleuse', name: 'Büsum, Schleuse', lat: 54.12, lon: 8.85 }
])
const fetchSpy = vi.spyOn(bshTides, 'fetchBshTidesForStation').mockResolvedValue({
distanceKm: 0,
location: { name: 'Büsum, Schleuse', lat: 54.12, lon: 8.85, source: 'bsh_station', stationId: 'buesum_schleuse' },
tides: { data: { timezone: 'Europe/Berlin', datum: 'gauge', source: 'BSH', extrema: [] } }
})
const result = await fetchTidesForPlace('Buesum')
expect(fetchSpy).toHaveBeenCalledWith('buesum_schleuse', undefined)
expect(result.location.name).toBe('Büsum, Schleuse')
})
it('falls back to geocoding if BSH station index does not match', async () => {
vi.spyOn(bshTides, 'loadBshStationIndex').mockResolvedValue([
{ id: 'buesum_schleuse', name: 'Büsum, Schleuse', lat: 54.12, lon: 8.85 }
])
vi.spyOn(openMeteoTides, 'geocodePlace').mockResolvedValue({
name: 'Kiel',
latitude: 54.32,
longitude: 10.13
})
const coordSpy = vi.spyOn(bshTides, 'fetchBshTidesForCoordinates').mockResolvedValue({
distanceKm: 0,
location: { name: 'Kiel-Holtenau', lat: 54.37, lon: 10.15, source: 'bsh_station', stationId: 'kiel_holtenau' },
tides: { data: { timezone: 'Europe/Berlin', datum: 'gauge', source: 'BSH', extrema: [] } }
})
const result = await fetchTidesForPlace('Kiel')
expect(coordSpy).toHaveBeenCalledWith(54.32, 10.13)
expect(result.location.name).toBe('Kiel-Holtenau')
})
})