UNPKG

@fmidev/smartmet-alert-client

Version:

Web application for viewing weather and flood alerts

214 lines (177 loc) 6.3 kB
import { describe, it, expect } from 'vitest' import { uncapitalize, twoDigits, warningType, regionFromReference, relativeCoverageFromReference, toTimeZone, msSinceStartOfDay, validInterval, } from '@/composables/useUtils' describe('useUtils composable - pure functions', () => { describe('uncapitalize', () => { it('should uncapitalize first letter', () => { expect(uncapitalize('HelloWorld')).toBe('helloWorld') }) it('should handle empty string', () => { expect(uncapitalize('')).toBe('') }) it('should handle null', () => { expect(uncapitalize(null)).toBe('') }) it('should handle single character', () => { expect(uncapitalize('A')).toBe('a') }) }) describe('warningType', () => { it('should parse thunderStorm type correctly', () => { const result = warningType({ warning_context: 'thunder-storm', }) expect(result).toBe('thunderStorm') }) it('should parse wind type correctly', () => { const result = warningType({ warning_context: 'wind', }) expect(result).toBe('wind') }) it('should handle sea-wind with extension', () => { const result = warningType({ warning_context: 'sea-wind', }) expect(result).toBe('seaWind') }) it('should handle context with extension', () => { const result = warningType({ warning_context: 'sea-water-height', context_extension: 'high-water', }) expect(result).toBe('seaWaterHeightHighWater') }) it('should handle multi-word contexts', () => { const result = warningType({ warning_context: 'forest-fire-weather', }) expect(result).toBe('forestFireWeather') }) }) describe('regionFromReference', () => { it('should parse single region reference', () => { const result = regionFromReference('fi-warning#county.1') expect(result).toBe('county.1') }) it('should parse merged region reference', () => { const result = regionFromReference( 'fi-warning#county.1,fi-warning#county.2' ) expect(result).toBe('county_1.2') }) it('should parse multiple merged regions', () => { const result = regionFromReference( 'fi-warning#county.1,fi-warning#county.2,fi-warning#county.3' ) expect(result).toBe('county_1_2.3') }) it('should handle Saimaa special case (lake region)', () => { const result = regionFromReference( 'fi-warning#sea_region_south.FI-115978' ) expect(result).toBe('sea_region_south.FI-115978') }) }) describe('relativeCoverageFromReference', () => { it('should extract coverage from reference URL', () => { const result = relativeCoverageFromReference('fi-warning#county.1?c=75') expect(result).toBe(75) }) it('should return 0 when no coverage parameter', () => { const result = relativeCoverageFromReference('fi-warning#county.1') expect(result).toBe(0) }) it('should return 0 when no query string', () => { const result = relativeCoverageFromReference('county.1') expect(result).toBe(0) }) it('should return 0 for null reference', () => { const result = relativeCoverageFromReference(null) expect(result).toBe(0) }) it('should handle URL with hash fragment', () => { const result = relativeCoverageFromReference( 'fi-warning#county.1?c=50#fragment' ) expect(result).toBe(50) }) }) describe('twoDigits', () => { it('should pad single digit with zero', () => { expect(twoDigits(5)).toBe('05') }) it('should not pad double digit', () => { expect(twoDigits(15)).toBe('15') }) it('should handle zero', () => { expect(twoDigits(0)).toBe('00') }) }) describe('toTimeZone', () => { const timeZone = 'Europe/Helsinki' const locale = 'fi-FI' it('should convert UTC to Helsinki timezone', () => { const date = new Date('2025-10-31T12:00:00Z') const result = toTimeZone(date, timeZone, locale) expect(result.timeZone).toBe('Europe/Helsinki') expect(result.year).toBe(2025) expect(result.month).toBe(10) expect(result.day).toBe(31) // Helsinki is UTC+2 during DST (summer) or UTC+2 after DST ends expect(result.hour).toBe(14) }) it('should handle different date formats', () => { const date = '2025-10-31T12:00:00Z' const result = toTimeZone(date, timeZone, locale) expect(result.year).toBe(2025) expect(result.month).toBe(10) expect(result.day).toBe(31) }) }) describe('msSinceStartOfDay', () => { const timeZone = 'Europe/Helsinki' const locale = 'fi-FI' it('should calculate milliseconds since start of day', () => { // 12:00:00 UTC = 14:00 in Helsinki (UTC+2) const timestamp = new Date('2025-10-31T12:00:00Z').getTime() const result = msSinceStartOfDay(timestamp, timeZone, locale) // 14 * 60 * 60 * 1000 = 50400000 ms expect(result).toBeGreaterThan(40000000) // At least 11+ hours expect(result).toBeLessThan(60000000) // Less than 17 hours }) it('should handle midnight', () => { const timestamp = new Date('2025-10-31T00:00:00Z').getTime() const result = msSinceStartOfDay(timestamp, timeZone, locale) expect(result).toBeGreaterThanOrEqual(0) expect(result).toBeLessThan(24 * 60 * 60 * 1000) }) }) describe('validInterval', () => { const timeZone = 'Europe/Helsinki' const locale = 'fi-FI' it('should format time interval with HTML time elements', () => { const start = '2025-10-31T12:00:00Z' const end = '2025-11-01T18:00:00Z' const result = validInterval(start, end, timeZone, locale) // Should contain both dates and times as display text expect(result).toContain('31.10.') expect(result).toContain('1.11.') expect(result).toContain('–') // en-dash separator }) it('should include time in HH:MM format', () => { const start = '2025-10-31T12:00:00Z' const end = '2025-10-31T18:00:00Z' const result = validInterval(start, end, timeZone, locale) expect(result).toMatch(/\d{2}:\d{2}/) }) }) })