@@ -13,13 +13,15 @@ import 'package:zulip/api/route/messages.dart';
13
13
import 'package:zulip/model/localizations.dart' ;
14
14
import 'package:zulip/model/narrow.dart' ;
15
15
import 'package:zulip/model/store.dart' ;
16
+ import 'package:zulip/model/typing_status.dart' ;
16
17
import 'package:zulip/widgets/compose_box.dart' ;
17
18
18
19
import '../api/fake_api.dart' ;
19
20
import '../example_data.dart' as eg;
20
21
import '../flutter_checks.dart' ;
21
22
import '../model/binding.dart' ;
22
23
import '../model/test_store.dart' ;
24
+ import '../model/typing_status_test.dart' ;
23
25
import '../stdlib_checks.dart' ;
24
26
import 'dialog_checks.dart' ;
25
27
import 'test_app.dart' ;
@@ -155,6 +157,97 @@ void main() {
155
157
});
156
158
});
157
159
160
+ group ('ComposeBox typing notification' , () {
161
+ void checkTypingRequest (TypingOp op, SendableNarrow narrow) =>
162
+ checkSetTypingStatusRequests (connection, [(op, narrow)]);
163
+
164
+ final testCases = [
165
+ const TopicNarrow (123 , 'some topic' ),
166
+ DmNarrow .withUsers ([eg.otherUser.userId], selfUserId: eg.selfUser.userId),
167
+ ];
168
+
169
+ final contentInputFinder = find.byWidgetPredicate (
170
+ (widget) => widget is TextField && widget.controller is ComposeContentController );
171
+ final topicInputFinder = find.byWidgetPredicate (
172
+ (widget) => widget is TextField && widget.controller is ComposeTopicController );
173
+
174
+ for (final narrow in testCases) {
175
+ testWidgets ('smoke $narrow ' , (tester) async {
176
+ await prepareComposeBox (tester, narrow: narrow);
177
+
178
+ connection.prepare (json: {});
179
+ await tester.enterText (contentInputFinder, 'hello world' );
180
+ checkTypingRequest (TypingOp .start, narrow);
181
+
182
+ connection.prepare (json: {});
183
+ tester.pumpAndSettle (store.typingNotifier.typingStoppedWaitPeriod);
184
+ checkTypingRequest (TypingOp .stop, narrow);
185
+ });
186
+
187
+ testWidgets ('$narrow : clearing text' , (tester) async {
188
+ await prepareComposeBox (tester, narrow: narrow);
189
+
190
+ connection.prepare (json: {});
191
+ await tester.enterText (contentInputFinder, 'hello world' );
192
+ checkTypingRequest (TypingOp .start, narrow);
193
+
194
+ connection.prepare (json: {});
195
+ await tester.enterText (contentInputFinder, '' );
196
+ checkTypingRequest (TypingOp .stop, narrow);
197
+ });
198
+
199
+ testWidgets ('$narrow : unfocusing content input stops previous typing notification' , (tester) async {
200
+ // TODO
201
+ // await prepareComposeBox(tester, narrow: narrow);
202
+
203
+ // connection.prepare(json: {});
204
+ // await tester.enterText(contentInputFinder, 'hello world');
205
+ // checkTypingRequest(TypingOp.start, narrow);
206
+
207
+ // connection.prepare(json: {});
208
+ // await tester.press(find.widgetWithIcon(IconButton, Icons.attach_file));
209
+ // await tester.pump();
210
+ // checkTypingRequest(TypingOp.stop, narrow);
211
+ });
212
+ }
213
+
214
+ testWidgets ('smoke ChannelNarrow' , (tester) async {
215
+ const narrow = ChannelNarrow (123 );
216
+ await prepareComposeBox (tester, narrow: narrow);
217
+
218
+ await tester.enterText (topicInputFinder, 'test topic' );
219
+ // Clean an irrelevant topic request.
220
+ check (connection.takePreviousRequests ()).single
221
+ ..method.equals ('GET' )
222
+ ..url.path.equals ('/api/v1/users/me/123/topics' );
223
+
224
+ connection.prepare (json: {});
225
+ final typingNarrow = TopicNarrow (narrow.streamId, 'test topic' );
226
+ await tester.enterText (contentInputFinder, 'hello world' );
227
+ checkTypingRequest (TypingOp .start, typingNarrow);
228
+
229
+ connection.prepare (json: {});
230
+ tester.pumpAndSettle (store.typingNotifier.typingStoppedWaitPeriod);
231
+ checkTypingRequest (TypingOp .stop, typingNarrow);
232
+ });
233
+
234
+ testWidgets ('unfocusing content input stops previous typing notification' , (tester) async {
235
+ // TODO
236
+ // const narrow = ChannelNarrow(123);
237
+ // await prepareComposeBox(tester, narrow: narrow);
238
+
239
+ // await tester.enterText(topicInputFinder, 'topic');
240
+ // // Clean an irrelevant topic request.
241
+ // check(connection.takePreviousRequests()).single
242
+ // ..method.equals('GET')
243
+ // ..url.path.equals('/api/v1/users/me/123/topics');
244
+
245
+ // connection.prepare(json: {});
246
+ // await tester.enterText(contentInputFinder, 'hello world');
247
+ // checkTypingRequest(TypingOp.start, TopicNarrow(narrow.streamId, 'topic'));
248
+ });
249
+ });
250
+
158
251
group ('ComposeBox textCapitalization' , () {
159
252
void checkComposeBoxTextFields (WidgetTester tester, {
160
253
required GlobalKey <ComposeBoxController > controllerKey,
@@ -198,6 +291,9 @@ void main() {
198
291
Future <void > setupAndTapSend (WidgetTester tester, {
199
292
required void Function (int messageId) prepareResponse,
200
293
}) async {
294
+ DebugTypingNotifier .debugEnable = false ;
295
+ addTearDown (DebugTypingNotifier .debugReset);
296
+
201
297
final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
202
298
await prepareComposeBox (tester, narrow: const TopicNarrow (123 , 'some topic' ));
203
299
@@ -263,6 +359,9 @@ void main() {
263
359
264
360
group ('attach from media library' , () {
265
361
testWidgets ('success' , (tester) async {
362
+ DebugTypingNotifier .debugEnable = false ;
363
+ addTearDown (DebugTypingNotifier .debugReset);
364
+
266
365
final controllerKey = await prepareComposeBox (tester, narrow: ChannelNarrow (eg.stream ().streamId));
267
366
final composeBoxController = controllerKey.currentState! ;
268
367
@@ -319,6 +418,9 @@ void main() {
319
418
320
419
group ('attach from camera' , () {
321
420
testWidgets ('success' , (tester) async {
421
+ DebugTypingNotifier .debugEnable = false ;
422
+ addTearDown (DebugTypingNotifier .debugReset);
423
+
322
424
final controllerKey = await prepareComposeBox (tester, narrow: ChannelNarrow (eg.stream ().streamId));
323
425
final composeBoxController = controllerKey.currentState! ;
324
426
0 commit comments