mirror of
https://github.com/foss42/apidash.git
synced 2025-06-05 01:46:21 +08:00
fix: ui tests
This commit is contained in:
@ -71,6 +71,10 @@ final kCodeStyle = TextStyle(
|
||||
fontFamilyFallback: kFontFamilyFallback,
|
||||
);
|
||||
|
||||
final kHomeScaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final kEnvScaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final kHisScaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
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);
|
||||
|
||||
|
@ -2,8 +2,8 @@ import 'package:apidash/consts.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
final mobileScaffoldKeyStateProvider = StateProvider<GlobalKey<ScaffoldState>>(
|
||||
(ref) => GlobalKey<ScaffoldState>());
|
||||
final mobileScaffoldKeyStateProvider =
|
||||
StateProvider<GlobalKey<ScaffoldState>>((ref) => kHomeScaffoldKey);
|
||||
final leftDrawerStateProvider = StateProvider<bool>((ref) => false);
|
||||
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
|
||||
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
@ -12,10 +12,8 @@ import 'environment_editor.dart';
|
||||
class EnvironmentPage extends ConsumerWidget {
|
||||
const EnvironmentPage({
|
||||
super.key,
|
||||
required this.scaffoldKey,
|
||||
});
|
||||
|
||||
final GlobalKey<ScaffoldState> 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,
|
||||
|
@ -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) {
|
||||
|
@ -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<ScaffoldState> 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(),
|
||||
|
@ -150,10 +150,7 @@ class _HistoryExpansionTileState extends ConsumerState<HistoryExpansionTile>
|
||||
ref
|
||||
.read(historyMetaStateNotifier.notifier)
|
||||
.loadHistoryRequest(item.first.historyId);
|
||||
ref
|
||||
.read(mobileScaffoldKeyStateProvider)
|
||||
.currentState
|
||||
?.closeDrawer();
|
||||
kHisScaffoldKey.currentState?.closeDrawer();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -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;
|
||||
|
@ -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(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
),
|
||||
|
@ -15,11 +15,8 @@ import 'request_response_tabs.dart';
|
||||
class RequestResponsePage extends StatefulHookConsumerWidget {
|
||||
const RequestResponsePage({
|
||||
super.key,
|
||||
required this.scaffoldKey,
|
||||
});
|
||||
|
||||
final GlobalKey<ScaffoldState> scaffoldKey;
|
||||
|
||||
@override
|
||||
ConsumerState<RequestResponsePage> createState() =>
|
||||
_RequestResponsePageState();
|
||||
@ -35,7 +32,7 @@ class _RequestResponsePageState extends ConsumerState<RequestResponsePage>
|
||||
final TabController requestResponseTabController =
|
||||
useTabController(initialLength: 2, vsync: this);
|
||||
return DrawerSplitView(
|
||||
scaffoldKey: widget.scaffoldKey,
|
||||
scaffoldKey: kHomeScaffoldKey,
|
||||
title: EditorTitle(
|
||||
title: name,
|
||||
onSelected: (ItemMenuOption item) {
|
||||
|
@ -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(
|
||||
|
@ -69,3 +69,14 @@ double? getJsonPreviewerMaxRootNodeWidth(double w) {
|
||||
}
|
||||
return w - 150;
|
||||
}
|
||||
|
||||
GlobalKey<ScaffoldState> getScaffoldKey(int railIdx) {
|
||||
switch (railIdx) {
|
||||
case 1:
|
||||
return kEnvScaffoldKey;
|
||||
case 2:
|
||||
return kHisScaffoldKey;
|
||||
default:
|
||||
return kHomeScaffoldKey;
|
||||
}
|
||||
}
|
||||
|
@ -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<HistoryRetentionPeriod>? 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,
|
||||
|
@ -15,7 +15,7 @@ class URIPopupMenu extends StatelessWidget {
|
||||
final List<String>? 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,
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user