import {
formatTemperature,
formatDateTime,
formatCurrentWeather,
formatHourlyWeather,
formatDailyWeather,
formatWeatherAlerts,
} from '../src/utils/formatters.js';
import type {
CurrentWeather,
HourlyWeather,
DailyWeather,
WeatherAlert,
} from '../src/types/weather.js';
describe('Formatters', () => {
describe('formatTemperature', () => {
it('should format temperature in Celsius by default', () => {
expect(formatTemperature(20.5)).toBe('21°C');
});
it('should format temperature in Fahrenheit', () => {
expect(formatTemperature(68.5, 'imperial')).toBe('69°F');
});
it('should format temperature in Kelvin', () => {
expect(formatTemperature(293.15, 'standard')).toBe('293K');
});
});
describe('formatDateTime', () => {
it('should format Unix timestamp to readable date', () => {
const timestamp = 1609459200; // 2021-01-01 00:00:00 UTC
const result = formatDateTime(timestamp);
expect(result).toMatch(/\d{1,2}\/\d{1,2}\/\d{4}/); // MM/DD/YYYY or similar format
});
});
describe('formatCurrentWeather', () => {
const mockCurrentWeather: CurrentWeather = {
dt: 1609459200,
sunrise: 1609422000,
sunset: 1609452000,
temp: 20,
feels_like: 18,
pressure: 1013,
humidity: 65,
dew_point: 15,
uvi: 3,
clouds: 40,
visibility: 10000,
wind_speed: 5,
wind_deg: 200,
weather: [
{
id: 800,
main: 'Clear',
description: 'clear sky',
icon: '01d',
},
],
};
it('should format current weather in metric units', () => {
const result = formatCurrentWeather(mockCurrentWeather);
expect(result).toContain('🌡️ Temperature: 20°C (feels like 18°C)');
expect(result).toContain('☁️ Condition: clear sky');
expect(result).toContain('💧 Humidity: 65%');
expect(result).toContain('💨 Wind: 5 m/s');
expect(result).toContain('👁️ Visibility: 10 km');
});
it('should format current weather in imperial units', () => {
const result = formatCurrentWeather(mockCurrentWeather, 'imperial');
expect(result).toContain('🌡️ Temperature: 20°F (feels like 18°F)');
expect(result).toContain('💨 Wind: 5 mph');
});
});
describe('formatHourlyWeather', () => {
const mockHourlyWeather: HourlyWeather[] = [
{
dt: 1609459200,
temp: 20,
feels_like: 18,
pressure: 1013,
humidity: 65,
dew_point: 15,
uvi: 3,
clouds: 40,
visibility: 10000,
wind_speed: 5,
wind_deg: 200,
weather: [
{
id: 800,
main: 'Clear',
description: 'clear sky',
icon: '01d',
},
],
pop: 0.3,
},
];
it('should format hourly weather with rain probability', () => {
const result = formatHourlyWeather(mockHourlyWeather);
expect(result).toContain('20°C');
expect(result).toContain('clear sky');
expect(result).toContain('(30% rain)');
});
it('should format hourly weather without rain probability when zero', () => {
const noRainWeather = [{ ...mockHourlyWeather[0], pop: 0 }];
const result = formatHourlyWeather(noRainWeather);
expect(result).not.toContain('rain');
});
});
describe('formatDailyWeather', () => {
const mockDailyWeather: DailyWeather[] = [
{
dt: 1609459200,
sunrise: 1609422000,
sunset: 1609452000,
moonrise: 1609440000,
moonset: 1609470000,
moon_phase: 0.5,
summary: 'Clear sky throughout the day',
temp: {
day: 20,
min: 15,
max: 25,
night: 18,
eve: 22,
morn: 16,
},
feels_like: {
day: 18,
night: 16,
eve: 20,
morn: 14,
},
pressure: 1013,
humidity: 65,
dew_point: 15,
wind_speed: 5,
wind_deg: 200,
weather: [
{
id: 800,
main: 'Clear',
description: 'clear sky',
icon: '01d',
},
],
clouds: 40,
pop: 0.2,
uvi: 3,
},
];
it('should format daily weather with high/low temperatures', () => {
const result = formatDailyWeather(mockDailyWeather);
expect(result).toContain('25°C/15°C');
expect(result).toContain('clear sky');
expect(result).toContain('(20% rain)');
});
});
describe('formatWeatherAlerts', () => {
const mockAlerts: WeatherAlert[] = [
{
sender_name: 'NWS',
event: 'Heat Wave',
start: 1609459200,
end: 1609545600,
description: 'Excessive heat warning in effect',
tags: ['heat', 'warning'],
},
];
it('should format weather alerts', () => {
const result = formatWeatherAlerts(mockAlerts);
expect(result).toContain('🚨 **Heat Wave**');
expect(result).toContain('📍 Issued by: NWS');
expect(result).toContain('📝 Excessive heat warning in effect');
expect(result).toContain('🏷️ Tags: heat, warning');
});
it('should handle empty alerts array', () => {
const result = formatWeatherAlerts([]);
expect(result).toBe('No active weather alerts');
});
});
});