@@ -3,6 +3,7 @@ import 'dart:convert';
33import 'dart:io' ;
44
55import 'package:checks/checks.dart' ;
6+ import 'package:collection/collection.dart' ;
67import 'package:crypto/crypto.dart' ;
78import 'package:file_picker/file_picker.dart' ;
89import 'package:flutter_checks/flutter_checks.dart' ;
@@ -56,14 +57,23 @@ void main() {
5657 User ? selfUser,
5758 List <User > otherUsers = const [],
5859 List <ZulipStream > streams = const [],
60+ List <Message >? messages,
5961 bool ? mandatoryTopics,
6062 int ? zulipFeatureLevel,
6163 }) async {
6264 if (narrow case ChannelNarrow (: var streamId) || TopicNarrow (: var streamId)) {
63- assert (streams.any ((stream) => stream.streamId == streamId),
65+ final channel = streams.firstWhereOrNull ((s) => s.streamId == streamId);
66+ assert (channel != null ,
6467 'Add a channel with "streamId" the same as of $narrow .streamId to the store.' );
68+ if (narrow is ChannelNarrow ) {
69+ // By default, bypass the complexity where the topic input is autofocused
70+ // on an empty fetch, by making the fetch not empty. (In particular that
71+ // complexity includes a getStreamTopics fetch for topic autocomplete.)
72+ messages ?? = [eg.streamMessage (stream: channel)];
73+ }
6574 }
6675 addTearDown (testBinding.reset);
76+ messages ?? = [];
6777 selfUser ?? = eg.selfUser;
6878 zulipFeatureLevel ?? = eg.futureZulipFeatureLevel;
6979 final selfAccount = eg.account (user: selfUser, zulipFeatureLevel: zulipFeatureLevel);
@@ -81,7 +91,11 @@ void main() {
8191 connection = store.connection as FakeApiConnection ;
8292
8393 connection.prepare (json:
84- eg.newestGetMessagesResult (foundOldest: true , messages: []).toJson ());
94+ eg.newestGetMessagesResult (foundOldest: true , messages: messages).toJson ());
95+ if (narrow is ChannelNarrow && messages.isEmpty) {
96+ // The topic input will autofocus, triggering a getStreamTopics request.
97+ connection.prepare (json: GetStreamTopicsResult (topics: []).toJson ());
98+ }
8599 await tester.pumpWidget (TestZulipApp (accountId: selfAccount.id,
86100 child: MessageListPage (initNarrow: narrow)));
87101 await tester.pumpAndSettle ();
@@ -134,6 +148,61 @@ void main() {
134148 await tester.pump (Duration .zero);
135149 }
136150
151+ group ('auto focus' , () {
152+ testWidgets ('ChannelNarrow, non-empty fetch' , (tester) async {
153+ final channel = eg.stream ();
154+ await prepareComposeBox (tester,
155+ narrow: ChannelNarrow (channel.streamId),
156+ streams: [channel],
157+ messages: [eg.streamMessage (stream: channel)]);
158+ check (controller).isA <StreamComposeBoxController >()
159+ .topicFocusNode.hasFocus.isFalse ();
160+ });
161+
162+ testWidgets ('ChannelNarrow, empty fetch' , (tester) async {
163+ final channel = eg.stream ();
164+ await prepareComposeBox (tester,
165+ narrow: ChannelNarrow (channel.streamId),
166+ streams: [channel],
167+ messages: []);
168+ check (controller).isA <StreamComposeBoxController >()
169+ .topicFocusNode.hasFocus.isTrue ();
170+ });
171+
172+ testWidgets ('TopicNarrow, non-empty fetch' , (tester) async {
173+ final channel = eg.stream ();
174+ await prepareComposeBox (tester,
175+ narrow: TopicNarrow (channel.streamId, eg.t ('topic' )),
176+ streams: [channel],
177+ messages: [eg.streamMessage (stream: channel, topic: 'topic' )]);
178+ check (controller).isNotNull ().contentFocusNode.hasFocus.isFalse ();
179+ });
180+
181+ testWidgets ('TopicNarrow, empty fetch' , (tester) async {
182+ final channel = eg.stream ();
183+ await prepareComposeBox (tester,
184+ narrow: TopicNarrow (channel.streamId, eg.t ('topic' )),
185+ streams: [channel],
186+ messages: []);
187+ check (controller).isNotNull ().contentFocusNode.hasFocus.isTrue ();
188+ });
189+
190+ testWidgets ('DmNarrow, non-empty fetch' , (tester) async {
191+ final user = eg.user ();
192+ await prepareComposeBox (tester,
193+ narrow: DmNarrow .withUser (user.userId, selfUserId: store.selfUserId),
194+ messages: [eg.dmMessage (from: user, to: [store.selfUser])]);
195+ check (controller).isNotNull ().contentFocusNode.hasFocus.isFalse ();
196+ });
197+
198+ testWidgets ('DmNarrow, empty fetch' , (tester) async {
199+ await prepareComposeBox (tester,
200+ narrow: DmNarrow .withUser (eg.user ().userId, selfUserId: store.selfUserId),
201+ messages: []);
202+ check (controller).isNotNull ().contentFocusNode.hasFocus.isTrue ();
203+ });
204+ });
205+
137206 group ('ComposeBoxTheme' , () {
138207 test ('lerp light to dark, no crash' , () {
139208 final a = ComposeBoxTheme .light;
0 commit comments