main
dart 129 lines 3.5 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:localmind/core/models/enums.dart';
5 import 'package:localmind/features/chat/providers/chat_reasoning_providers.dart';
6 import 'package:localmind/features/models/components/inline_thinking_selector.dart';
7 import 'package:localmind/features/models/components/thinking_mode_chip.dart';
8 import 'package:localmind/features/models/data/models/model_info.dart';
9 import 'package:localmind/l10n/app_localizations.dart';
10
11 Widget _app(Widget child) {
12 return ProviderScope(
13 child: MaterialApp(
14 localizationsDelegates: AppLocalizations.localizationsDelegates,
15 supportedLocales: AppLocalizations.supportedLocales,
16 home: Scaffold(body: child),
17 ),
18 );
19 }
20
21 ModelInfo _model({
22 required List<String> supportedEfforts,
23 bool mandatory = false,
24 }) {
25 return ModelInfo(
26 id: 'thinking-model',
27 name: 'Thinking model',
28 serverType: ServerType.ollama,
29 serverId: 'ollama',
30 supportsReasoning: true,
31 supportedReasoningEfforts: supportedEfforts,
32 reasoningMandatory: mandatory,
33 );
34 }
35
36 void main() {
37 testWidgets('binary model selector labels its boolean state On', (
38 tester,
39 ) async {
40 await tester.pumpWidget(
41 _app(
42 const InlineThinkingSelector(
43 isDark: false,
44 isSelected: true,
45 supportedEfforts: ['off', 'on'],
46 ),
47 ),
48 );
49
50 expect(find.text('Thinking mode'), findsOneWidget);
51 expect(find.text('Off'), findsOneWidget);
52 expect(find.text('On'), findsOneWidget);
53 expect(find.text('Medium'), findsNothing);
54 });
55
56 testWidgets('mandatory binary selector exposes only On', (tester) async {
57 await tester.pumpWidget(
58 _app(
59 const InlineThinkingSelector(
60 isDark: false,
61 isSelected: true,
62 supportedEfforts: ['on'],
63 reasoningMandatory: true,
64 ),
65 ),
66 );
67
68 expect(find.text('On'), findsOneWidget);
69 expect(find.text('Off'), findsNothing);
70 expect(find.text('Medium'), findsNothing);
71 });
72
73 testWidgets('compact binary chip displays On and toggles to Off', (
74 tester,
75 ) async {
76 await tester.pumpWidget(
77 _app(
78 ThinkingModeChip(
79 model: _model(supportedEfforts: const ['off', 'on']),
80 isDark: false,
81 ),
82 ),
83 );
84
85 expect(find.text('On'), findsOneWidget);
86 expect(find.text('Medium'), findsNothing);
87
88 await tester.tap(find.text('On'));
89 await tester.pump();
90
91 expect(find.text('Off'), findsOneWidget);
92 expect(find.text('On'), findsNothing);
93 });
94
95 testWidgets('mandatory compact binary chip stays On', (tester) async {
96 await tester.pumpWidget(
97 _app(
98 ThinkingModeChip(
99 model: _model(supportedEfforts: const ['on'], mandatory: true),
100 isDark: false,
101 ),
102 ),
103 );
104
105 expect(find.text('On'), findsOneWidget);
106 expect(find.text('Off'), findsNothing);
107 expect(find.text('Medium'), findsNothing);
108 });
109
110 test('mandatory model normalization can represent an On-only capability', () {
111 expect(hasGranularReasoningChoice(const ['on']), isFalse);
112 expect(
113 resolveOllamaThinkValue(
114 enabled: false,
115 effort: ReasoningEffort.medium,
116 allowedOptions: const ['on'],
117 ),
118 isNull,
119 );
120 expect(
121 resolveOllamaThinkValue(
122 enabled: true,
123 effort: ReasoningEffort.medium,
124 allowedOptions: const ['on'],
125 ),
126 isTrue,
127 );
128 });
129 }