Jonny Borges
Committed by GitHub

Merge pull request #2162 from jonataslaw/navigator-rework

fix all binding types
@@ -7,7 +7,7 @@ export 'get_common/get_reset.dart'; @@ -7,7 +7,7 @@ export 'get_common/get_reset.dart';
7 export 'get_connect/connect.dart'; 7 export 'get_connect/connect.dart';
8 export 'get_core/get_core.dart'; 8 export 'get_core/get_core.dart';
9 export 'get_instance/get_instance.dart'; 9 export 'get_instance/get_instance.dart';
10 -export 'get_navigation/get_navigation.dart' hide FirstWhereOrNullExt; 10 +export 'get_navigation/get_navigation.dart';
11 export 'get_rx/get_rx.dart'; 11 export 'get_rx/get_rx.dart';
12 export 'get_state_manager/get_state_manager.dart'; 12 export 'get_state_manager/get_state_manager.dart';
13 export 'get_utils/get_utils.dart'; 13 export 'get_utils/get_utils.dart';
@@ -511,7 +511,7 @@ extension GetNavigationExt on GetInterface { @@ -511,7 +511,7 @@ extension GetNavigationExt on GetInterface {
511 String? routeName, 511 String? routeName,
512 bool fullscreenDialog = false, 512 bool fullscreenDialog = false,
513 dynamic arguments, 513 dynamic arguments,
514 - List<BindingsInterface>? bindings, 514 + List<BindingsInterface> bindings = const [],
515 bool preventDuplicates = true, 515 bool preventDuplicates = true,
516 bool? popGesture, 516 bool? popGesture,
517 bool showCupertinoParallax = true, 517 bool showCupertinoParallax = true,
@@ -889,7 +889,7 @@ extension GetNavigationExt on GetInterface { @@ -889,7 +889,7 @@ extension GetNavigationExt on GetInterface {
889 int? id, 889 int? id,
890 String? routeName, 890 String? routeName,
891 dynamic arguments, 891 dynamic arguments,
892 - List<BindingsInterface>? bindings, 892 + List<BindingsInterface> bindings = const [],
893 bool fullscreenDialog = false, 893 bool fullscreenDialog = false,
894 bool preventDuplicates = true, 894 bool preventDuplicates = true,
895 Duration? duration, 895 Duration? duration,
@@ -968,7 +968,7 @@ extension GetNavigationExt on GetInterface { @@ -968,7 +968,7 @@ extension GetNavigationExt on GetInterface {
968 int? id, 968 int? id,
969 String? routeName, 969 String? routeName,
970 dynamic arguments, 970 dynamic arguments,
971 - List<BindingsInterface>? bindings, 971 + List<BindingsInterface> bindings = const [],
972 bool fullscreenDialog = false, 972 bool fullscreenDialog = false,
973 Transition? transition, 973 Transition? transition,
974 Curve? curve, 974 Curve? curve,
@@ -4,7 +4,7 @@ import '../../../get.dart'; @@ -4,7 +4,7 @@ import '../../../get.dart';
4 4
5 class GetMaterialController extends FullLifeCycleController { 5 class GetMaterialController extends FullLifeCycleController {
6 static GetMaterialController get to => Get.find(); 6 static GetMaterialController get to => Get.find();
7 - 7 +
8 bool testMode = false; 8 bool testMode = false;
9 Key? unikey; 9 Key? unikey;
10 ThemeData? theme; 10 ThemeData? theme;
@@ -51,7 +51,7 @@ class GetPageRoute<T> extends PageRoute<T> @@ -51,7 +51,7 @@ class GetPageRoute<T> extends PageRoute<T>
51 this.customTransition, 51 this.customTransition,
52 this.barrierDismissible = false, 52 this.barrierDismissible = false,
53 this.barrierColor, 53 this.barrierColor,
54 - this.bindings, 54 + this.bindings = const [],
55 this.binds, 55 this.binds,
56 this.routeName, 56 this.routeName,
57 this.page, 57 this.page,
@@ -73,7 +73,7 @@ class GetPageRoute<T> extends PageRoute<T> @@ -73,7 +73,7 @@ class GetPageRoute<T> extends PageRoute<T>
73 final String? routeName; 73 final String? routeName;
74 //final String reference; 74 //final String reference;
75 final CustomTransition? customTransition; 75 final CustomTransition? customTransition;
76 - final List<BindingsInterface>? bindings; 76 + final List<BindingsInterface> bindings;
77 final Map<String, String>? parameter; 77 final Map<String, String>? parameter;
78 final List<Bind>? binds; 78 final List<Bind>? binds;
79 79
@@ -113,41 +113,33 @@ class GetPageRoute<T> extends PageRoute<T> @@ -113,41 +113,33 @@ class GetPageRoute<T> extends PageRoute<T>
113 if (_child != null) return _child!; 113 if (_child != null) return _child!;
114 final middlewareRunner = MiddlewareRunner(middlewares); 114 final middlewareRunner = MiddlewareRunner(middlewares);
115 115
116 - final localbinds = [  
117 - if (binds != null) ...binds!,  
118 - ];  
119 -  
120 - final localbindings = [  
121 - if (bindings != null) ...bindings!,  
122 - ]; 116 + final localbinds = [if (binds != null) ...binds!];
123 117
124 final bindingsToBind = middlewareRunner 118 final bindingsToBind = middlewareRunner
125 - .runOnBindingsStart(bindings != null ? localbindings : localbinds);  
126 -  
127 - /// Retrocompatibility workaround, remove this when Bindings api  
128 - /// have been removed  
129 - if (bindingsToBind != null &&  
130 - bindingsToBind is! List<Bind> &&  
131 - bindingsToBind is List<BindingsInterface>) {  
132 - for (final binding in bindingsToBind) {  
133 - binding.dependencies();  
134 - }  
135 - } 119 + .runOnBindingsStart(bindings.isNotEmpty ? bindings : localbinds);
136 120
137 final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!; 121 final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;
138 122
139 - if (bindingsToBind != null &&  
140 - bindingsToBind.isNotEmpty &&  
141 - bindingsToBind is List<Bind>) {  
142 - _child = Binds(  
143 - child: middlewareRunner.runOnPageBuilt(pageToBuild()),  
144 - binds: bindingsToBind,  
145 - );  
146 - } else {  
147 - _child = middlewareRunner.runOnPageBuilt(pageToBuild()); 123 + if (bindingsToBind != null && bindingsToBind.isNotEmpty) {
  124 + if (bindingsToBind is List<BindingsInterface>) {
  125 + for (final item in bindingsToBind) {
  126 + final dep = item.dependencies();
  127 + if (dep is List<Bind>) {
  128 + _child = Binds(
  129 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
  130 + binds: dep,
  131 + );
  132 + }
  133 + }
  134 + } else if (bindingsToBind is List<Bind>) {
  135 + _child = Binds(
  136 + child: middlewareRunner.runOnPageBuilt(pageToBuild()),
  137 + binds: bindingsToBind,
  138 + );
  139 + }
148 } 140 }
149 141
150 - return _child!; 142 + return _child ??= middlewareRunner.runOnPageBuilt(pageToBuild());
151 } 143 }
152 144
153 @override 145 @override
@@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart'; @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
2 import 'package:flutter/widgets.dart'; 2 import 'package:flutter/widgets.dart';
3 3
4 import '../../../get.dart'; 4 import '../../../get.dart';
5 -import 'parse_route.dart';  
6 5
7 class GetInformationParser extends RouteInformationParser<RouteDecoder> { 6 class GetInformationParser extends RouteInformationParser<RouteDecoder> {
8 final String initialRoute; 7 final String initialRoute;
@@ -15,7 +15,7 @@ mixin IGetNavigation { @@ -15,7 +15,7 @@ mixin IGetNavigation {
15 String? routeName, 15 String? routeName,
16 bool fullscreenDialog = false, 16 bool fullscreenDialog = false,
17 dynamic arguments, 17 dynamic arguments,
18 - List<BindingsInterface>? bindings, 18 + List<BindingsInterface> bindings = const [],
19 bool preventDuplicates = true, 19 bool preventDuplicates = true,
20 bool? popGesture, 20 bool? popGesture,
21 bool showCupertinoParallax = true, 21 bool showCupertinoParallax = true,
@@ -32,7 +32,7 @@ mixin IGetNavigation { @@ -32,7 +32,7 @@ mixin IGetNavigation {
32 String? routeName, 32 String? routeName,
33 bool fullscreenDialog = false, 33 bool fullscreenDialog = false,
34 dynamic arguments, 34 dynamic arguments,
35 - List<BindingsInterface>? bindings, 35 + List<BindingsInterface> bindings = const [],
36 bool preventDuplicates = true, 36 bool preventDuplicates = true,
37 bool? popGesture, 37 bool? popGesture,
38 bool showCupertinoParallax = true, 38 bool showCupertinoParallax = true,
@@ -47,7 +47,7 @@ mixin IGetNavigation { @@ -47,7 +47,7 @@ mixin IGetNavigation {
47 int? id, 47 int? id,
48 String? routeName, 48 String? routeName,
49 dynamic arguments, 49 dynamic arguments,
50 - List<BindingsInterface>? bindings, 50 + List<BindingsInterface> bindings = const [],
51 bool fullscreenDialog = false, 51 bool fullscreenDialog = false,
52 Transition? transition, 52 Transition? transition,
53 Curve? curve, 53 Curve? curve,
@@ -20,7 +20,7 @@ class GetPage<T> extends Page<T> { @@ -20,7 +20,7 @@ class GetPage<T> extends Page<T> {
20 final bool opaque; 20 final bool opaque;
21 final double Function(BuildContext context)? gestureWidth; 21 final double Function(BuildContext context)? gestureWidth;
22 //final BindingsInterface? binding; 22 //final BindingsInterface? binding;
23 - final List<BindingsInterface>? bindings; 23 + final List<BindingsInterface> bindings;
24 final List<Bind> binds; 24 final List<Bind> binds;
25 final CustomTransition? customTransition; 25 final CustomTransition? customTransition;
26 final Duration? transitionDuration; 26 final Duration? transitionDuration;
@@ -75,17 +75,19 @@ class GetPage<T> extends Page<T> { @@ -75,17 +75,19 @@ class GetPage<T> extends Page<T> {
75 this.preventDuplicateHandlingMode = 75 this.preventDuplicateHandlingMode =
76 PreventDuplicateHandlingMode.ReorderRoutes, 76 PreventDuplicateHandlingMode.ReorderRoutes,
77 this.completer, 77 this.completer,
  78 + LocalKey? key,
78 }) : path = _nameToRegex(name), 79 }) : path = _nameToRegex(name),
79 assert(name.startsWith('/'), 80 assert(name.startsWith('/'),
80 'It is necessary to start route name [$name] with a slash: /$name'), 81 'It is necessary to start route name [$name] with a slash: /$name'),
81 super( 82 super(
82 - key: ValueKey(name), 83 + key: key ?? ValueKey(name),
83 name: name, 84 name: name,
84 // arguments: Get.arguments, 85 // arguments: Get.arguments,
85 ); 86 );
86 // settings = RouteSettings(name: name, arguments: Get.arguments); 87 // settings = RouteSettings(name: name, arguments: Get.arguments);
87 88
88 GetPage<T> copy({ 89 GetPage<T> copy({
  90 + LocalKey? key,
89 String? name, 91 String? name,
90 GetPageBuilder? page, 92 GetPageBuilder? page,
91 bool? popGesture, 93 bool? popGesture,
@@ -114,6 +116,7 @@ class GetPage<T> extends Page<T> { @@ -114,6 +116,7 @@ class GetPage<T> extends Page<T> {
114 Completer<T?>? completer, 116 Completer<T?>? completer,
115 }) { 117 }) {
116 return GetPage( 118 return GetPage(
  119 + key: key ?? this.key,
117 participatesInRootNavigator: 120 participatesInRootNavigator:
118 participatesInRootNavigator ?? this.participatesInRootNavigator, 121 participatesInRootNavigator ?? this.participatesInRootNavigator,
119 preventDuplicates: preventDuplicates ?? this.preventDuplicates, 122 preventDuplicates: preventDuplicates ?? this.preventDuplicates,
@@ -7,6 +7,7 @@ import '../../../get_instance/src/bindings_interface.dart'; @@ -7,6 +7,7 @@ import '../../../get_instance/src/bindings_interface.dart';
7 import '../../../get_state_manager/src/simple/list_notifier.dart'; 7 import '../../../get_state_manager/src/simple/list_notifier.dart';
8 import '../../../get_utils/src/platform/platform.dart'; 8 import '../../../get_utils/src/platform/platform.dart';
9 import '../../../route_manager.dart'; 9 import '../../../route_manager.dart';
  10 +import 'parse_route.dart';
10 11
11 /// Enables the user to customize the intended pop behavior 12 /// Enables the user to customize the intended pop behavior
12 /// 13 ///
@@ -350,7 +351,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -350,7 +351,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
350 String? routeName, 351 String? routeName,
351 bool fullscreenDialog = false, 352 bool fullscreenDialog = false,
352 dynamic arguments, 353 dynamic arguments,
353 - List<BindingsInterface>? bindings, 354 + List<BindingsInterface> bindings = const [],
354 bool preventDuplicates = true, 355 bool preventDuplicates = true,
355 bool? popGesture, 356 bool? popGesture,
356 bool showCupertinoParallax = true, 357 bool showCupertinoParallax = true,
@@ -401,7 +402,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -401,7 +402,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
401 String? routeName, 402 String? routeName,
402 bool fullscreenDialog = false, 403 bool fullscreenDialog = false,
403 dynamic arguments, 404 dynamic arguments,
404 - List<BindingsInterface>? bindings, 405 + List<BindingsInterface> bindings = const [],
405 bool preventDuplicates = true, 406 bool preventDuplicates = true,
406 bool? popGesture, 407 bool? popGesture,
407 bool showCupertinoParallax = true, 408 bool showCupertinoParallax = true,
@@ -435,7 +436,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -435,7 +436,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
435 int? id, 436 int? id,
436 String? routeName, 437 String? routeName,
437 dynamic arguments, 438 dynamic arguments,
438 - List<BindingsInterface>? bindings, 439 + List<BindingsInterface> bindings = const [],
439 bool fullscreenDialog = false, 440 bool fullscreenDialog = false,
440 Transition? transition, 441 Transition? transition,
441 Curve? curve, 442 Curve? curve,
@@ -701,6 +702,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder> @@ -701,6 +702,7 @@ class GetDelegate extends RouterDelegate<RouteDecoder>
701 completer: _activePages.isEmpty ? null : Completer(), 702 completer: _activePages.isEmpty ? null : Completer(),
702 arguments: arguments, 703 arguments: arguments,
703 parameters: parameters, 704 parameters: parameters,
  705 + key: ValueKey(arguments.name),
704 ); 706 );
705 707
706 return decoder; 708 return decoder;
@@ -7,7 +7,6 @@ import 'package:flutter/gestures.dart'; @@ -7,7 +7,6 @@ import 'package:flutter/gestures.dart';
7 import 'package:flutter/material.dart'; 7 import 'package:flutter/material.dart';
8 8
9 import '../../../get.dart'; 9 import '../../../get.dart';
10 -import 'default_transitions.dart';  
11 10
12 const double _kBackGestureWidth = 20.0; 11 const double _kBackGestureWidth = 20.0;
13 const int _kMaxDroppedSwipePageForwardAnimationTime = 12 const int _kMaxDroppedSwipePageForwardAnimationTime =
@@ -11,7 +11,7 @@ export 'get_transition_mixin.dart'; @@ -11,7 +11,7 @@ export 'get_transition_mixin.dart';
11 export 'modules.dart'; 11 export 'modules.dart';
12 export 'observers/route_observer.dart'; 12 export 'observers/route_observer.dart';
13 export 'page_settings.dart'; 13 export 'page_settings.dart';
14 -export 'parse_route.dart'; 14 +export 'parse_route.dart' hide FirstWhereOrNullExt;
15 export 'route_middleware.dart'; 15 export 'route_middleware.dart';
16 export 'route_report.dart'; 16 export 'route_report.dart';
17 export 'router_outlet.dart'; 17 export 'router_outlet.dart';
@@ -79,7 +79,8 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> @@ -79,7 +79,8 @@ class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object>
79 } 79 }
80 } 80 }
81 81
82 -// class _RouterOutletState<TDelegate extends RouterDelegate<T>, T extends Object> 82 +// class _RouterOutletState<TDelegate extends RouterDelegate<T>,
  83 +//T extends Object>
83 // extends State<RouterOutlet<TDelegate, T>> { 84 // extends State<RouterOutlet<TDelegate, T>> {
84 // TDelegate get delegate => context.delegate as TDelegate; 85 // TDelegate get delegate => context.delegate as TDelegate;
85 // @override 86 // @override
@@ -64,6 +64,22 @@ mixin StateMixin<T> on ListNotifier { @@ -64,6 +64,22 @@ mixin StateMixin<T> on ListNotifier {
64 refresh(); 64 refresh();
65 } 65 }
66 66
  67 + @protected
  68 + void change(T newState, {GetStatus<T>? status}) {
  69 + var _canUpdate = false;
  70 + if (status != null) {
  71 + _status = status;
  72 + _canUpdate = true;
  73 + }
  74 + if (newState != _value) {
  75 + _value = newState;
  76 + _canUpdate = true;
  77 + }
  78 + if (_canUpdate) {
  79 + refresh();
  80 + }
  81 + }
  82 +
67 void futurize(Future<T> Function() body(), 83 void futurize(Future<T> Function() body(),
68 {String? errorMessage, bool useEmpty = true}) { 84 {String? errorMessage, bool useEmpty = true}) {
69 final compute = body(); 85 final compute = body();
@@ -89,8 +105,9 @@ class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> { @@ -89,8 +105,9 @@ class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> {
89 105
90 StreamController<T> get subject { 106 StreamController<T> get subject {
91 if (_controller == null) { 107 if (_controller == null) {
92 - _controller = StreamController<T>.broadcast();  
93 - addListener(_streamListener); 108 + _controller =
  109 + StreamController<T>.broadcast(onCancel: addListener(_streamListener));
  110 + _controller?.add(_value);
94 111
95 ///TODO: report to controller dispose 112 ///TODO: report to controller dispose
96 } 113 }
@@ -80,7 +80,8 @@ abstract class RxController with GetLifeCycleMixin {} @@ -80,7 +80,8 @@ abstract class RxController with GetLifeCycleMixin {}
80 /// A recommended way to use Getx with Future fetching 80 /// A recommended way to use Getx with Future fetching
81 abstract class StateController<T> extends GetxController with StateMixin<T> {} 81 abstract class StateController<T> extends GetxController with StateMixin<T> {}
82 82
83 -/// A controller with super lifecycles (including native lifecycles) and StateMixins 83 +/// A controller with super lifecycles (including native lifecycles)
  84 +/// and StateMixins
84 abstract class SuperController<T> extends FullLifeCycleController 85 abstract class SuperController<T> extends FullLifeCycleController
85 with FullLifeCycleMixin, StateMixin<T> {} 86 with FullLifeCycleMixin, StateMixin<T> {}
86 87
@@ -114,7 +114,7 @@ abstract class Bind<T> extends StatelessWidget { @@ -114,7 +114,7 @@ abstract class Bind<T> extends StatelessWidget {
114 114
115 final Widget? child; 115 final Widget? child;
116 116
117 - static Bind put<S extends GetxController>(S dependency, 117 + static Bind put<S>(S dependency,
118 {String? tag, 118 {String? tag,
119 bool permanent = false, 119 bool permanent = false,
120 InstanceBuilderCallback<S>? builder}) { 120 InstanceBuilderCallback<S>? builder}) {
@@ -137,10 +137,8 @@ abstract class Bind<T> extends StatelessWidget { @@ -137,10 +137,8 @@ abstract class Bind<T> extends StatelessWidget {
137 ); 137 );
138 } 138 }
139 139
140 - static Bind create<S extends GetxController>(  
141 - InstanceBuilderCallback<S> builder,  
142 - {String? tag,  
143 - bool permanent = true}) { 140 + static Bind create<S>(InstanceBuilderCallback<S> builder,
  141 + {String? tag, bool permanent = true}) {
144 Get.create<S>(builder, tag: tag, permanent: permanent); 142 Get.create<S>(builder, tag: tag, permanent: permanent);
145 return _FactoryBind<S>( 143 return _FactoryBind<S>(
146 tag: tag, 144 tag: tag,
@@ -581,4 +579,4 @@ class BindError<T> extends Error { @@ -581,4 +579,4 @@ class BindError<T> extends Error {
581 /// instance of Bindings to manage the 579 /// instance of Bindings to manage the
582 /// dependencies() (via Get.put()) for the Route you are opening. 580 /// dependencies() (via Get.put()) for the Route you are opening.
583 // ignore: one_member_abstracts 581 // ignore: one_member_abstracts
584 -abstract class Binding extends BindingsInterface<Iterable<Bind>> {} 582 +abstract class Binding extends BindingsInterface<List<Bind>> {}
@@ -3,7 +3,7 @@ export 'double_extensions.dart'; @@ -3,7 +3,7 @@ export 'double_extensions.dart';
3 export 'duration_extensions.dart'; 3 export 'duration_extensions.dart';
4 export 'dynamic_extensions.dart'; 4 export 'dynamic_extensions.dart';
5 export 'event_loop_extensions.dart'; 5 export 'event_loop_extensions.dart';
6 -export 'internacionalization.dart'; 6 +export 'internacionalization.dart' hide FirstWhereExt;
7 export 'iterable_extensions.dart'; 7 export 'iterable_extensions.dart';
8 export 'num_extensions.dart'; 8 export 'num_extensions.dart';
9 export 'string_extensions.dart'; 9 export 'string_extensions.dart';
1 name: get 1 name: get
2 description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX. 2 description: Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.
3 -version: 5.0.0-beta.15 3 +version: 5.0.0-beta.18
4 homepage: https://github.com/jonataslaw/getx 4 homepage: https://github.com/jonataslaw/getx
5 5
6 environment: 6 environment:
@@ -85,7 +85,8 @@ Future<int> stream() { @@ -85,7 +85,8 @@ Future<int> stream() {
85 // if (times == v) { 85 // if (times == v) {
86 // timer.stop(); 86 // timer.stop();
87 // print( 87 // print(
88 -// """$v listeners notified | [GET_STREAM] time: ${timer.elapsedMicroseconds}ms"""); 88 +// """$v listeners notified |
  89 +// [GET_STREAM] time: ${timer.elapsedMicroseconds}ms""");
89 // c.complete(timer.elapsedMicroseconds); 90 // c.complete(timer.elapsedMicroseconds);
90 // } 91 // }
91 // }); 92 // });
@@ -342,28 +342,28 @@ void main() { @@ -342,28 +342,28 @@ void main() {
342 expect(find.byType(SecondScreen), findsNothing); 342 expect(find.byType(SecondScreen), findsNothing);
343 }); 343 });
344 344
345 - // testWidgets(  
346 - // "Get.offNamedUntil leaves previous routes that match provided predicate",  
347 - // (tester) async {  
348 - // await tester.pumpWidget(WrapperNamed(  
349 - // initialRoute: '/first',  
350 - // namedRoutes: [  
351 - // GetPage(page: () => FirstScreen(), name: '/first'),  
352 - // GetPage(page: () => SecondScreen(), name: '/second'),  
353 - // GetPage(page: () => ThirdScreen(), name: '/third'),  
354 - // ],  
355 - // ));  
356 -  
357 - // Get.toNamed('/second');  
358 - // await tester.pumpAndSettle();  
359 - // Get.offNamedUntil('/third', (route) => route.name == '/first');  
360 - // await tester.pumpAndSettle();  
361 - // Get.back();  
362 -  
363 - // await tester.pumpAndSettle();  
364 -  
365 - // expect(find.byType(FirstScreen), findsOneWidget);  
366 - // }); 345 + testWidgets(
  346 + "Get.offNamedUntil leaves previous routes that match provided predicate",
  347 + (tester) async {
  348 + await tester.pumpWidget(WrapperNamed(
  349 + initialRoute: '/first',
  350 + namedRoutes: [
  351 + GetPage(page: () => FirstScreen(), name: '/first'),
  352 + GetPage(page: () => SecondScreen(), name: '/second'),
  353 + GetPage(page: () => ThirdScreen(), name: '/third'),
  354 + ],
  355 + ));
  356 +
  357 + Get.toNamed('/second');
  358 + await tester.pumpAndSettle();
  359 + Get.offNamedUntil('/third', (route) => route.name == '/first');
  360 + await tester.pumpAndSettle();
  361 + Get.back();
  362 +
  363 + await tester.pumpAndSettle();
  364 +
  365 + expect(find.byType(FirstScreen), findsOneWidget);
  366 + });
367 367
368 testWidgets("Get.back navigates back", (tester) async { 368 testWidgets("Get.back navigates back", (tester) async {
369 await tester.pumpWidget( 369 await tester.pumpWidget(