From acee1da2642d0e0e73eaf2cda99612f1736ace8e Mon Sep 17 00:00:00 2001 From: Ashley Venn Date: Tue, 30 Jun 2026 14:17:49 -0700 Subject: [PATCH] fix: seed partial overlap timeline tasks --- .../lib/app/demo_scheduler_composition.dart | 42 ++++++++++++++++++ apps/focus_flow_flutter/test/widget_test.dart | 43 ++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/apps/focus_flow_flutter/lib/app/demo_scheduler_composition.dart b/apps/focus_flow_flutter/lib/app/demo_scheduler_composition.dart index 6bb91ed..8a2df03 100644 --- a/apps/focus_flow_flutter/lib/app/demo_scheduler_composition.dart +++ b/apps/focus_flow_flutter/lib/app/demo_scheduler_composition.dart @@ -229,6 +229,48 @@ class DemoSchedulerComposition { completedAt: _instant(date, 16, 20), createdAt: createdAt, ), + _task( + id: 'sort-mail', + title: 'Sort mail', + type: TaskType.flexible, + status: TaskStatus.planned, + date: date, + startHour: 14, + startMinute: 40, + endHour: 15, + endMinute: 20, + reward: RewardLevel.low, + difficulty: DifficultyLevel.easy, + createdAt: createdAt, + ), + _task( + id: 'start-laundry', + title: 'Start laundry', + type: TaskType.flexible, + status: TaskStatus.planned, + date: date, + startHour: 15, + startMinute: 0, + endHour: 15, + endMinute: 40, + reward: RewardLevel.medium, + difficulty: DifficultyLevel.medium, + createdAt: createdAt, + ), + _task( + id: 'water-plants', + title: 'Water plants', + type: TaskType.flexible, + status: TaskStatus.planned, + date: date, + startHour: 15, + startMinute: 20, + endHour: 16, + endMinute: 0, + reward: RewardLevel.medium, + difficulty: DifficultyLevel.medium, + createdAt: createdAt, + ), _task( id: 'pay-bill', title: 'Pay bill', diff --git a/apps/focus_flow_flutter/test/widget_test.dart b/apps/focus_flow_flutter/test/widget_test.dart index aabd58c..146d61a 100644 --- a/apps/focus_flow_flutter/test/widget_test.dart +++ b/apps/focus_flow_flutter/test/widget_test.dart @@ -44,6 +44,9 @@ void main() { ); expect(find.text('Clean coffee maker'), findsOneWidget); expect(find.text('Cleaned kitchen counter'), findsNWidgets(2)); + expect(find.text('Sort mail'), findsOneWidget); + expect(find.text('Start laundry'), findsOneWidget); + expect(find.text('Water plants'), findsOneWidget); expect(find.text('Pay bill'), findsOneWidget); expect(find.text('Doctor appointment'), findsOneWidget); expect(find.text('Free Slot'), findsOneWidget); @@ -57,6 +60,9 @@ void main() { final data = TodayScreenData.fromTodayState(state); expect(_kindFor(data, 'clean-coffee-maker'), TaskVisualKind.flexible); + expect(_kindFor(data, 'sort-mail'), TaskVisualKind.flexible); + expect(_kindFor(data, 'start-laundry'), TaskVisualKind.flexible); + expect(_kindFor(data, 'water-plants'), TaskVisualKind.flexible); expect(_kindFor(data, 'pay-bill'), TaskVisualKind.required); expect(_kindFor(data, 'doctor-appointment'), TaskVisualKind.appointment); expect(_kindFor(data, 'free-slot'), TaskVisualKind.freeSlot); @@ -159,7 +165,7 @@ void main() { }, ); - testWidgets('timeline reuses empty overlap lanes for chained tasks', ( + testWidgets('timeline splits partial overlaps and reuses empty lanes', ( tester, ) async { await _pumpConstrainedWidget( @@ -210,6 +216,41 @@ void main() { expect(leftReused.right, lessThan(rightMiddle.left)); }); + testWidgets('seeded demo partial overlaps pack into two lanes', ( + tester, + ) async { + final state = await _readSeededToday(); + final data = TodayScreenData.fromTodayState(state); + + await _pumpConstrainedWidget( + tester, + size: const Size(900, 620), + child: TimelineView( + cards: data.cards, + range: data.timelineRange, + now: () => DateTime(2025, 5, 20, 15, 20), + onCardSelected: (_) {}, + ), + ); + + expect(tester.takeException(), isNull); + + final sortMail = tester.getRect(find.byKey(const ValueKey('sort-mail'))); + final startLaundry = tester.getRect( + find.byKey(const ValueKey('start-laundry')), + ); + final waterPlants = tester.getRect( + find.byKey(const ValueKey('water-plants')), + ); + + expect(startLaundry.left, greaterThan(sortMail.left)); + expect(waterPlants.left, closeTo(sortMail.left, 1)); + expect(sortMail.width, closeTo(startLaundry.width, 1)); + expect(waterPlants.width, closeTo(sortMail.width, 1)); + expect(sortMail.right, lessThan(startLaundry.left)); + expect(waterPlants.right, lessThan(startLaundry.left)); + }); + testWidgets('top bar controls scale inside a compact header width', ( tester, ) async {