import Testing import Foundation @testable import CalendarProvider @Suite("Terminliste nach Tagen") struct AgendaGroupingTests { private var calendar: Calendar { var calendar = Calendar(identifier: .gregorian) calendar.timeZone = TimeZone(identifier: "Europe/Berlin")! return calendar } private func date(_ day: Int, _ hour: Int = 0) -> Date { calendar.date(from: DateComponents(year: 2026, month: 8, day: day, hour: hour))! } private func event(_ title: String, day: Int, hour: Int = 0, allDay: Bool = false) -> OnyxEvent { OnyxEvent(id: "\(title)-\(day)-\(hour)", title: title, start: date(day, hour), end: date(day, hour + 1), isAllDay: allDay, colorHex: nil, location: nil, calendarID: "c", calendarTitle: "C") } @Test("Termine landen unter ihrem Tag") func groupsByDay() { // Der Fall aus der Praxis: zweimal „Nina arbeiten, 8:00" untereinander, // und nichts verriet, welcher Tag gemeint war. let days = AgendaGrouping.group([ event("Nina arbeiten", day: 14, hour: 8), event("Grillplausch", day: 15, hour: 18), event("Nina arbeiten", day: 16, hour: 8), ], calendar: calendar) #expect(days.count == 3) #expect(days.map(\.events.count) == [1, 1, 1]) #expect(days[0].date == date(14)) } @Test("Die Tage kommen in ihrer Reihenfolge") func daysStayInOrder() { let days = AgendaGrouping.group([ event("Später", day: 16), event("Früher", day: 14), ], calendar: calendar) #expect(days.map(\.date) == [date(14), date(16)]) } @Test("Ganztägige Termine stehen über den Uhrzeiten") func allDayComesFirst() { // Sie beginnen um Mitternacht und stünden sonst zwischen den frühen // Terminen — dabei gelten sie für den ganzen Tag. let days = AgendaGrouping.group([ event("Frühschicht", day: 14, hour: 6), event("Urlaub", day: 14, allDay: true), ], calendar: calendar) #expect(days[0].events.map(\.title) == ["Urlaub", "Frühschicht"]) } @Test("Heute, morgen und später sind auseinandergehalten") func dayKinds() { let today = date(14, 12) #expect(AgendaGrouping.kind(for: date(14), today: today, calendar: calendar) == .today) #expect(AgendaGrouping.kind(for: date(15), today: today, calendar: calendar) == .tomorrow) #expect(AgendaGrouping.kind(for: date(20), today: today, calendar: calendar) == .later) // Auch rückwärts: ein Termin von gestern ist nicht „heute". #expect(AgendaGrouping.kind(for: date(13), today: today, calendar: calendar) == .later) } @Test("Später steht das Datum in der Überschrift") func laterDaysShowTheDate() { // Der Wochentag allein wäre in drei Wochen mehrdeutig. let label = AgendaGrouping.label(for: date(20), today: date(14, 12), calendar: calendar) #expect(label.contains("20")) } @Test("Eine späte Uhrzeit zählt noch zum selben Tag") func lateHoursStayOnTheirDay() { // Nicht selbstverständlich: mit UTC statt der lokalen Zone rutschte ein // Termin um 23 Uhr auf den Folgetag. let days = AgendaGrouping.group([ event("Spät", day: 14, hour: 23), event("Früh", day: 14, hour: 7), ], calendar: calendar) #expect(days.count == 1) } @Test("Ohne Termine gibt es keine Tage") func emptyStaysEmpty() { #expect(AgendaGrouping.group([], calendar: calendar).isEmpty) } }