diff --git a/lib/widgets/about_zulip.dart b/lib/widgets/about_zulip.dart index fc15c6b63f..57afa6737a 100644 --- a/lib/widgets/about_zulip.dart +++ b/lib/widgets/about_zulip.dart @@ -1,11 +1,13 @@ import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'page.dart'; + class AboutZulipPage extends StatefulWidget { const AboutZulipPage({super.key}); static Route buildRoute(BuildContext context) { - return MaterialPageRoute(builder: (context) => const AboutZulipPage()); + return MaterialWidgetRoute(page: const AboutZulipPage()); } @override diff --git a/lib/widgets/app.dart b/lib/widgets/app.dart index 209fefbd9b..3d054ad0c6 100644 --- a/lib/widgets/app.dart +++ b/lib/widgets/app.dart @@ -4,6 +4,7 @@ import '../model/narrow.dart'; import 'about_zulip.dart'; import 'login.dart'; import 'message_list.dart'; +import 'page.dart'; import 'recent_dm_conversations.dart'; import 'store.dart'; @@ -110,8 +111,8 @@ class HomePage extends StatelessWidget { const HomePage({super.key}); static Route buildRoute({required int accountId}) { - return MaterialPageRoute(builder: (context) => - PerAccountStoreWidget(accountId: accountId, + return MaterialWidgetRoute( + page: PerAccountStoreWidget(accountId: accountId, child: const HomePage())); } diff --git a/lib/widgets/login.dart b/lib/widgets/login.dart index 9af391e9d1..ec140c0474 100644 --- a/lib/widgets/login.dart +++ b/lib/widgets/login.dart @@ -9,11 +9,12 @@ import '../model/store.dart'; import 'app.dart'; import 'dialog.dart'; import 'input.dart'; +import 'page.dart'; import 'store.dart'; -class _LoginSequenceRoute extends MaterialPageRoute { +class _LoginSequenceRoute extends MaterialWidgetRoute { _LoginSequenceRoute({ - required super.builder, + required super.page, }); } @@ -101,8 +102,7 @@ class AddAccountPage extends StatefulWidget { const AddAccountPage({super.key}); static Route buildRoute() { - return _LoginSequenceRoute(builder: (context) => - const AddAccountPage()); + return _LoginSequenceRoute(page: const AddAccountPage()); } @override @@ -231,8 +231,8 @@ class PasswordLoginPage extends StatefulWidget { final GetServerSettingsResult serverSettings; static Route buildRoute({required GetServerSettingsResult serverSettings}) { - return _LoginSequenceRoute(builder: (context) => - PasswordLoginPage(serverSettings: serverSettings)); + return _LoginSequenceRoute( + page: PasswordLoginPage(serverSettings: serverSettings)); } @override diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index 060caff32a..c31bdfe426 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -20,9 +20,8 @@ class MessageListPage extends StatefulWidget { const MessageListPage({super.key, required this.narrow}); static Route buildRoute({required BuildContext context, required Narrow narrow}) { - return MaterialAccountPageRoute(context: context, - settings: RouteSettings(name: 'message_list', arguments: narrow), // for testing - builder: (context) => MessageListPage(narrow: narrow)); + return MaterialAccountWidgetRoute(context: context, + page: MessageListPage(narrow: narrow)); } /// A [ComposeBoxController], if this [MessageListPage] offers a compose box. diff --git a/lib/widgets/page.dart b/lib/widgets/page.dart index 4e2a836498..bd2072fb4a 100644 --- a/lib/widgets/page.dart +++ b/lib/widgets/page.dart @@ -3,6 +3,30 @@ import 'package:flutter/material.dart'; import 'store.dart'; +/// A page route that always builds the same widget. +/// +/// This is useful for making the route more transparent for a test to inspect. +abstract class WidgetRoute extends PageRoute { + /// The widget that this page route always builds. + Widget get page; +} + +/// A [MaterialPageRoute] that always builds the same widget. +/// +/// This is useful for making the route more transparent for a test to inspect. +class MaterialWidgetRoute extends MaterialPageRoute implements WidgetRoute { + MaterialWidgetRoute({ + required this.page, + super.settings, + super.maintainState, + super.fullscreenDialog, + super.allowSnapshotting, + }) : super(builder: (context) => page); + + @override + final Widget page; +} + mixin AccountPageRouteMixin on PageRoute { int get accountId; @@ -28,6 +52,23 @@ class MaterialAccountPageRoute extends MaterialPageRoute with AccountPageR final int accountId; } +/// A [MaterialAccountPageRoute] that always builds the same widget. +/// +/// This is useful for making the route more transparent for a test to inspect. +class MaterialAccountWidgetRoute extends MaterialAccountPageRoute implements WidgetRoute { + MaterialAccountWidgetRoute({ + required super.context, + required this.page, + super.settings, + super.maintainState, + super.fullscreenDialog, + super.allowSnapshotting, + }) : super(builder: (context) => page); + + @override + final Widget page; +} + class AccountPageRouteBuilder extends PageRouteBuilder with AccountPageRouteMixin { AccountPageRouteBuilder({ required BuildContext context, diff --git a/lib/widgets/recent_dm_conversations.dart b/lib/widgets/recent_dm_conversations.dart index 3b38e7f3a2..3b4014c4e4 100644 --- a/lib/widgets/recent_dm_conversations.dart +++ b/lib/widgets/recent_dm_conversations.dart @@ -13,8 +13,8 @@ class RecentDmConversationsPage extends StatefulWidget { const RecentDmConversationsPage({super.key}); static Route buildRoute({required BuildContext context}) { - return MaterialAccountPageRoute(context: context, - builder: (context) => const RecentDmConversationsPage()); + return MaterialAccountWidgetRoute(context: context, + page: const RecentDmConversationsPage()); } @override diff --git a/test/widgets/message_list_checks.dart b/test/widgets/message_list_checks.dart new file mode 100644 index 0000000000..5daa91a1f4 --- /dev/null +++ b/test/widgets/message_list_checks.dart @@ -0,0 +1,7 @@ +import 'package:checks/checks.dart'; +import 'package:zulip/model/narrow.dart'; +import 'package:zulip/widgets/message_list.dart'; + +extension MessageListPageChecks on Subject { + Subject get narrow => has((x) => x.narrow, 'narrow'); +} diff --git a/test/widgets/page_checks.dart b/test/widgets/page_checks.dart new file mode 100644 index 0000000000..26590df8a5 --- /dev/null +++ b/test/widgets/page_checks.dart @@ -0,0 +1,7 @@ +import 'package:checks/checks.dart'; +import 'package:flutter/widgets.dart'; +import 'package:zulip/widgets/page.dart'; + +extension WidgetRouteChecks on Subject { + Subject get page => has((x) => x.page, 'page'); +} diff --git a/test/widgets/recent_dm_conversations_test.dart b/test/widgets/recent_dm_conversations_test.dart index e59b7b4f57..b2b0340961 100644 --- a/test/widgets/recent_dm_conversations_test.dart +++ b/test/widgets/recent_dm_conversations_test.dart @@ -7,15 +7,18 @@ import 'package:zulip/api/model/model.dart'; import 'package:zulip/model/narrow.dart'; import 'package:zulip/widgets/content.dart'; import 'package:zulip/widgets/icons.dart'; +import 'package:zulip/widgets/message_list.dart'; +import 'package:zulip/widgets/page.dart'; import 'package:zulip/widgets/recent_dm_conversations.dart'; import 'package:zulip/widgets/store.dart'; import '../example_data.dart' as eg; -import '../flutter_checks.dart'; import '../model/binding.dart'; import '../model/test_store.dart'; import '../test_navigation.dart'; import 'content_checks.dart'; +import 'message_list_checks.dart'; +import 'page_checks.dart'; Future setupPage(WidgetTester tester, { required List dmMessages, @@ -275,9 +278,9 @@ void main() { await tester.tap(find.byType(RecentDmConversationsItem)); // no `tester.pump`, to avoid having to mock API response for [MessageListPage] - check(pushedRoutes).last.settings - ..name.equals('message_list') - ..arguments.equals(expectedNarrow); + check(pushedRoutes).last.isA().page + .isA() + .narrow.equals(expectedNarrow); } testWidgets('1:1', (WidgetTester tester) async {