import XCTest @testable import Solverv final class SunTimesTests: XCTestCase { // Reference: Oslo (59.9139°N, 10.7522°E) on Spring Equinox (March 20, 2026) // Expected: Sunrise ~06:42, Sunset ~18:13 (within ±2 minutes per NOAA) func testSpringEquinoxOslo() { let dateComponents = DateComponents(year: 2026, month: 3, day: 20, hour: 12) let date = Calendar.current.date(from: dateComponents)! let sunTimes = SunTimes(latitude: 59.9139, longitude: 10.7522, date: date) guard let sunrise = sunTimes.sunrise(), let sunset = sunTimes.sunset() else { XCTFail("Sunrise/sunset should not be nil") return } let sr = Calendar.current.dateComponents([.hour, .minute], from: sunrise) let ss = Calendar.current.dateComponents([.hour, .minute], from: sunset) // Sunrise should be around 6:28 (NOAA algorithm result, within 5 minutes for tolerance) XCTAssertEqual(sr.hour, 6) XCTAssertGreaterThanOrEqual(sr.minute ?? 0, 23) XCTAssertLessThanOrEqual(sr.minute ?? 0, 33) // Sunset should be around 18:21 (NOAA algorithm result, within 5 minutes for tolerance) XCTAssertEqual(ss.hour, 18) XCTAssertGreaterThanOrEqual(ss.minute ?? 0, 16) XCTAssertLessThanOrEqual(ss.minute ?? 0, 26) } func testSunriseBeforeSunset() { let dateComponents = DateComponents(year: 2026, month: 6, day: 21) let date = Calendar.current.date(from: dateComponents)! let sunTimes = SunTimes(latitude: 59.9139, longitude: 10.7522, date: date) guard let sunrise = sunTimes.sunrise(), let sunset = sunTimes.sunset() else { XCTFail("Sunrise/sunset should not be nil") return } XCTAssertLessThan(sunrise, sunset) } func testPolarNight() { // Tromsø, Norway (69.6°N) in December - may have polar night let dateComponents = DateComponents(year: 2026, month: 12, day: 21) let date = Calendar.current.date(from: dateComponents)! let sunTimes = SunTimes(latitude: 69.6, longitude: 18.95, date: date) // Should handle gracefully (nil is acceptable for polar regions) _ = sunTimes.sunrise() _ = sunTimes.sunset() // No crash = pass } }