main
dart 123 lines 3.71 KB
Raw
1 import 'package:flutter/material.dart';
2 import 'package:flutter_riverpod/flutter_riverpod.dart';
3 import 'package:flutter_test/flutter_test.dart';
4 import 'package:go_router/go_router.dart';
5 import 'package:localmind/app.dart';
6 import 'package:localmind/core/routes/app_routes.dart';
7 import 'package:localmind/core/theme/app_theme.dart';
8 import 'package:localmind/features/chat/providers/chat_providers.dart';
9 import 'package:localmind/features/servers/data/models/server.dart';
10 import 'package:localmind/features/servers/providers/server_providers.dart';
11 import 'package:localmind/features/tts/providers/tts_providers.dart';
12 import 'package:localmind/l10n/app_localizations.dart';
13 import 'package:shadcn_ui/shadcn_ui.dart';
14
15 void main() {
16 late GoRouter router;
17
18 setUp(() {
19 router = GoRouter(
20 initialLocation: AppRoutes.home,
21 routes: [
22 ShellRoute(
23 builder: (context, state, child) => AppShell(child: child),
24 routes: [
25 GoRoute(
26 path: AppRoutes.home,
27 builder: (context, state) => const Text('Home'),
28 ),
29 GoRoute(
30 path: AppRoutes.ttsModels,
31 builder: (context, state) => const Text('TTS models'),
32 ),
33 ],
34 ),
35 ],
36 );
37 addTearDown(router.dispose);
38 });
39
40 Future<void> pumpShell(
41 WidgetTester tester, {
42 String location = AppRoutes.home,
43 }) async {
44 tester.view.physicalSize = const Size(400, 800);
45 tester.view.devicePixelRatio = 1;
46 addTearDown(tester.view.resetPhysicalSize);
47 addTearDown(tester.view.resetDevicePixelRatio);
48
49 router.go(location);
50 await tester.pumpWidget(
51 ProviderScope(
52 overrides: [
53 chatProvider.overrideWith(_StubChatNotifier.new),
54 activeServerProvider.overrideWith(_StubActiveServerNotifier.new),
55 serversProvider.overrideWith(_StubServersNotifier.new),
56 ttsProvider.overrideWith(_StubTtsNotifier.new),
57 ],
58 child: ShadTheme(
59 data: AppTheme.lightShadTheme,
60 child: MaterialApp.router(
61 locale: const Locale('en'),
62 localizationsDelegates: AppLocalizations.localizationsDelegates,
63 supportedLocales: AppLocalizations.supportedLocales,
64 routerConfig: router,
65 ),
66 ),
67 ),
68 );
69 await tester.pump();
70 }
71
72 testWidgets('back on empty mobile home opens the drawer without crashing', (
73 tester,
74 ) async {
75 await pumpShell(tester);
76
77 await tester.binding.handlePopRoute();
78 await tester.pump();
79
80 final scaffold = tester.state<ScaffoldState>(find.byType(Scaffold));
81 expect(scaffold.isDrawerOpen, isTrue);
82 expect(tester.takeException(), isNull);
83 });
84
85 testWidgets('back from TTS returns home, then opens the drawer safely', (
86 tester,
87 ) async {
88 await pumpShell(tester, location: AppRoutes.ttsModels);
89 expect(find.text('TTS models'), findsOneWidget);
90
91 await tester.binding.handlePopRoute();
92 await tester.pumpAndSettle();
93 expect(find.text('Home'), findsOneWidget);
94 expect(tester.takeException(), isNull);
95
96 await tester.binding.handlePopRoute();
97 await tester.pump();
98
99 final scaffold = tester.state<ScaffoldState>(find.byType(Scaffold));
100 expect(scaffold.isDrawerOpen, isTrue);
101 expect(tester.takeException(), isNull);
102 });
103 }
104
105 class _StubChatNotifier extends ChatNotifier {
106 @override
107 ChatState build() => const ChatState();
108 }
109
110 class _StubActiveServerNotifier extends ActiveServerNotifier {
111 @override
112 Server? build() => null;
113 }
114
115 class _StubServersNotifier extends ServersNotifier {
116 @override
117 Future<List<Server>> build() async => const [];
118 }
119
120 class _StubTtsNotifier extends TtsNotifier {
121 @override
122 TtsState build() => const TtsState();
123 }