From dace495264f478f5e9e10f3c5498221b41311254 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Tue, 23 Jul 2024 16:02:46 +0530 Subject: [PATCH] fix: ui tests --- lib/consts.dart | 6 ++- lib/providers/ui_providers.dart | 4 +- lib/screens/common_widgets/button_navbar.dart | 14 ++++--- lib/screens/dashboard.dart | 19 ++++----- lib/screens/envvar/environment_page.dart | 4 +- lib/screens/envvar/environments_pane.dart | 2 +- lib/screens/history/history_page.dart | 5 +-- lib/screens/history/history_pane.dart | 5 +-- lib/screens/home_page/collection_pane.dart | 4 +- lib/screens/home_page/home_page.dart | 24 +++++++----- lib/screens/mobile/dashboard.dart | 13 ++----- lib/screens/mobile/navbar.dart | 2 +- .../mobile/requests_page/requests_page.dart | 5 +-- lib/screens/settings_page.dart | 2 +- lib/utils/ui_utils.dart | 11 ++++++ lib/widgets/popup_menu_history.dart | 6 +-- lib/widgets/popup_menu_uri.dart | 2 +- test/models/settings_model_test.dart | 10 +++-- test/providers/ui_providers_test.dart | 39 ++++++++++++++++++- 19 files changed, 108 insertions(+), 69 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 5e8790c0..73de67f6 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -71,6 +71,10 @@ final kCodeStyle = TextStyle( fontFamilyFallback: kFontFamilyFallback, ); +final kHomeScaffoldKey = GlobalKey(); +final kEnvScaffoldKey = GlobalKey(); +final kHisScaffoldKey = GlobalKey(); + const kHintOpacity = 0.6; const kForegroundOpacity = 0.05; const kOverlayBackgroundOpacity = 0.5; @@ -82,7 +86,7 @@ const kFormDataButtonLabelTextStyle = TextStyle( fontSize: 12, fontWeight: FontWeight.w600, ); -const kTextStylePopupMenuItem = TextStyle(fontSize: 16); +const kTextStylePopupMenuItem = TextStyle(fontSize: 14); final kButtonSidebarStyle = ElevatedButton.styleFrom(padding: kPh12); diff --git a/lib/providers/ui_providers.dart b/lib/providers/ui_providers.dart index 0478b040..d8076935 100644 --- a/lib/providers/ui_providers.dart +++ b/lib/providers/ui_providers.dart @@ -2,8 +2,8 @@ import 'package:apidash/consts.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -final mobileScaffoldKeyStateProvider = StateProvider>( - (ref) => GlobalKey()); +final mobileScaffoldKeyStateProvider = + StateProvider>((ref) => kHomeScaffoldKey); final leftDrawerStateProvider = StateProvider((ref) => false); final navRailIndexStateProvider = StateProvider((ref) => 0); final selectedIdEditStateProvider = StateProvider((ref) => null); diff --git a/lib/screens/common_widgets/button_navbar.dart b/lib/screens/common_widgets/button_navbar.dart index f18c695c..bce7687f 100644 --- a/lib/screens/common_widgets/button_navbar.dart +++ b/lib/screens/common_widgets/button_navbar.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; +import 'package:apidash/utils/utils.dart'; class NavbarButton extends ConsumerWidget { const NavbarButton({ @@ -25,19 +26,20 @@ class NavbarButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final mobileScaffoldKey = ref.watch(mobileScaffoldKeyStateProvider); + final mobileScaffoldKeyNotifier = + ref.watch(mobileScaffoldKeyStateProvider.notifier); final bool isSelected = railIdx == buttonIdx; final Size size = isCompact ? const Size(56, 32) : const Size(65, 32); var onPress = isSelected ? null : () { if (buttonIdx != null) { - ref.read(navRailIndexStateProvider.notifier).state = buttonIdx!; + final scaffoldKey = getScaffoldKey(buttonIdx!); + ref.watch(navRailIndexStateProvider.notifier).state = buttonIdx!; + mobileScaffoldKeyNotifier.state = scaffoldKey; if ((railIdx > 2 && buttonIdx! <= 2) || - !(ref - .read(mobileScaffoldKeyStateProvider) - .currentState - ?.isDrawerOpen ?? - true)) { + !(mobileScaffoldKey.currentState?.isDrawerOpen ?? true)) { ref.read(leftDrawerStateProvider.notifier).state = false; } } diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index c9b57475..c0f1532f 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -1,4 +1,3 @@ -import 'package:apidash/screens/history/history_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -7,6 +6,7 @@ import 'package:apidash/consts.dart'; import 'common_widgets/common_widgets.dart'; import 'envvar/environment_page.dart'; import 'home_page/home_page.dart'; +import 'history/history_page.dart'; import 'settings_page.dart'; class Dashboard extends ConsumerWidget { @@ -15,7 +15,6 @@ class Dashboard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final railIdx = ref.watch(navRailIndexStateProvider); - final mobileScaffoldKey = ref.watch(mobileScaffoldKeyStateProvider); return Scaffold( body: SafeArea( child: Row( @@ -61,7 +60,7 @@ class Dashboard extends ConsumerWidget { ref.read(navRailIndexStateProvider.notifier).state = 2; }, icon: const Icon(Icons.history_outlined), - selectedIcon: const Icon(Icons.history), + selectedIcon: const Icon(Icons.history_rounded), ), Text( 'History', @@ -113,15 +112,11 @@ class Dashboard extends ConsumerWidget { child: IndexedStack( alignment: AlignmentDirectional.topCenter, index: railIdx, - children: [ - const HomePage(), - EnvironmentPage( - scaffoldKey: mobileScaffoldKey, - ), - HistoryPage( - scaffoldKey: mobileScaffoldKey, - ), - const SettingsPage(), + children: const [ + HomePage(), + EnvironmentPage(), + HistoryPage(), + SettingsPage(), ], ), ) diff --git a/lib/screens/envvar/environment_page.dart b/lib/screens/envvar/environment_page.dart index bbf1dcec..360b4551 100644 --- a/lib/screens/envvar/environment_page.dart +++ b/lib/screens/envvar/environment_page.dart @@ -12,10 +12,8 @@ import 'environment_editor.dart'; class EnvironmentPage extends ConsumerWidget { const EnvironmentPage({ super.key, - required this.scaffoldKey, }); - final GlobalKey scaffoldKey; @override Widget build(BuildContext context, WidgetRef ref) { final id = ref.watch(selectedEnvironmentIdStateProvider); @@ -23,7 +21,7 @@ class EnvironmentPage extends ConsumerWidget { selectedEnvironmentModelProvider.select((value) => value?.name))); if (context.isMediumWindow) { return DrawerSplitView( - scaffoldKey: scaffoldKey, + scaffoldKey: kEnvScaffoldKey, mainContent: const EnvironmentEditor(), title: EditorTitle( title: name, diff --git a/lib/screens/envvar/environments_pane.dart b/lib/screens/envvar/environments_pane.dart index dd6b5af4..34d58e4b 100644 --- a/lib/screens/envvar/environments_pane.dart +++ b/lib/screens/envvar/environments_pane.dart @@ -191,7 +191,7 @@ class EnvironmentItem extends ConsumerWidget { }, onTap: () { ref.read(selectedEnvironmentIdStateProvider.notifier).state = id; - ref.read(mobileScaffoldKeyStateProvider).currentState?.closeDrawer(); + kEnvScaffoldKey.currentState?.closeDrawer(); }, focusNode: ref.watch(nameTextFieldFocusNodeProvider), onChangedNameEditor: (value) { diff --git a/lib/screens/history/history_page.dart b/lib/screens/history/history_page.dart index 0f288fb7..d56c90f7 100644 --- a/lib/screens/history/history_page.dart +++ b/lib/screens/history/history_page.dart @@ -4,16 +4,15 @@ import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/utils/utils.dart'; +import 'package:apidash/consts.dart'; import 'history_pane.dart'; import 'history_viewer.dart'; class HistoryPage extends ConsumerWidget { const HistoryPage({ super.key, - required this.scaffoldKey, }); - final GlobalKey scaffoldKey; @override Widget build(BuildContext context, WidgetRef ref) { final historyModel = ref.watch(selectedHistoryRequestModelProvider); @@ -22,7 +21,7 @@ class HistoryPage extends ConsumerWidget { : 'History'; if (context.isMediumWindow) { return DrawerSplitView( - scaffoldKey: scaffoldKey, + scaffoldKey: kHisScaffoldKey, mainContent: const HistoryViewer(), title: Text(title), leftDrawerContent: const HistoryPane(), diff --git a/lib/screens/history/history_pane.dart b/lib/screens/history/history_pane.dart index ba89c565..d76eac17 100644 --- a/lib/screens/history/history_pane.dart +++ b/lib/screens/history/history_pane.dart @@ -150,10 +150,7 @@ class _HistoryExpansionTileState extends ConsumerState ref .read(historyMetaStateNotifier.notifier) .loadHistoryRequest(item.first.historyId); - ref - .read(mobileScaffoldKeyStateProvider) - .currentState - ?.closeDrawer(); + kHisScaffoldKey.currentState?.closeDrawer(); }, ), ); diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 7c40ef3f..b30eded2 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,7 +1,7 @@ -import 'package:apidash/importer/importer.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; +import 'package:apidash/importer/importer.dart'; import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/models/models.dart'; @@ -221,7 +221,7 @@ class RequestItem extends ConsumerWidget { editRequestId: editRequestId, onTap: () { ref.read(selectedIdStateProvider.notifier).state = id; - ref.read(mobileScaffoldKeyStateProvider).currentState?.closeDrawer(); + kHomeScaffoldKey.currentState?.closeDrawer(); }, // onDoubleTap: () { // ref.read(selectedIdStateProvider.notifier).state = id; diff --git a/lib/screens/home_page/home_page.dart b/lib/screens/home_page/home_page.dart index a7338a08..76509a08 100644 --- a/lib/screens/home_page/home_page.dart +++ b/lib/screens/home_page/home_page.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:apidash/widgets/widgets.dart'; +import 'package:apidash/extensions/extensions.dart'; +import '../mobile/requests_page/requests_page.dart'; import 'editor_pane/editor_pane.dart'; import 'collection_pane.dart'; @@ -8,15 +10,17 @@ class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Column( - children: [ - Expanded( - child: DashboardSplitView( - sidebarWidget: CollectionPane(), - mainWidget: RequestEditorPane(), - ), - ), - ], - ); + return context.isMediumWindow + ? const RequestResponsePage() + : const Column( + children: [ + Expanded( + child: DashboardSplitView( + sidebarWidget: CollectionPane(), + mainWidget: RequestEditorPane(), + ), + ), + ], + ); } } diff --git a/lib/screens/mobile/dashboard.dart b/lib/screens/mobile/dashboard.dart index 8da58375..0cef40ab 100644 --- a/lib/screens/mobile/dashboard.dart +++ b/lib/screens/mobile/dashboard.dart @@ -67,25 +67,18 @@ class PageBranch extends ConsumerWidget { final int pageIndex; @override Widget build(BuildContext context, WidgetRef ref) { - final scaffoldKey = ref.watch(mobileScaffoldKeyStateProvider); switch (pageIndex) { case 1: - return EnvironmentPage( - scaffoldKey: scaffoldKey, - ); + return const EnvironmentPage(); case 2: - return HistoryPage( - scaffoldKey: scaffoldKey, - ); + return const HistoryPage(); case 3: return const PageBase( title: 'Settings', scaffoldBody: SettingsPage(), ); default: - return RequestResponsePage( - scaffoldKey: scaffoldKey, - ); + return const RequestResponsePage(); } } } diff --git a/lib/screens/mobile/navbar.dart b/lib/screens/mobile/navbar.dart index 5449f45f..b5402b88 100644 --- a/lib/screens/mobile/navbar.dart +++ b/lib/screens/mobile/navbar.dart @@ -52,7 +52,7 @@ class BottomNavBar extends ConsumerWidget { child: NavbarButton( railIdx: railIdx, buttonIdx: 2, - selectedIcon: Icons.history, + selectedIcon: Icons.history_rounded, icon: Icons.history_outlined, label: 'History', ), diff --git a/lib/screens/mobile/requests_page/requests_page.dart b/lib/screens/mobile/requests_page/requests_page.dart index 4164356c..fcd291b1 100644 --- a/lib/screens/mobile/requests_page/requests_page.dart +++ b/lib/screens/mobile/requests_page/requests_page.dart @@ -15,11 +15,8 @@ import 'request_response_tabs.dart'; class RequestResponsePage extends StatefulHookConsumerWidget { const RequestResponsePage({ super.key, - required this.scaffoldKey, }); - final GlobalKey scaffoldKey; - @override ConsumerState createState() => _RequestResponsePageState(); @@ -35,7 +32,7 @@ class _RequestResponsePageState extends ConsumerState final TabController requestResponseTabController = useTabController(initialLength: 2, vsync: this); return DrawerSplitView( - scaffoldKey: widget.scaffoldKey, + scaffoldKey: kHomeScaffoldKey, title: EditorTitle( title: name, onSelected: (ItemMenuOption item) { diff --git a/lib/screens/settings_page.dart b/lib/screens/settings_page.dart index da00bfd2..2ce155f2 100644 --- a/lib/screens/settings_page.dart +++ b/lib/screens/settings_page.dart @@ -149,7 +149,7 @@ class SettingsPage extends ConsumerWidget { hoverColor: kColorTransparent, title: const Text('History Retention Period'), subtitle: Text( - 'Your request history will be retained for ${settings.historyRetentionPeriod.label}'), + 'Your request history will be retained${settings.historyRetentionPeriod == HistoryRetentionPeriod.forever ? "" : " for"} ${settings.historyRetentionPeriod.label}'), trailing: Container( decoration: BoxDecoration( border: Border.all( diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index 3bf1fb98..764c821b 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -69,3 +69,14 @@ double? getJsonPreviewerMaxRootNodeWidth(double w) { } return w - 150; } + +GlobalKey getScaffoldKey(int railIdx) { + switch (railIdx) { + case 1: + return kEnvScaffoldKey; + case 2: + return kHisScaffoldKey; + default: + return kHomeScaffoldKey; + } +} diff --git a/lib/widgets/popup_menu_history.dart b/lib/widgets/popup_menu_history.dart index 3f2af6ee..72398bb3 100644 --- a/lib/widgets/popup_menu_history.dart +++ b/lib/widgets/popup_menu_history.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:apidash/extensions/extensions.dart'; import 'package:apidash/consts.dart'; class HistoryRetentionPopupMenu extends StatelessWidget { @@ -15,11 +14,11 @@ class HistoryRetentionPopupMenu extends StatelessWidget { final List? items; @override Widget build(BuildContext context) { - final double boxLength = context.isCompactWindow ? 110 : 130; + const double boxLength = 120; return PopupMenuButton( tooltip: "Select retention period", surfaceTintColor: kColorTransparent, - constraints: BoxConstraints(minWidth: boxLength), + constraints: const BoxConstraints(minWidth: boxLength), itemBuilder: (BuildContext context) { return [ ...items!.map((period) { @@ -44,6 +43,7 @@ class HistoryRetentionPopupMenu extends StatelessWidget { Text( value.label, style: kTextStylePopupMenuItem, + overflow: TextOverflow.ellipsis, ), const Icon( Icons.unfold_more, diff --git a/lib/widgets/popup_menu_uri.dart b/lib/widgets/popup_menu_uri.dart index 177381b0..5a62c97e 100644 --- a/lib/widgets/popup_menu_uri.dart +++ b/lib/widgets/popup_menu_uri.dart @@ -15,7 +15,7 @@ class URIPopupMenu extends StatelessWidget { final List? items; @override Widget build(BuildContext context) { - final double boxLength = context.isCompactWindow ? 90 : 130; + final double boxLength = context.isCompactWindow ? 90 : 110; return PopupMenuButton( tooltip: "Select URI Scheme", surfaceTintColor: kColorTransparent, diff --git a/test/models/settings_model_test.dart b/test/models/settings_model_test.dart index 41fea3b3..6df01335 100644 --- a/test/models/settings_model_test.dart +++ b/test/models/settings_model_test.dart @@ -14,6 +14,7 @@ void main() { saveResponses: true, promptBeforeClosing: true, activeEnvironmentId: null, + historyRetentionPeriod: HistoryRetentionPeriod.oneWeek, ); test('Testing toJson()', () { @@ -28,7 +29,8 @@ void main() { "defaultCodeGenLang": "curl", "saveResponses": true, "promptBeforeClosing": true, - 'activeEnvironmentId': null + "activeEnvironmentId": null, + "historyRetentionPeriod": "oneWeek", }; expect(sm.toJson(), expectedResult); }); @@ -45,7 +47,8 @@ void main() { "defaultCodeGenLang": "curl", "saveResponses": true, "promptBeforeClosing": true, - 'activeEnvironmentId': null + "activeEnvironmentId": null, + "historyRetentionPeriod": "oneWeek", }; expect(SettingsModel.fromJson(input), sm); }); @@ -61,6 +64,7 @@ void main() { saveResponses: false, promptBeforeClosing: true, activeEnvironmentId: null, + historyRetentionPeriod: HistoryRetentionPeriod.oneWeek, ); expect( sm.copyWith( @@ -72,7 +76,7 @@ void main() { test('Testing toString()', () { const expectedResult = - "{isDark: false, alwaysShowCollectionPaneScrollbar: true, width: 300.0, height: 200.0, dx: 100.0, dy: 150.0, defaultUriScheme: http, defaultCodeGenLang: curl, saveResponses: true, promptBeforeClosing: true, activeEnvironmentId: null}"; + "{isDark: false, alwaysShowCollectionPaneScrollbar: true, width: 300.0, height: 200.0, dx: 100.0, dy: 150.0, defaultUriScheme: http, defaultCodeGenLang: curl, saveResponses: true, promptBeforeClosing: true, activeEnvironmentId: null, historyRetentionPeriod: oneWeek}"; expect(sm.toString(), expectedResult); }); diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 81fb7656..9b0653d3 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -12,6 +12,7 @@ import 'package:apidash/screens/home_page/editor_pane/editor_pane.dart'; import 'package:apidash/screens/home_page/editor_pane/url_card.dart'; import 'package:apidash/screens/home_page/home_page.dart'; import 'package:apidash/screens/settings_page.dart'; +import 'package:apidash/screens/history/history_page.dart'; import 'package:apidash/services/hive_services.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:extended_text_field/extended_text_field.dart'; @@ -59,6 +60,7 @@ void main() { // Verify that the HomePage is displayed initially expect(find.byType(HomePage), findsOneWidget); expect(find.byType(EnvironmentPage), findsNothing); + expect(find.byType(HistoryPage), findsNothing); expect(find.byType(SettingsPage), findsNothing); }); @@ -79,9 +81,32 @@ void main() { // Verify that the EnvironmentPage is displayed expect(find.byType(HomePage), findsNothing); expect(find.byType(EnvironmentPage), findsOneWidget); + expect(find.byType(HistoryPage), findsNothing); expect(find.byType(SettingsPage), findsNothing); }); + testWidgets( + "Dashboard should display HistorPage when navRailIndexStateProvider is 2", + (WidgetTester tester) async { + await tester.pumpWidget( + ProviderScope( + overrides: [ + navRailIndexStateProvider.overrideWith((ref) => 2), + ], + child: const Portal( + child: MaterialApp( + home: Dashboard(), + ), + ), + ), + ); + + // Verify that the SettingsPage is displayed + expect(find.byType(HomePage), findsNothing); + expect(find.byType(EnvironmentPage), findsNothing); + expect(find.byType(HistoryPage), findsOneWidget); + expect(find.byType(SettingsPage), findsNothing); + }); testWidgets( "Dashboard should display SettingsPage when navRailIndexStateProvider is 3", (WidgetTester tester) async { @@ -101,6 +126,7 @@ void main() { // Verify that the SettingsPage is displayed expect(find.byType(HomePage), findsNothing); expect(find.byType(EnvironmentPage), findsNothing); + expect(find.byType(HistoryPage), findsNothing); expect(find.byType(SettingsPage), findsOneWidget); }); @@ -159,7 +185,7 @@ void main() { // Verify that the navRailIndexStateProvider still has the updated value final dashboard = tester.element(find.byType(Dashboard)); final container = ProviderScope.containerOf(dashboard); - expect(container.read(navRailIndexStateProvider), 2); + expect(container.read(navRailIndexStateProvider), 3); // Verify that the SettingsPage is still displayed after the rebuild expect(find.byType(SettingsPage), findsOneWidget); @@ -193,10 +219,19 @@ void main() { // Verify that the selected icon is the filled version (selectedIcon) expect(find.byIcon(Icons.computer_rounded), findsOneWidget); - // Go to SettingsPage + // Go to HistoryPage container.read(navRailIndexStateProvider.notifier).state = 2; await tester.pump(); + // Verify that the HistoryPage is displayed + expect(find.byType(HistoryPage), findsOneWidget); + // Verify that the selected icon is the filled version (selectedIcon) + expect(find.byIcon(Icons.history_rounded), findsOneWidget); + + // Go to SettingsPage + container.read(navRailIndexStateProvider.notifier).state = 3; + await tester.pump(); + // Verify that the SettingsPage is displayed expect(find.byType(SettingsPage), findsOneWidget); // Verify that the selected icon is the filled version (selectedIcon)