Skip to content

Commit 33701f7

Browse files
committed
chore: add tests
1 parent 1dc75a0 commit 33701f7

File tree

1 file changed

+287
-1
lines changed

1 file changed

+287
-1
lines changed

packages/stream_chat_flutter/test/src/poll/creator/poll_option_reorderable_list_view_test.dart

Lines changed: 287 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// ignore_for_file: lines_longer_than_80_chars
1+
// ignore_for_file: lines_longer_than_80_chars, avoid_redundant_argument_values
22

33
import 'package:alchemist/alchemist.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:flutter_test/flutter_test.dart';
56
import 'package:stream_chat_flutter/src/poll/creator/poll_option_reorderable_list_view.dart';
67
import 'package:stream_chat_flutter/src/theme/stream_chat_theme.dart';
78

@@ -45,6 +46,291 @@ void main() {
4546
),
4647
);
4748
}
49+
50+
group('Options Range Functionality', () {
51+
testWidgets('should enforce minimum options requirement', (tester) async {
52+
var optionsChanged = <PollOptionItem>[];
53+
54+
await tester.pumpWidget(_wrapWithMaterialApp(
55+
PollOptionReorderableListView(
56+
optionsRange: (min: 3, max: null),
57+
initialOptions: [
58+
PollOptionItem(text: 'Option 1'),
59+
],
60+
onOptionsChanged: (options) => optionsChanged = options,
61+
),
62+
));
63+
64+
// Should automatically add options to meet minimum requirement
65+
final textFields = find.byType(TextField);
66+
// Should have 3 options (1 + 2 auto-added)
67+
expect(textFields, findsNWidgets(3));
68+
69+
// Verify callback was called with the minimum options
70+
expect(optionsChanged.length, 3);
71+
});
72+
73+
testWidgets('should respect maximum options limit', (tester) async {
74+
await tester.pumpWidget(_wrapWithMaterialApp(
75+
PollOptionReorderableListView(
76+
optionsRange: (min: null, max: 3),
77+
initialOptions: [
78+
PollOptionItem(text: 'Option 1'),
79+
PollOptionItem(text: 'Option 2'),
80+
PollOptionItem(text: 'Option 3'),
81+
],
82+
),
83+
));
84+
85+
// Find the add button
86+
final addButton = find.byType(FilledButton);
87+
expect(addButton, findsOneWidget);
88+
89+
// The button should be disabled since we're at max options
90+
final button = tester.widget<FilledButton>(addButton);
91+
expect(button.onPressed, isNull);
92+
});
93+
94+
testWidgets('should respect both min and max options', (tester) async {
95+
await tester.pumpWidget(_wrapWithMaterialApp(
96+
PollOptionReorderableListView(
97+
optionsRange: (min: 2, max: 4),
98+
initialOptions: [
99+
PollOptionItem(text: 'Option 1'),
100+
PollOptionItem(text: 'Option 2'),
101+
],
102+
),
103+
));
104+
105+
// Should have 2 options initially (meeting minimum)
106+
final textFields = find.byType(TextField);
107+
expect(textFields, findsNWidgets(2));
108+
109+
// Add two more options to reach maximum
110+
final addButton = find.byType(FilledButton);
111+
await tester.tap(addButton);
112+
await tester.pumpAndSettle();
113+
114+
// Fill the newly added option so we can add another
115+
final textFieldsAfterFirst = find.byType(TextField);
116+
await tester.enterText(textFieldsAfterFirst.last, 'Option 3');
117+
await tester.pumpAndSettle();
118+
119+
// Add one more option
120+
await tester.tap(addButton);
121+
await tester.pumpAndSettle();
122+
123+
// Should now have 4 options (max reached)
124+
expect(find.byType(TextField), findsNWidgets(4));
125+
126+
// Add button should now be disabled since we reached max
127+
final button = tester.widget<FilledButton>(addButton);
128+
expect(button.onPressed, isNull);
129+
});
130+
131+
testWidgets(
132+
'should work with unlimited options when max is null',
133+
(tester) async {
134+
await tester.pumpWidget(_wrapWithMaterialApp(
135+
PollOptionReorderableListView(
136+
optionsRange: (min: 2, max: null),
137+
initialOptions: [
138+
PollOptionItem(text: 'Option 1'),
139+
PollOptionItem(text: 'Option 2'),
140+
],
141+
),
142+
));
143+
144+
// Add button should be enabled for unlimited options
145+
final addButton = find.byType(FilledButton);
146+
final button = tester.widget<FilledButton>(addButton);
147+
expect(button.onPressed, isNotNull);
148+
},
149+
);
150+
});
151+
152+
group('Auto-Focus Functionality', () {
153+
testWidgets('should auto-focus on newly added option', (tester) async {
154+
await tester.pumpWidget(_wrapWithMaterialApp(
155+
PollOptionReorderableListView(
156+
optionsRange: (min: 1, max: null),
157+
initialOptions: [
158+
PollOptionItem(text: 'Option 1'),
159+
],
160+
),
161+
));
162+
163+
// Find the add button and tap it
164+
final addButton = find.byType(FilledButton);
165+
await tester.tap(addButton);
166+
await tester.pumpAndSettle();
167+
168+
// Verify that there are now 2 text fields
169+
final textFields = find.byType(TextField);
170+
expect(textFields, findsNWidgets(2));
171+
172+
// The newly added text field should have focus
173+
// Note: In tests, we can verify the structure but actual focus behavior
174+
// depends on the platform and test environment
175+
expect(textFields, findsNWidgets(2));
176+
});
177+
});
178+
179+
group('Empty Options Prevention', () {
180+
testWidgets(
181+
'should disable add button when empty option exists',
182+
(tester) async {
183+
await tester.pumpWidget(_wrapWithMaterialApp(
184+
PollOptionReorderableListView(
185+
optionsRange: (min: null, max: 5),
186+
initialOptions: [
187+
PollOptionItem(text: 'Option 1'),
188+
PollOptionItem(text: 'Option 2'),
189+
PollOptionItem(text: ''), // Empty option
190+
],
191+
),
192+
));
193+
194+
// Find the add button
195+
final addButton = find.byType(FilledButton);
196+
expect(addButton, findsOneWidget);
197+
198+
// The button should be disabled since there's already an empty option
199+
final button = tester.widget<FilledButton>(addButton);
200+
expect(button.onPressed, isNull);
201+
},
202+
);
203+
204+
testWidgets(
205+
'should enable add button when no empty options exist',
206+
(tester) async {
207+
await tester.pumpWidget(_wrapWithMaterialApp(
208+
PollOptionReorderableListView(
209+
optionsRange: (min: null, max: 5),
210+
initialOptions: [
211+
PollOptionItem(text: 'Option 1'),
212+
PollOptionItem(text: 'Option 2'),
213+
],
214+
),
215+
));
216+
217+
// Find the add button
218+
final addButton = find.byType(FilledButton);
219+
expect(addButton, findsOneWidget);
220+
221+
// The button should be enabled since no empty options exist
222+
final button = tester.widget<FilledButton>(addButton);
223+
expect(button.onPressed, isNotNull);
224+
},
225+
);
226+
227+
testWidgets(
228+
'should re-enable add button after filling empty option',
229+
(tester) async {
230+
await tester.pumpWidget(_wrapWithMaterialApp(
231+
PollOptionReorderableListView(
232+
optionsRange: (min: null, max: 5),
233+
initialOptions: [
234+
PollOptionItem(text: 'Option 1'),
235+
PollOptionItem(text: ''), // Empty option
236+
],
237+
),
238+
));
239+
240+
// Initially, add button should be disabled
241+
var addButton = find.byType(FilledButton);
242+
var button = tester.widget<FilledButton>(addButton);
243+
expect(button.onPressed, isNull);
244+
245+
// Fill the empty option
246+
final textFields = find.byType(TextField);
247+
await tester.enterText(textFields.last, 'Option 2');
248+
await tester.pumpAndSettle();
249+
250+
// Now add button should be enabled
251+
addButton = find.byType(FilledButton);
252+
button = tester.widget<FilledButton>(addButton);
253+
expect(button.onPressed, isNotNull);
254+
},
255+
);
256+
});
257+
258+
group('Options Management', () {
259+
testWidgets(
260+
'should allow adding options when under limits',
261+
(tester) async {
262+
var optionsChanged = <PollOptionItem>[];
263+
264+
await tester.pumpWidget(_wrapWithMaterialApp(
265+
PollOptionReorderableListView(
266+
optionsRange: (min: 2, max: 5),
267+
initialOptions: [
268+
PollOptionItem(text: 'Option 1'),
269+
PollOptionItem(text: 'Option 2'),
270+
],
271+
onOptionsChanged: (options) => optionsChanged = options,
272+
),
273+
));
274+
275+
// Find the add button and tap it
276+
final addButton = find.byType(FilledButton);
277+
await tester.tap(addButton);
278+
await tester.pumpAndSettle();
279+
280+
// Verify a new option was added
281+
expect(optionsChanged.length, equals(3));
282+
},
283+
);
284+
});
285+
286+
group('Edge Cases', () {
287+
testWidgets(
288+
'should handle empty initial options with minimum requirement',
289+
(tester) async {
290+
var optionsChanged = <PollOptionItem>[];
291+
292+
await tester.pumpWidget(_wrapWithMaterialApp(
293+
PollOptionReorderableListView(
294+
optionsRange: (min: 2, max: null),
295+
initialOptions: const [], // No initial options
296+
onOptionsChanged: (options) => optionsChanged = options,
297+
),
298+
));
299+
300+
// Should auto-add options to meet minimum requirement
301+
final textFields = find.byType(TextField);
302+
expect(textFields, findsNWidgets(2));
303+
expect(optionsChanged.length, 2);
304+
},
305+
);
306+
307+
testWidgets('should handle updating initial options', (tester) async {
308+
await tester.pumpWidget(_wrapWithMaterialApp(
309+
PollOptionReorderableListView(
310+
initialOptions: [
311+
PollOptionItem(text: 'Option 1'),
312+
],
313+
),
314+
));
315+
316+
// Initially should have 1 option
317+
expect(find.byType(TextField), findsNWidgets(1));
318+
319+
// Update with new options
320+
await tester.pumpWidget(_wrapWithMaterialApp(
321+
PollOptionReorderableListView(
322+
initialOptions: [
323+
PollOptionItem(text: 'Option 1'),
324+
PollOptionItem(text: 'Option 2'),
325+
PollOptionItem(text: 'Option 3'),
326+
],
327+
),
328+
));
329+
330+
// Should now have 3 options
331+
expect(find.byType(TextField), findsNWidgets(3));
332+
});
333+
});
48334
}
49335

50336
Widget _wrapWithMaterialApp(

0 commit comments

Comments
 (0)