Files
openclaw/apps/ios/Tests/RemindersServiceTests.swift
Peter Lee e08e1a0ca8 fix(ios): attach EKAlarm to reminders.add so due-time notifications fire (#106376)
* fix(ios): attach EKAlarm to reminders.add so due-time notifications fire

EKReminder.dueDateComponents only sets the deadline; without an explicit
EKAlarm, iOS does not produce lock-screen or banner notifications.

Closes #105523

* fix(ios): configure reminder due alerts

Co-authored-by: xialonglee <li.xialong@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 01:14:40 -07:00

66 lines
2.6 KiB
Swift

import EventKit
import Foundation
import Testing
@testable import OpenClaw
struct RemindersServiceTests {
@Test func `due date uses Gregorian components and an absolute alarm`() throws {
let dueISO = "2026-07-18T10:15:30+09:00"
let expectedDate = try #require(ISO8601DateFormatter().date(from: dueISO))
let timeZone = try #require(TimeZone(secondsFromGMT: 9 * 60 * 60))
let reminder = EKReminder(eventStore: EKEventStore())
try RemindersService.applyDueISO(dueISO, to: reminder, timeZone: timeZone)
let start = try #require(reminder.startDateComponents)
let due = try #require(reminder.dueDateComponents)
let startCalendar = try #require(start.calendar)
let dueCalendar = try #require(due.calendar)
let reconstructedStartDate = try #require(startCalendar.date(from: start))
let reconstructedDueDate = try #require(dueCalendar.date(from: due))
let alarms = try #require(reminder.alarms)
#expect(startCalendar.identifier == .gregorian)
#expect(dueCalendar.identifier == .gregorian)
#expect(start.timeZone == timeZone)
#expect(due.timeZone == timeZone)
#expect(reconstructedStartDate == expectedDate)
#expect(reconstructedDueDate == expectedDate)
#expect(alarms.count == 1)
#expect(alarms[0].absoluteDate == expectedDate)
}
@Test func `missing due leaves reminder unscheduled`() throws {
let omittedValues: [String?] = [nil, "", " \n "]
for dueISO in omittedValues {
let reminder = EKReminder(eventStore: EKEventStore())
try RemindersService.applyDueISO(dueISO, to: reminder)
#expect(reminder.startDateComponents == nil)
#expect(reminder.dueDateComponents == nil)
#expect(!reminder.hasAlarms)
}
}
@Test func `due serialization honors the components calendar`() throws {
let timeZone = try #require(TimeZone(secondsFromGMT: 0))
var gregorian = Calendar(identifier: .gregorian)
gregorian.timeZone = timeZone
let components = DateComponents(
calendar: gregorian,
timeZone: timeZone,
year: 2026,
month: 7,
day: 18,
hour: 10,
minute: 15,
second: 30)
let expectedDate = try #require(gregorian.date(from: components))
var buddhist = Calendar(identifier: .buddhist)
buddhist.timeZone = timeZone
#expect(buddhist.date(from: components) != expectedDate)
#expect(RemindersService.date(fromDueComponents: components) == expectedDate)
}
}