Skip to content

Commit 67842c0

Browse files
committed
home test: Add tapButtonAndAwaitTransition
As in the previous commit, this removes some more hard-coding of route-animation durations.
1 parent 22e0502 commit 67842c0

File tree

1 file changed

+50
-35
lines changed

1 file changed

+50
-35
lines changed

test/widgets/home_test.dart

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,22 @@ void main () {
3737
late Route<dynamic>? topRoute;
3838
late Route<dynamic>? previousTopRoute;
3939
late List<Route<dynamic>> pushedRoutes;
40+
late Route<dynamic>? lastPoppedRoute;
4041

4142
final testNavObserver = TestNavigatorObserver()
4243
..onChangedTop = ((current, previous) {
4344
topRoute = current;
4445
previousTopRoute = previous;
4546
})
46-
..onPushed = ((route, prevRoute) => pushedRoutes.add(route));
47+
..onPushed = ((route, prevRoute) => pushedRoutes.add(route))
48+
..onPopped = ((route, prevRoute) => lastPoppedRoute = route);
4749

4850
Future<void> prepare(WidgetTester tester) async {
4951
addTearDown(testBinding.reset);
5052
topRoute = null;
5153
previousTopRoute = null;
5254
pushedRoutes = [];
55+
lastPoppedRoute = null;
5356
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
5457
store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
5558
connection = store.connection as FakeApiConnection;
@@ -168,6 +171,44 @@ void main () {
168171
check(find.byType(BottomSheet)).findsOne();
169172
}
170173

174+
/// Taps the [buttonFinder] button and awaits the bottom sheet's exit.
175+
///
176+
/// Includes a check that the bottom sheet is gone.
177+
/// Also awaits the transition to a new pushed route, if one is pushed.
178+
///
179+
/// [buttonFinder] will be run only in the bottom sheet's subtree;
180+
/// it doesn't need its own `find.descendant` logic.
181+
Future<void> tapButtonAndAwaitTransition(WidgetTester tester, Finder buttonFinder) async {
182+
final topRouteBeforePress = topRoute;
183+
check(topRouteBeforePress).isA<ModalBottomSheetRoute<void>>();
184+
final numPushedRoutesBeforePress = pushedRoutes.length;
185+
await tester.tap(find.descendant(
186+
of: find.byType(BottomSheet),
187+
matching: buttonFinder));
188+
await tester.pump(Duration.zero);
189+
190+
final newPushedRoute = pushedRoutes.skip(numPushedRoutesBeforePress)
191+
.singleOrNull;
192+
193+
final sheetPopDuration = (topRouteBeforePress as ModalBottomSheetRoute<void>)
194+
.reverseTransitionDuration;
195+
// TODO not sure why a 1ms fudge is needed; investigate.
196+
await tester.pump(sheetPopDuration + Duration(milliseconds: 1));
197+
check(find.byType(BottomSheet)).findsNothing();
198+
199+
if (newPushedRoute != null) {
200+
final pushDuration = (newPushedRoute as TransitionRoute).transitionDuration;
201+
if (pushDuration > sheetPopDuration) {
202+
await tester.pump(pushDuration - sheetPopDuration);
203+
}
204+
}
205+
206+
// We dismissed the sheet by popping, not pushing or replacing.
207+
check(topRouteBeforePress as Route<dynamic>?)
208+
..not((it) => it.identicalTo(topRoute))
209+
..identicalTo(lastPoppedRoute);
210+
}
211+
171212
void checkIconSelected(WidgetTester tester, Finder finder) {
172213
final widget = tester.widget(find.descendant(
173214
of: find.byType(BottomSheet),
@@ -190,9 +231,7 @@ void main () {
190231
await tapOpenMenuAndAwait(tester);
191232
checkIconSelected(tester, inboxMenuIconFinder);
192233
checkIconNotSelected(tester, channelsMenuIconFinder);
193-
await tester.tap(find.text('Cancel'));
194-
await tester.pump(Duration.zero); // tap the button
195-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
234+
await tapButtonAndAwaitTransition(tester, find.text('Cancel'));
196235

197236
await tester.tap(find.byIcon(ZulipIcons.hash_italic));
198237
await tester.pump();
@@ -211,12 +250,7 @@ void main () {
211250
check(find.byType(InboxPageBody)).findsOne();
212251
check(find.byType(SubscriptionListPageBody)).findsNothing();
213252

214-
await tester.tap(find.descendant(
215-
of: find.byType(BottomSheet),
216-
matching: channelsMenuIconFinder));
217-
await tester.pump(Duration.zero); // tap the button
218-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
219-
check(find.byType(BottomSheet)).findsNothing();
253+
await tapButtonAndAwaitTransition(tester, channelsMenuIconFinder);
220254
check(find.byType(InboxPageBody)).findsNothing();
221255
check(find.byType(SubscriptionListPageBody)).findsOne();
222256

@@ -228,30 +262,21 @@ void main () {
228262
testWidgets('navigation bar menu buttons dismiss the menu', (tester) async {
229263
await prepare(tester);
230264
await tapOpenMenuAndAwait(tester);
231-
232-
await tester.tap(find.descendant(
233-
of: find.byType(BottomSheet),
234-
matching: channelsMenuIconFinder));
235-
await tester.pump(Duration.zero); // tap the button
236-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
237-
check(find.byType(BottomSheet)).findsNothing();
265+
await tapButtonAndAwaitTransition(tester, channelsMenuIconFinder);
238266
});
239267

240268
testWidgets('cancel button dismisses the menu', (tester) async {
241269
await prepare(tester);
242270
await tapOpenMenuAndAwait(tester);
243-
244-
await tester.tap(find.text('Cancel'));
245-
await tester.pump(Duration.zero); // tap the button
246-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
247-
check(find.byType(BottomSheet)).findsNothing();
271+
await tapButtonAndAwaitTransition(tester, find.text('Cancel'));
248272
});
249273

250274
testWidgets('menu buttons dismiss the menu', (tester) async {
251275
addTearDown(testBinding.reset);
252276
topRoute = null;
253277
previousTopRoute = null;
254278
pushedRoutes = [];
279+
lastPoppedRoute = null;
255280
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
256281

257282
await tester.pumpWidget(ZulipApp(navigatorObservers: [testNavObserver]));
@@ -263,11 +288,7 @@ void main () {
263288

264289
connection.prepare(json: eg.newestGetMessagesResult(
265290
foundOldest: true, messages: [eg.streamMessage()]).toJson());
266-
await tester.tap(find.descendant(
267-
of: find.byType(BottomSheet),
268-
matching: combinedFeedMenuIconFinder));
269-
await tester.pump(Duration.zero); // tap the button
270-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
291+
await tapButtonAndAwaitTransition(tester, combinedFeedMenuIconFinder);
271292

272293
// When we go back to the home page, the menu sheet should be gone.
273294
(await ZulipApp.navigator).pop();
@@ -278,21 +299,15 @@ void main () {
278299
testWidgets('_MyProfileButton', (tester) async {
279300
await prepare(tester);
280301
await tapOpenMenuAndAwait(tester);
281-
282-
await tester.tap(find.text('My profile'));
283-
await tester.pump(Duration.zero); // tap the button
284-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
302+
await tapButtonAndAwaitTransition(tester, find.text('My profile'));
285303
check(find.byType(ProfilePage)).findsOne();
286304
check(find.text(eg.selfUser.fullName)).findsAny();
287305
});
288306

289307
testWidgets('_AboutZulipButton', (tester) async {
290308
await prepare(tester);
291309
await tapOpenMenuAndAwait(tester);
292-
293-
await tester.tap(find.byIcon(ZulipIcons.info));
294-
await tester.pump(Duration.zero); // tap the button
295-
await tester.pump(const Duration(milliseconds: 250)); // wait for animation
310+
await tapButtonAndAwaitTransition(tester, find.byIcon(ZulipIcons.info));
296311
check(find.byType(AboutZulipPage)).findsOne();
297312
});
298313
});

0 commit comments

Comments
 (0)