@@ -139,8 +139,8 @@ Future<void> setupToMessageActionSheet(WidgetTester tester, {
139139 // the long-press might land where no child hit-tests as true,
140140 // like if it's in padding around a Paragraph.
141141 await tester.longPress (find.byType (MessageContent ), warnIfMissed: false );
142- // sheet appears onscreen; default duration of bottom-sheet enter animation
143- await tester. pump ( const Duration (milliseconds : 250 ));
142+ await transitionDurationObserver. pumpPastTransition (tester);
143+
144144 // Check the action sheet did in fact open, so we don't defeat any tests that
145145 // use simple `find.byIcon`-style checks to test presence/absence of a button.
146146 check (find.byType (BottomSheet )).findsOne ();
@@ -199,19 +199,22 @@ void main() {
199199 check (find.byType (InboxPageBody )).findsOne ();
200200
201201 await tester.longPress (find.text (someChannel.name).hitTestable ());
202- await tester. pump ( const Duration (milliseconds : 250 ) );
202+ await transitionDurationObserver. pumpPastTransition (tester );
203203 }
204204
205205 Future <void > showFromSubscriptionList (WidgetTester tester) async {
206+ final transitionDurationObserver = TransitionDurationObserver ();
207+
206208 await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
209+ navigatorObservers: [transitionDurationObserver],
207210 child: const HomePage ()));
208211 await tester.pump ();
209212 await tester.tap (find.byIcon (ZulipIcons .hash_italic));
210213 await tester.pump ();
211214 check (find.byType (SubscriptionListPageBody )).findsOne ();
212215
213216 await tester.longPress (find.text (someChannel.name).hitTestable ());
214- await tester. pump ( const Duration (milliseconds : 250 ) );
217+ await transitionDurationObserver. pumpPastTransition (tester );
215218 }
216219
217220 Future <void > showFromMsglistAppBar (WidgetTester tester, {
@@ -220,6 +223,8 @@ void main() {
220223 }) async {
221224 channel ?? = someChannel;
222225
226+ final transitionDurationObserver = TransitionDurationObserver ();
227+
223228 connection.prepare (json: eg.newestGetMessagesResult (
224229 foundOldest: true , messages: []).toJson ());
225230 if (narrow case ChannelNarrow ()) {
@@ -229,31 +234,35 @@ void main() {
229234 }
230235 await tester.pumpWidget (TestZulipApp (
231236 accountId: eg.selfAccount.id,
237+ navigatorObservers: [transitionDurationObserver],
232238 child: MessageListPage (
233239 initNarrow: narrow)));
234240 await tester.pumpAndSettle ();
235241
236242 await tester.longPress (find.descendant (
237243 of: find.byType (ZulipAppBar ),
238244 matching: find.text (channel.name)));
239- await tester. pump ( const Duration (milliseconds : 250 ) );
245+ await transitionDurationObserver. pumpPastTransition (tester );
240246 }
241247
242248 Future <void > showFromRecipientHeader (WidgetTester tester, {
243249 StreamMessage ? message,
244250 }) async {
245251 message ?? = someMessage;
246252
253+ final transitionDurationObserver = TransitionDurationObserver ();
254+
247255 connection.prepare (json: eg.newestGetMessagesResult (
248256 foundOldest: true , messages: [message]).toJson ());
249257 await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id,
258+ navigatorObservers: [transitionDurationObserver],
250259 child: const MessageListPage (initNarrow: CombinedFeedNarrow ())));
251260 await tester.pumpAndSettle ();
252261
253262 await tester.longPress (find.descendant (
254263 of: find.byType (RecipientHeader ),
255264 matching: find.text (message.displayRecipient ?? '' )));
256- await tester. pump ( const Duration (milliseconds : 250 ) );
265+ await transitionDurationObserver. pumpPastTransition (tester );
257266 }
258267
259268 Future <void > showFromTopicListAppBar (WidgetTester tester, {int ? streamId}) async {
@@ -739,7 +748,7 @@ void main() {
739748
740749 await tester.longPress (find.text (topic));
741750 // sheet appears onscreen; default duration of bottom-sheet enter animation
742- await tester. pump ( const Duration (milliseconds : 250 ) );
751+ await transitionDurationObserver. pumpPastTransition (tester );
743752 }
744753
745754 Future <void > showFromAppBar (WidgetTester tester, {
@@ -766,8 +775,7 @@ void main() {
766775 effectiveTopic.displayName ?? eg.defaultRealmEmptyTopicDisplayName));
767776 await tester.longPress (topicRow);
768777 // sheet appears onscreen; default duration of bottom-sheet enter animation
769- await tester.pump (const Duration (milliseconds: 250 ));
770- }
778+ await transitionDurationObserver.pumpPastTransition (tester); }
771779
772780 Future <void > showFromRecipientHeader (WidgetTester tester, {
773781 StreamMessage ? message,
@@ -785,7 +793,7 @@ void main() {
785793 of: find.byType (RecipientHeader ),
786794 matching: find.text (effectiveMessage.topic.displayName! )));
787795 // sheet appears onscreen; default duration of bottom-sheet enter animation
788- await tester. pump ( const Duration (milliseconds : 250 ) );
796+ await transitionDurationObserver. pumpPastTransition (tester );
789797 }
790798
791799 final actionSheetFinder = find.byType (BottomSheet );
@@ -2037,29 +2045,62 @@ void main() {
20372045 check (await Clipboard .getData ('text/plain' )).isNotNull ().text.equals ('Hello world' );
20382046 });
20392047
2040- testWidgets ('can show snackbar on success' , (tester) async {
2041- // Regression test for: https://github.com/zulip/zulip-flutter/issues/732
2042- testBinding.deviceInfoResult = const IosDeviceInfo (systemVersion: '16.0' );
2043-
2048+ testWidgets ('success' , (tester) async {
20442049 final message = eg.streamMessage ();
20452050 await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
20462051
2047- // Make the request take a bit of time to complete…
2048- prepareRawContentResponseSuccess (message: message, rawContent: 'Hello world' ,
2049- delay: const Duration (milliseconds: 500 ));
2052+ prepareRawContentResponseSuccess (message: message, rawContent: 'Hello world' );
20502053 await tapCopyMessageTextButton (tester);
2051- // … and pump a frame to finish the NavigationState.pop animation…
2052- await tester.pump (const Duration (milliseconds: 250 ));
2053- // … before the request finishes. This is the repro condition for #732.
2054- await tester.pump (const Duration (milliseconds: 250 ));
2054+ await tester.pump (Duration .zero);
2055+ check (await Clipboard .getData ('text/plain' )).isNotNull ().text.equals ('Hello world' );
2056+ });
20552057
2056- final snackbar = tester.widget <SnackBar >(find.byType (SnackBar ));
2057- check (snackbar.behavior).equals (SnackBarBehavior .floating);
2058- final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
2059- tester.widget (find.descendant (matchRoot: true ,
2058+ testWidgets ('can show snackbar on success' , (WidgetTester tester) async {
2059+ // Regression test for: https://github.com/zulip/zulip-flutter/issues/732
2060+ final TransitionDurationObserver observer = TransitionDurationObserver ();
2061+ await tester.pumpWidget (
2062+ MaterialApp (
2063+ navigatorObservers: < NavigatorObserver > [observer],
2064+ home: Scaffold (
2065+ body: Builder (
2066+ builder: (context) {
2067+ testBinding.deviceInfoResult = const IosDeviceInfo (systemVersion: '16.0' );
2068+ final message = eg.streamMessage ();
2069+ setupToMessageActionSheet (
2070+ tester,
2071+ message: message,
2072+ narrow: TopicNarrow .ofMessage (message),
2073+ );
2074+ return const SizedBox .shrink ();
2075+ },
2076+ ),
2077+ ),
2078+ ),
2079+ );
2080+ final message = eg.streamMessage ();
2081+ // Make the request take a bit of time to complete
2082+ prepareRawContentResponseSuccess (
2083+ message: message,
2084+ rawContent: 'Hello world' ,
2085+ delay: const Duration (milliseconds: 500 ),
2086+ );
2087+ await tapCopyMessageTextButton (tester);
2088+ await observer.pumpPastTransition (tester); // for the NavigationState.pop animation
2089+ await observer.pumpPastTransition (tester); // for the second animation / repro timing
2090+
2091+ final snackbar = tester.widget <SnackBar >(find.byType (SnackBar ));
2092+ check (snackbar.behavior).equals (SnackBarBehavior .floating);
2093+
2094+ final zulipLocalizations = GlobalLocalizations .zulipLocalizations;
2095+ tester.widget (
2096+ find.descendant (
2097+ matchRoot: true ,
20602098 of: find.byWidget (snackbar.content),
2061- matching: find.text (zulipLocalizations.successMessageTextCopied)));
2062- });
2099+ matching: find.text (zulipLocalizations.successMessageTextCopied),
2100+ ),
2101+ );
2102+ });
2103+
20632104
20642105 testWidgets ('request has an error' , (tester) async {
20652106 final message = eg.streamMessage ();
@@ -2283,8 +2324,7 @@ void main() {
22832324 // See comment in setupToMessageActionSheet about warnIfMissed: false
22842325 await tester.longPress (find.byType (MessageContent ), warnIfMissed: false );
22852326 // sheet appears onscreen; default duration of bottom-sheet enter animation
2286- await tester.pump (const Duration (milliseconds: 250 ));
2287- check (find.byType (BottomSheet )).findsOne ();
2327+ await transitionDurationObserver.pumpPastTransition (tester); check (find.byType (BottomSheet )).findsOne ();
22882328 checkButtonIsPresent (expected);
22892329
22902330 await tester.pump (Duration (milliseconds: 500 )); // flush timers
0 commit comments