Skip to content

Commit

Permalink
[iOS] Fix iOS tests and SDK event expansion
Browse files Browse the repository at this point in the history
The way that we count events and occurrences changed with the
implementation of the advanced repeat rules, given that, we've had to
fix tests that relies on these counts.

This commit address one corner case for weekly events expansion on SDK
and fixes the tests on Swift.
  • Loading branch information
mup committed Feb 6, 2025
1 parent 7446664 commit 5ca250b
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 26 deletions.
5 changes: 3 additions & 2 deletions app-ios/TutanotaSharedFramework/Alarms/AlarmModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,15 @@ private struct LazyEventSequence: Sequence, IteratorProtocol {

mutating func next() -> EventOccurrence? {
if case let .count(n) = repeatRule.endCondition, occurrenceNumber >= n { return nil }
if intervalNumber > EVENTS_SCHEDULED_AHEAD { return nil }

if expandedEvents.isEmpty {
let nextExpansionProgenitor = cal.date(byAdding: self.calendarComponent, value: repeatRule.interval * intervalNumber, to: calcEventStart)!
let progenitorTime = UInt64(nextExpansionProgenitor.timeIntervalSince1970)
let eventFacade = EventFacade()
let byRules = repeatRule.advancedRules.map { $0.toSDKRule() }
let generatedEvents = eventFacade.generateFutureInstances(
date: progenitorTime * 1000,
date: progenitorTime,
repeatRule: EventRepeatRule(frequency: repeatRule.frequency.toSDKPeriod(), byRules: byRules)
)
self.expandedEvents.append(contentsOf: generatedEvents)
Expand All @@ -162,7 +163,7 @@ private struct LazyEventSequence: Sequence, IteratorProtocol {

return true
}
.map { (_, event) in event }
.map { (_, event) in event }.sorted { $1 < $0 }

if let date = expandedEvents.popLast() {
occurrenceNumber += 1
Expand Down
8 changes: 4 additions & 4 deletions app-ios/tutanotaTests/AlarmManagerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ class AlarmManagerTest: XCTestCase {
[
ScheduledAlarmInfo(
alarmTime: start2.advanced(by: 24, .hours).advanced(by: -10, .minutes),
occurrence: 1,
identifier: ocurrenceIdentifier(alarmIdentifier: alarm2.identifier, occurrence: 1),
occurrence: 2,
identifier: ocurrenceIdentifier(alarmIdentifier: alarm2.identifier, occurrence: 2),
summary: alarm2.summary,
eventDate: start2.advanced(by: 24, .hours)
),
ScheduledAlarmInfo(
alarmTime: start2.advanced(by: -10, .minutes),
occurrence: 0,
identifier: ocurrenceIdentifier(alarmIdentifier: alarm2.identifier, occurrence: 0),
occurrence: 1,
identifier: ocurrenceIdentifier(alarmIdentifier: alarm2.identifier, occurrence: 1),
summary: alarm2.summary,
eventDate: start2
),
Expand Down
8 changes: 4 additions & 4 deletions app-ios/tutanotaTests/AlarmModelTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class AlarmModelTest: XCTestCase {
let result = plan(alarms: [alarm])

XCTAssertEqual(result.count, 3)
XCTAssertEqual(result[2].occurrenceNumber, 2)
XCTAssertEqual(result[2].occurrenceNumber, 3)
}

func testWhenRepeatedAlarmStartsBeforeNowOnlyFutureOcurrencesArePlanned() {
Expand All @@ -93,7 +93,7 @@ class AlarmModelTest: XCTestCase {
let result = plan(alarms: [alarm])

XCTAssertEqual(result.count, 2)
XCTAssertEqual(result[1].occurrenceNumber, 2)
XCTAssertEqual(result[1].occurrenceNumber, 3)
}

func testWhenMultipleAlarmsArePresentOnlyTheNewestOccurrencesArePlanned() {
Expand Down Expand Up @@ -169,8 +169,8 @@ class AlarmModelTest: XCTestCase {
let occurrences = prefix(seq: seq, 5).map { $0.eventOccurrenceTime }

let expected = [
date(2025, 2, 2, 11, timeZone), date(2025, 2, 3, 11, timeZone), date(2025, 2, 4, 11, timeZone), date(2025, 2, 10, 11, timeZone),
date(2025, 2, 11, 11, timeZone),
date(2025, 2, 2, 12, timeZone), date(2025, 2, 3, 12, timeZone), date(2025, 2, 4, 12, timeZone), date(2025, 2, 10, 12, timeZone),
date(2025, 2, 11, 12, timeZone),
]
XCTAssertEqual(occurrences, expected)
}
Expand Down
119 changes: 103 additions & 16 deletions tuta-sdk/rust/sdk/src/date/event_facade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::ops::{Add, Sub};
use regex::Regex;
use time::util::weeks_in_year;
use time::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Weekday};
use tokio::time::interval;

use crate::date::DateTime;

Expand Down Expand Up @@ -538,31 +539,52 @@ impl EventFacade {
{
new_dates.push(*date)
} else if frequency == &RepeatPeriod::Weekly && target_week_day.is_some() {
let mut new_date = date.replace_date(
Date::from_iso_week_date(
date.year(),
date.iso_week(),
Weekday::from_short(target_week_day.unwrap().as_str()),
)
.unwrap(),
);
let interval_start = date.replace_date(
Date::from_iso_week_date(date.year(), date.iso_week(), week_start).unwrap(),
);
let parsed_target_week_day =
Weekday::from_short(target_week_day.unwrap().as_str());
let mut interval_start = date.clone();
while interval_start.date().weekday() != week_start {
interval_start = interval_start.sub(Duration::days(1));
}

let mut new_date = interval_start.clone();
while new_date.weekday() != parsed_target_week_day {
new_date = new_date.add(Duration::days(1))
}

/*
if interval_start.assume_utc().unix_timestamp()
< date.assume_utc().unix_timestamp()
{
interval_start = interval_start.add(Duration::weeks(1))
}
*/
let next_event = date.add(Duration::weeks(1)).assume_utc().unix_timestamp();

if new_date.assume_utc().unix_timestamp()
> interval_start
>= interval_start
.add(Duration::weeks(1))
.assume_utc()
.unix_timestamp()
{
continue;
} else if new_date.assume_utc().unix_timestamp()
< interval_start.assume_utc().unix_timestamp()
< date.assume_utc().unix_timestamp()
{
new_date = new_date.add(Duration::weeks(1));
}

if new_date.assume_utc().unix_timestamp() >= next_event {
continue;
} else if week_start != Weekday::Monday // We have WKST
&& new_date.assume_utc().unix_timestamp()
>= interval_start
.add(Duration::weeks(1))
.assume_utc()
.unix_timestamp()
{
continue;
}

if valid_months.is_empty()
|| valid_months.contains(&new_date.month().to_number())
{
Expand Down Expand Up @@ -2221,7 +2243,39 @@ mod tests {
}

#[test]
fn test_flow_weekly_with_by_day_and_wkst() {
fn test_flow_weekly_with_by_day_edge() {
let time = Time::from_hms(13, 23, 00).unwrap();
let date = PrimitiveDateTime::new(
Date::from_calendar_date(2025, Month::February, 2).unwrap(),
time,
);

let repeat_rule = EventRepeatRule {
frequency: RepeatPeriod::Weekly,
by_rules: vec![
ByRule {
by_rule: ByRuleType::ByDay,
interval: "MO".to_string(),
},
ByRule {
by_rule: ByRuleType::ByDay,
interval: "TU".to_string(),
},
],
};

let event_recurrence = EventFacade {};
assert_eq!(
event_recurrence.generate_future_instances(date.to_date_time(), repeat_rule.clone()),
[
date.replace_day(3).unwrap().to_date_time(),
date.replace_day(4).unwrap().to_date_time()
]
);
}

#[test]
fn test_flow_weekly_with_by_day_and_wkst_edge() {
let time = Time::from_hms(13, 23, 00).unwrap();
let date = PrimitiveDateTime::new(
Date::from_calendar_date(2025, Month::February, 10).unwrap(),
Expand All @@ -2246,12 +2300,45 @@ mod tests {
],
};

let event_recurrence = EventFacade {};
assert_eq!(
event_recurrence.generate_future_instances(date.to_date_time(), repeat_rule.clone()),
[date.replace_day(13).unwrap().to_date_time(),]
);
}

#[test]
fn test_flow_weekly_with_by_day_and_wkst() {
let time = Time::from_hms(13, 23, 00).unwrap();
let date = PrimitiveDateTime::new(
Date::from_calendar_date(2025, Month::February, 7).unwrap(),
time,
);

let repeat_rule = EventRepeatRule {
frequency: RepeatPeriod::Weekly,
by_rules: vec![
ByRule {
by_rule: ByRuleType::Wkst,
interval: "FR".to_string(),
},
ByRule {
by_rule: ByRuleType::ByDay,
interval: "TH".to_string(),
},
ByRule {
by_rule: ByRuleType::ByDay,
interval: "FR".to_string(),
},
],
};

let event_recurrence = EventFacade {};
assert_eq!(
event_recurrence.generate_future_instances(date.to_date_time(), repeat_rule.clone()),
[
date.replace_day(14).unwrap().to_date_time(),
date.replace_day(20).unwrap().to_date_time()
date.replace_day(7).unwrap().to_date_time(),
date.replace_day(13).unwrap().to_date_time(),
]
);
}
Expand Down

0 comments on commit 5ca250b

Please sign in to comment.