/// Tests Widget behavior in the FocusFlow Flutter app. library; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:scheduler_core/scheduler_core.dart'; import 'package:focus_flow_flutter/app/demo_scheduler_composition.dart'; import 'package:focus_flow_flutter/app/focus_flow_app.dart'; import 'package:focus_flow_flutter/models/today_screen_models.dart'; import 'package:focus_flow_flutter/widgets/timeline/difficulty_bars.dart'; /// Runs FocusFlow widget and visual adapter tests. void main() { testWidgets('app shell renders compact Today frame', (tester) async { await _pumpPlanApp(tester); expect(find.text('FocusFlow'), findsOneWidget); expect(find.text('Today'), findsWidgets); expect(find.text('Backlog'), findsOneWidget); expect(find.text('Projects'), findsOneWidget); expect(find.text('Reports'), findsOneWidget); expect(find.text('Settings'), findsWidgets); expect(find.text('Compact'), findsOneWidget); expect(find.text('Normal'), findsOneWidget); expect(find.byKey(const ValueKey('nav-today-active')), findsOneWidget); }); testWidgets('seeded Today renders backend-backed compact mockup data', ( tester, ) async { await _pumpPlanApp(tester); expect(find.text('May 20, 2025'), findsOneWidget); expect( find.textContaining('Next required task:', findRichText: true), findsOneWidget, ); expect(find.text('Clean coffee maker'), findsOneWidget); expect(find.text('Cleaned kitchen counter'), findsNWidgets(2)); expect(find.text('Pay bill'), findsOneWidget); expect(find.text('Doctor appointment'), findsOneWidget); expect(find.text('Free Slot'), findsOneWidget); expect(find.text('Intentional rest'), findsOneWidget); }); test( 'visual token adapter maps seeded items to expected visual kinds', () async { final state = await _readSeededToday(); final data = TodayScreenData.fromTodayState(state); expect(_kindFor(data, 'clean-coffee-maker'), TaskVisualKind.flexible); expect(_kindFor(data, 'pay-bill'), TaskVisualKind.required); expect(_kindFor(data, 'doctor-appointment'), TaskVisualKind.appointment); expect(_kindFor(data, 'free-slot'), TaskVisualKind.freeSlot); expect( _kindFor(data, 'cleaned-kitchen-counter-early'), TaskVisualKind.completedSurprise, ); }, ); test('difficulty bars map every difficulty level to five-bar fill count', () { expect(DifficultyBars.fillCountForLevel(DifficultyLevel.notSet), 0); expect(DifficultyBars.fillCountForLevel(DifficultyLevel.veryEasy), 1); expect(DifficultyBars.fillCountForLevel(DifficultyLevel.easy), 2); expect(DifficultyBars.fillCountForLevel(DifficultyLevel.medium), 3); expect(DifficultyBars.fillCountForLevel(DifficultyLevel.hard), 4); expect(DifficultyBars.fillCountForLevel(DifficultyLevel.veryHard), 5); }); testWidgets('task modal opens closes and keeps action buttons inert', ( tester, ) async { await _pumpPlanApp(tester); expect(find.byKey(const ValueKey('task-selection-modal')), findsNothing); await tester.tap(find.byKey(const ValueKey('pay-bill'))); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('task-selection-modal')), findsOneWidget); expect(find.text('Pay bill'), findsNWidgets(2)); expect(find.textContaining('Required'), findsWidgets); expect(find.text('Reward level 2'), findsOneWidget); expect(find.text('Medium effort'), findsOneWidget); expect(find.text('Done'), findsOneWidget); expect(find.text('Push'), findsOneWidget); expect(find.text('Move to Backlog'), findsOneWidget); expect(find.text('Break up'), findsOneWidget); await tester.tap(find.text('Done')); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('task-selection-modal')), findsOneWidget); expect(find.text('Pay bill'), findsNWidgets(2)); await tester.tap(find.byKey(const ValueKey('close-task-modal'))); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('task-selection-modal')), findsNothing); await tester.tap(find.byKey(const ValueKey('pay-bill'))); await tester.pumpAndSettle(); await tester.tapAt(const Offset(1450, 140)); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('task-selection-modal')), findsNothing); expect(find.text('Pay bill'), findsOneWidget); }); } Future _pumpPlanApp(WidgetTester tester) async { await tester.binding.setSurfaceSize(const Size(1586, 992)); addTearDown(() => tester.binding.setSurfaceSize(null)); await tester.pumpWidget(FocusFlowApp(composition: _composition())); await tester.pumpAndSettle(); } DemoSchedulerComposition _composition() { return DemoSchedulerComposition.seeded(selectedDate: CivilDate(2025, 5, 20)); } Future _readSeededToday() async { final composition = _composition(); final result = await composition.todayQuery.execute( GetTodayStateRequest( context: composition.context('test-read-today'), date: composition.date, ), ); return result.requireValue; } TaskVisualKind _kindFor(TodayScreenData data, String id) { return data.cards.singleWhere((card) => card.id == id).visualKind; }