// SPDX-FileCopyrightText: 2026 FocusFlow contributors // SPDX-License-Identifier: AGPL-3.0-only /// Tests app-level settings dialog behavior. 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'; /// Runs app-level settings dialog tests. void main() { testWidgets('sidebar Settings opens a dialog seeded with persisted values', ( tester, ) async { await _pumpPlanApp(tester); await tester.tap(find.byKey(const ValueKey('nav-settings'))); await tester.pumpAndSettle(); expect(find.byType(AlertDialog), findsOneWidget); expect(find.text('UTC'), findsOneWidget); final compactSwitch = tester.widget( find.byKey(const ValueKey('settings-compact-mode')), ); expect(compactSwitch.value, isTrue); await tester.tap(find.text('Cancel')); await tester.pumpAndSettle(); expect(find.byType(AlertDialog), findsNothing); }); testWidgets('top bar Settings button opens the same dialog', (tester) async { await _pumpPlanApp(tester); await tester.tap(find.byKey(const ValueKey('top-bar-settings-button'))); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('settings-timezone')), findsOneWidget); await tester.tap(find.text('Cancel')); await tester.pumpAndSettle(); }); testWidgets('saving settings persists the change and reopens with it', ( tester, ) async { await _pumpPlanApp(tester); await tester.tap(find.byKey(const ValueKey('nav-settings'))); await tester.pumpAndSettle(); await tester.tap(find.byKey(const ValueKey('settings-timezone'))); await tester.pumpAndSettle(); await tester.tap(find.text('EST').last); await tester.pumpAndSettle(); await tester.tap(find.byKey(const ValueKey('settings-save'))); await tester.pumpAndSettle(); expect(find.byType(AlertDialog), findsNothing); await tester.tap(find.byKey(const ValueKey('nav-settings'))); await tester.pumpAndSettle(); expect(find.text('EST'), findsOneWidget); await tester.tap(find.text('Cancel')); await tester.pumpAndSettle(); }); testWidgets('invalid staleness thresholds show a calm inline error', ( tester, ) async { await _pumpPlanApp(tester); await tester.tap(find.byKey(const ValueKey('nav-settings'))); await tester.pumpAndSettle(); await tester.enterText( find.byKey(const ValueKey('settings-aging-days')), '1', ); await tester.pumpAndSettle(); await tester.tap(find.byKey(const ValueKey('settings-save'))); await tester.pumpAndSettle(); expect(find.byType(AlertDialog), findsOneWidget); expect( find.text('Aging must be a number of days at least as large as Fresh.'), findsOneWidget, ); await tester.tap(find.text('Cancel')); await tester.pumpAndSettle(); }); } /// Pumps the FocusFlow app at the desktop test size. 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(); } /// Builds the seeded demo composition used by settings dialog tests. DemoSchedulerComposition _composition() { return DemoSchedulerComposition.seeded(selectedDate: CivilDate(2025, 5, 20)); }