160 lines
5.4 KiB
Dart
160 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:pj_supermarket_cloud/common/index.dart';
|
|
import 'package:pj_supermarket_cloud/pages/terminal/setting/routes/navigation.dart';
|
|
|
|
void main() {
|
|
testWidgets('终端新旧页面重叠时使用不同 Key,并将菜单跳转交给新实例', (tester) async {
|
|
final oldOwner = Object();
|
|
final newOwner = Object();
|
|
final oldRoutes = <String>[];
|
|
final newRoutes = <String>[];
|
|
final oldKey = TerminalNavigationTool.attachNavigator(oldOwner);
|
|
final newKey = TerminalNavigationTool.attachNavigator(newOwner);
|
|
addTearDown(() => TerminalNavigationTool.detachNavigator(newOwner));
|
|
|
|
expect(identical(oldKey, newKey), isFalse);
|
|
await tester.pumpWidget(
|
|
_overlappingNavigators(
|
|
oldKey: oldKey,
|
|
newKey: newKey,
|
|
oldRoutes: oldRoutes,
|
|
newRoutes: newRoutes,
|
|
onOldRouteChanged: (route) =>
|
|
TerminalNavigationTool.handleRouteChanged(oldOwner, route),
|
|
onNewRouteChanged: (route) =>
|
|
TerminalNavigationTool.handleRouteChanged(newOwner, route),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(tester.takeException(), isNull);
|
|
TerminalNavigationTool.detachNavigator(oldOwner);
|
|
TerminalNavigationTool.replaceWorkspace(RouteNames.cashier);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('new:${RouteNames.cashier}'), findsOneWidget);
|
|
expect(find.text('old:/'), findsOneWidget);
|
|
final generatedRouteCount = newRoutes.length;
|
|
TerminalNavigationTool.replaceWorkspace(RouteNames.cashier);
|
|
await tester.pumpAndSettle();
|
|
expect(newRoutes.length, generatedRouteCount);
|
|
});
|
|
|
|
testWidgets('设置新旧内容区重叠时旧实例解绑不会清除新实例导航', (tester) async {
|
|
final oldOwner = Object();
|
|
final newOwner = Object();
|
|
final oldRoutes = <String>[];
|
|
final newRoutes = <String>[];
|
|
final oldKey = SettingNavigation.attachNavigator(oldOwner);
|
|
final newKey = SettingNavigation.attachNavigator(newOwner);
|
|
addTearDown(() => SettingNavigation.detachNavigator(newOwner));
|
|
|
|
expect(identical(oldKey, newKey), isFalse);
|
|
await tester.pumpWidget(
|
|
_overlappingNavigators(
|
|
oldKey: oldKey,
|
|
newKey: newKey,
|
|
oldRoutes: oldRoutes,
|
|
newRoutes: newRoutes,
|
|
onOldRouteChanged: (route) =>
|
|
SettingNavigation.handleRouteChanged(oldOwner, route),
|
|
onNewRouteChanged: (route) =>
|
|
SettingNavigation.handleRouteChanged(newOwner, route),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(tester.takeException(), isNull);
|
|
SettingNavigation.detachNavigator(oldOwner);
|
|
SettingNavigation.openMenu(SettingMenuType.syncSetting);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('new:${RouteNames.settingSync}'), findsOneWidget);
|
|
expect(find.text('old:/'), findsOneWidget);
|
|
final generatedRouteCount = newRoutes.length;
|
|
SettingNavigation.openMenu(SettingMenuType.syncSetting);
|
|
await tester.pumpAndSettle();
|
|
expect(newRoutes.length, generatedRouteCount);
|
|
});
|
|
}
|
|
|
|
/// 构建同时挂载的新旧嵌套 Navigator,复现根路由替换期间的短暂重叠状态。
|
|
Widget _overlappingNavigators({
|
|
required GlobalKey<NavigatorState> oldKey,
|
|
required GlobalKey<NavigatorState> newKey,
|
|
required List<String> oldRoutes,
|
|
required List<String> newRoutes,
|
|
required ValueChanged<String?> onOldRouteChanged,
|
|
required ValueChanged<String?> onNewRouteChanged,
|
|
}) {
|
|
return MaterialApp(
|
|
home: Row(
|
|
children: [
|
|
Expanded(
|
|
child: Navigator(
|
|
key: oldKey,
|
|
observers: [_TestRouteObserver(onOldRouteChanged)],
|
|
onGenerateRoute: (settings) =>
|
|
_testRoute('old', settings, oldRoutes),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Navigator(
|
|
key: newKey,
|
|
observers: [_TestRouteObserver(onNewRouteChanged)],
|
|
onGenerateRoute: (settings) =>
|
|
_testRoute('new', settings, newRoutes),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 创建无动画测试路由,并记录实际生成的路由名称供重复跳转断言使用。
|
|
Route<void> _testRoute(
|
|
String navigatorLabel,
|
|
RouteSettings settings,
|
|
List<String> generatedRoutes,
|
|
) {
|
|
final routeName = settings.name ?? '/';
|
|
generatedRoutes.add(routeName);
|
|
return PageRouteBuilder<void>(
|
|
settings: settings,
|
|
transitionDuration: Duration.zero,
|
|
reverseTransitionDuration: Duration.zero,
|
|
pageBuilder: (_, __, ___) => Center(
|
|
child: Text('$navigatorLabel:$routeName'),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 将测试 Navigator 的真实路由变化回传给对应导航工具。
|
|
class _TestRouteObserver extends NavigatorObserver {
|
|
/// 创建绑定到指定新旧页面实例的测试路由观察器。
|
|
_TestRouteObserver(this.onChanged);
|
|
|
|
/// 路由变化时接收当前页面名称的回调。
|
|
final ValueChanged<String?> onChanged;
|
|
|
|
/// 首个页面和后续页面推入时同步实际路由。
|
|
@override
|
|
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
onChanged(route.settings.name);
|
|
}
|
|
|
|
/// 页面替换时同步新路由。
|
|
@override
|
|
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
|
|
onChanged(newRoute?.settings.name);
|
|
}
|
|
|
|
/// 页面返回时同步恢复后的路由。
|
|
@override
|
|
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
onChanged(previousRoute?.settings.name);
|
|
}
|
|
}
|