test(mobile): verify calendar conversions are cached

Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
Tom Brow
2026-10-18 12:42:24 -07:00
parent 02dbd9fecd
commit 59d12aff71
2 changed files with 35 additions and 1 deletions

View File

@@ -85,10 +85,21 @@ bool isSameDay(int a, int b) {
/// avatars, and sticky headers. Resolve each timestamp only once. Create a new
/// instance on each build so a timezone change cannot leave stale cached days.
class TimelineCalendarDays {
/// Creates a calendar cache using local-time conversion.
TimelineCalendarDays() : _toLocalDate = _localDate;
/// Creates a cache with an observable conversion for regression tests.
@visibleForTesting
TimelineCalendarDays.withConverter(this._toLocalDate);
final DateTime Function(int) _toLocalDate;
final _days = <int, (int, int, int)>{};
static DateTime _localDate(int unixSeconds) =>
DateTime.fromMillisecondsSinceEpoch(unixSeconds * 1000);
(int, int, int) _day(int unixSeconds) => _days.putIfAbsent(unixSeconds, () {
final date = DateTime.fromMillisecondsSinceEpoch(unixSeconds * 1000);
final date = _toLocalDate(unixSeconds);
return (date.year, date.month, date.day);
});

View File

@@ -5,6 +5,29 @@ import 'package:buzz/features/channels/date_formatters.dart';
int _ts(DateTime local) => local.millisecondsSinceEpoch ~/ 1000;
void main() {
test('timeline converts each timestamp only once per cache', () {
final conversions = <int, int>{};
DateTime convert(int timestamp) {
conversions.update(timestamp, (count) => count + 1, ifAbsent: () => 1);
return DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
}
final first = _ts(DateTime(2026, 10, 18, 10));
final second = _ts(DateTime(2026, 10, 18, 11));
final nextDay = _ts(DateTime(2026, 10, 19));
final days = TimelineCalendarDays.withConverter(convert);
for (var repeat = 0; repeat < 3; repeat++) {
expect(days.isSameDay(first, second), isTrue);
expect(days.isSameDay(second, nextDay), isFalse);
expect(days.isSameDay(first, first), isTrue);
}
expect(conversions, {first: 1, second: 1, nextDay: 1});
final nextBuild = TimelineCalendarDays.withConverter(convert);
expect(nextBuild.isSameDay(first, second), isTrue);
expect(conversions, {first: 2, second: 2, nextDay: 1});
});
test('timeline calendar grouping matches uncached local-day comparisons', () {
final days = TimelineCalendarDays();
final timestamps = [