Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
89d1b9e4
Unverified
Commit
89d1b9e4
authored
Aug 18, 2021
by
chunhtai
Committed by
GitHub
Aug 18, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Makes PlatformInformationProvider aware of the browser default route … (#88122)
parent
7864e64d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
147 additions
and
148 deletions
+147
-148
router.dart
packages/flutter/lib/src/widgets/router.dart
+72
-75
route_notification_messages_test.dart
...lutter/test/widgets/route_notification_messages_test.dart
+9
-0
router_test.dart
packages/flutter/test/widgets/router_test.dart
+66
-73
No files found.
packages/flutter/lib/src/widgets/router.dart
View file @
89d1b9e4
...
...
@@ -201,39 +201,36 @@ class RouteInformation {
/// method.
///
/// If the location in the new route information is different from the
/// current location, this is considered to be a navigation event, the router
/// sends the new route information to the [routeInformationProvider]'s
/// [RouteInformationProvider.routerReportsNewRouteInformation] method with
/// `isNavigation` equals to true. That method as implemented in
/// [PlatformRouteInformationProvider] uses
/// [SystemNavigator.routeInformationUpdated] to notify the engine, and through
/// that the browser, to create a history entry with the new url if the
/// `isNavigation` is true.
///
/// If the location is the same as the current location but different state,
/// the router still sends the new route information to the
/// [routeInformationProvider]'s
/// [RouteInformationProvider.routerReportsNewRouteInformation] but with
/// `isNavigation` equals to false. This causes
/// [PlatformRouteInformationProvider] replace current history entry instead
/// of creating a new one.
/// current location, this is considered to be a navigation event, the
/// [PlatformRouteInformationProvider.routerReportsNewRouteInformation] method
/// calls [SystemNavigator.routeInformationUpdated] with `replace = false` to
/// notify the engine, and through that the browser, to create a history entry
/// with the new url. Otherwise,
/// [PlatformRouteInformationProvider.routerReportsNewRouteInformation] calls
/// [SystemNavigator.routeInformationUpdated] with `replace = true` to update
/// the current history entry with the latest [RouteInformation].
///
/// One can force the [Router] to report new route information as navigation
/// event to the [routeInformationProvider] (and thus the browser) even if the
/// [RouteInformation.location] has not changed by calling the [Router.navigate]
/// method with a callback that performs the state change. This allows one to
/// support the browser's back and forward buttons without changing the URL. For
/// example, the scroll position of a scroll view may be saved in the
/// [RouteInformation.state]. Using [Router.navigate] to update the scroll
/// position causes the browser to create a new history entry with the
/// method with a callback that performs the state change. This causes [Router]
/// to call the [RouteInformationProvider.routerReportsNewRouteInformation] with
/// [RouteInformationReportingType.navigate], and thus causes
/// [PlatformRouteInformationProvider] to push a new history entry regardlessly.
/// This allows one to support the browser's back and forward buttons without
/// changing the URL. For example, the scroll position of a scroll view may be
/// saved in the [RouteInformation.state]. Using [Router.navigate] to update the
/// scroll position causes the browser to create a new history entry with the
/// [RouteInformation.state] that stores this new scroll position. When the user
/// clicks the back button, the app will go back to the previous scroll position
/// without changing the URL in the location bar.
///
/// One can also force the [Router] to ignore a navigation event by making
/// those changes during a callback passed to [Router.neglect]. The [Router]
/// will not report the route information with `isNavigation` equals to false
/// even if it detects location change as the result of running the callback.
/// calls the [RouteInformationProvider.routerReportsNewRouteInformation] with
/// [RouteInformationReportingType.neglect], and thus causes
/// [PlatformRouteInformationProvider] to replace the current history entry
/// regardlessly even if it detects location change.
///
/// To opt out of URL updates entirely, pass null for [routeInformationProvider]
/// and [routeInformationParser]. This is not recommended in general, but may be
...
...
@@ -432,7 +429,7 @@ class Router<T> extends StatefulWidget {
final
_RouterScope
scope
=
context
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
widget
as
_RouterScope
;
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
.
must
,
callback
);
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
RouteInformationReportingType
.
navigate
,
callback
);
}
/// Forces the [Router] to run the [callback] without creating a new history
...
...
@@ -461,7 +458,7 @@ class Router<T> extends StatefulWidget {
final
_RouterScope
scope
=
context
.
getElementForInheritedWidgetOfExactType
<
_RouterScope
>()!
.
widget
as
_RouterScope
;
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
.
ignore
,
callback
);
scope
.
routerState
.
_setStateWithExplicitReportStatus
(
RouteInformationReportingType
.
neglect
,
callback
);
}
@override
...
...
@@ -471,22 +468,33 @@ class Router<T> extends StatefulWidget {
typedef
_AsyncPassthrough
<
Q
>
=
Future
<
Q
>
Function
(
Q
);
typedef
_DelegateRouteSetter
<
T
>
=
Future
<
void
>
Function
(
T
);
// Whether to report the route information in this build cycle.
enum
_IntentionToReportRouteInformation
{
// We haven't receive any signal on whether to report.
/// The [Router]'s intention when it reports a new [RouteInformation] to the
/// [RouteInformationProvider].
///
/// See also:
///
/// * [RouteInformationProvider.routerReportsNewRouteInformation]: which is
/// called by the router when it has a new route information to report.
enum
RouteInformationReportingType
{
/// Router does not have a specific intention.
///
/// The router generates a new route information every time it detects route
/// information may have change due to a rebuild. This is the default type if
/// neither [Router.neglect] nor [Router.navigate] was used during the
/// rebuild.
none
,
//
Report if route information changes.
maybe
,
// Report regardless of route information changes.
must
,
//
Don't report regardless of route information changes
.
ignor
e
,
//
/ The accompanying [RouteInformation] were generated during a
/// [Router.neglect] call.
neglect
,
/// The accompanying [RouteInformation] were generated during a
//
/ [Router.navigate] call
.
navigat
e
,
}
class
_RouterState
<
T
>
extends
State
<
Router
<
T
>>
with
RestorationMixin
{
Object
?
_currentRouteInformationParserTransaction
;
Object
?
_currentRouterDelegateTransaction
;
_IntentionToReportRouteInformation
_currentIntentionToReport
=
_IntentionToReportRouteInformation
.
none
;
RouteInformationReportingType
?
_currentIntentionToReport
;
final
_RestorableRouteInformation
_routeInformation
=
_RestorableRouteInformation
();
@override
...
...
@@ -515,7 +523,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
void
_scheduleRouteInformationReportingTask
()
{
if
(
_routeInformationReportingTaskScheduled
||
widget
.
routeInformationProvider
==
null
)
return
;
assert
(
_currentIntentionToReport
!=
_IntentionToReportRouteInformation
.
none
);
assert
(
_currentIntentionToReport
!=
null
);
_routeInformationReportingTaskScheduled
=
true
;
SchedulerBinding
.
instance
!.
addPostFrameCallback
(
_reportRouteInformation
);
}
...
...
@@ -525,31 +533,11 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
_routeInformationReportingTaskScheduled
=
false
;
if
(
_routeInformation
.
value
!=
null
)
{
final
RouteInformation
oldRouteInformation
=
widget
.
routeInformationProvider
!.
value
;
final
RouteInformation
currentRouteInformation
=
_routeInformation
.
value
!;
switch
(
_currentIntentionToReport
)
{
case
_IntentionToReportRouteInformation
.
none
:
assert
(
false
,
'_reportRouteInformation must not be called with _IntentionToReportRouteInformation.none'
);
return
;
case
_IntentionToReportRouteInformation
.
ignore
:
if
(
oldRouteInformation
.
location
!=
currentRouteInformation
.
location
||
oldRouteInformation
.
state
!=
currentRouteInformation
.
state
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
isNavigation:
false
);
}
break
;
case
_IntentionToReportRouteInformation
.
maybe
:
if
(
oldRouteInformation
.
location
!=
currentRouteInformation
.
location
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
);
}
else
if
(
oldRouteInformation
.
state
!=
currentRouteInformation
.
state
)
{
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
isNavigation:
false
);
}
break
;
case
_IntentionToReportRouteInformation
.
must
:
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
);
break
;
}
assert
(
_currentIntentionToReport
!=
null
);
widget
.
routeInformationProvider
!.
routerReportsNewRouteInformation
(
currentRouteInformation
,
type:
_currentIntentionToReport
!);
}
_currentIntentionToReport
=
_IntentionToReportRouteInformation
.
none
;
_currentIntentionToReport
=
RouteInformationReportingType
.
none
;
}
RouteInformation
?
_retrieveNewRouteInformation
()
{
...
...
@@ -560,13 +548,14 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
}
void
_setStateWithExplicitReportStatus
(
_IntentionToReportRouteInformation
status
,
RouteInformationReportingType
status
,
VoidCallback
fn
,
)
{
assert
(
status
!=
null
);
assert
(
status
.
index
>=
_IntentionToReportRouteInformation
.
mus
t
.
index
);
assert
(
status
.
index
>=
RouteInformationReportingType
.
neglec
t
.
index
);
assert
(()
{
if
(
_currentIntentionToReport
.
index
>=
_IntentionToReportRouteInformation
.
must
.
index
&&
if
(
_currentIntentionToReport
!=
null
&&
_currentIntentionToReport
!=
RouteInformationReportingType
.
none
&&
_currentIntentionToReport
!=
status
)
{
FlutterError
.
reportError
(
const
FlutterErrorDetails
(
...
...
@@ -587,9 +576,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
void
_maybeNeedToReportRouteInformation
()
{
_routeInformation
.
value
=
_retrieveNewRouteInformation
();
_currentIntentionToReport
=
_currentIntentionToReport
!=
_IntentionToReportRouteInformation
.
none
?
_currentIntentionToReport
:
_IntentionToReportRouteInformation
.
maybe
;
_currentIntentionToReport
??=
RouteInformationReportingType
.
none
;
_scheduleRouteInformationReportingTask
();
}
...
...
@@ -1325,19 +1312,21 @@ abstract class RouteInformationProvider extends ValueListenable<RouteInformation
/// other side effects. For example, the [PlatformRouteInformationProvider]
/// overrides this method to report the route information back to the engine.
///
/// The [routeInformation] is the new route information after the navigation
/// event.
/// The `routeInformation` is the new route information generated by the
/// Router rebuild, and it can be the same or different from the
/// [value].
///
/// The [isNavigation] denotes whether the new route information is generated
/// as a result of a navigation event. This information can be useful in a
/// web application, for example, the [PlatformRouteInformationProvider] uses
/// this flag to decide whether to create a browser history entry that enables
/// browser backward and forward buttons.
/// The `type` denotes the [Router]'s intention when it reports this
/// `routeInformation`. It is useful when deciding how to update the internal
/// state of [RouteInformationProvider] subclass with the `routeInformation`.
/// For example, [PlatformRouteInformationProvider] uses this property to
/// decide whether to push or replace the browser history entry with the new
/// `routeInformation`.
///
/// For more information on how [Router] determines a navigation event, see
/// the "URL updates for web applications" section in the [Router]
/// documentation.
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
tru
e
})
{}
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
typ
e
})
{}
}
/// The route information provider that propagates the platform route information changes.
...
...
@@ -1360,24 +1349,32 @@ class PlatformRouteInformationProvider extends RouteInformationProvider with Wid
})
:
_value
=
initialRouteInformation
;
@override
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
true
})
{
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
type
})
{
final
bool
replace
=
type
==
RouteInformationReportingType
.
neglect
||
(
type
==
RouteInformationReportingType
.
none
&&
_valueInEngine
.
location
==
routeInformation
.
location
);
SystemNavigator
.
selectMultiEntryHistory
();
SystemNavigator
.
routeInformationUpdated
(
location:
routeInformation
.
location
!,
state:
routeInformation
.
state
,
replace:
!
isNavigation
,
replace:
replace
,
);
_value
=
routeInformation
;
_valueInEngine
=
routeInformation
;
}
@override
RouteInformation
get
value
=>
_value
;
RouteInformation
_value
;
RouteInformation
_valueInEngine
=
RouteInformation
(
location:
WidgetsBinding
.
instance
!.
window
.
defaultRouteName
);
void
_platformReportsNewRouteInformation
(
RouteInformation
routeInformation
)
{
if
(
_value
==
routeInformation
)
return
;
_value
=
routeInformation
;
_valueInEngine
=
routeInformation
;
notifyListeners
();
}
...
...
packages/flutter/test/widgets/route_notification_messages_test.dart
View file @
89d1b9e4
...
...
@@ -286,6 +286,15 @@ void main() {
routerDelegate:
delegate
,
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'initial'
,
'state'
:
null
,
'replace'
:
false
,
}),
]);
log
.
clear
();
// Triggers a router rebuild and verify the route information is reported
// to the web engine.
...
...
packages/flutter/test/widgets/router_test.dart
View file @
89d1b9e4
...
...
@@ -477,14 +477,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
testWidgets
(
'router does report URL change correctly'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
bool
?
reportedIsNavigation
;
RouteInformationReportingType
?
reportedType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// Makes sure we only report once after manually cleaning up.
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reported
IsNavigation
,
isNull
);
expect
(
reported
Type
,
isNull
);
reportedRouteInformation
=
information
;
reported
IsNavigation
=
isNavigation
;
reported
Type
=
type
;
},
);
final
SimpleRouterDelegate
delegate
=
SimpleRouterDelegate
(
...
...
@@ -514,7 +514,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
!.
location
,
'initial'
);
expect
(
reportedType
,
RouteInformationReportingType
.
none
);
reportedRouteInformation
=
null
;
reportedType
=
null
;
delegate
.
routeInformation
=
const
RouteInformation
(
location:
'update'
,
);
...
...
@@ -522,11 +525,11 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
// The router should report as non navigation event if only state changes.
reportedRouteInformation
=
null
;
reported
IsNavigation
=
null
;
reported
Type
=
null
;
delegate
.
routeInformation
=
const
RouteInformation
(
location:
'update'
,
state:
'another state'
,
...
...
@@ -535,31 +538,31 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
expect
(
reportedRouteInformation
!.
state
,
'another state'
);
expect
(
reported
IsNavigation
,
isFals
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
reportedRouteInformation
=
null
;
reported
IsNavigation
=
null
;
reported
Type
=
null
;
bool
result
=
false
;
result
=
await
outerDispatcher
.
invokeCallback
(
SynchronousFuture
<
bool
>(
false
));
expect
(
result
,
isTrue
);
await
tester
.
pump
();
expect
(
find
.
text
(
'popped'
),
findsOneWidget
);
expect
(
reportedRouteInformation
!.
location
,
'popped'
);
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
non
e
);
});
testWidgets
(
'router can be forced to recognize or ignore navigating events'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
bool
?
reportedIsNavigation
;
RouteInformationReportingType
?
reportedType
;
bool
isNavigating
=
false
;
late
RouteInformation
nextRouteInformation
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// Makes sure we only report once after manually cleaning up.
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reported
IsNavigation
,
isNull
);
expect
(
reported
Type
,
isNull
);
reportedRouteInformation
=
information
;
reported
IsNavigation
=
isNavigation
;
reported
Type
=
type
;
},
);
provider
.
value
=
const
RouteInformation
(
...
...
@@ -595,7 +598,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportedRouteInformation
!.
location
,
'initial'
);
expect
(
reportedType
,
RouteInformationReportingType
.
none
);
reportedType
=
null
;
reportedRouteInformation
=
null
;
nextRouteInformation
=
const
RouteInformation
(
location:
'update'
,
...
...
@@ -604,9 +610,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
await
tester
.
pump
();
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
reported
IsNavigation
,
isFalse
);
expect
(
reported
Type
,
RouteInformationReportingType
.
neglect
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
reported
IsNavigation
=
null
;
reported
Type
=
null
;
reportedRouteInformation
=
null
;
isNavigating
=
true
;
...
...
@@ -615,21 +621,22 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
// report a route information because isNavigating = true.
await
tester
.
tap
(
find
.
byType
(
ElevatedButton
));
await
tester
.
pump
();
expect
(
reported
IsNavigation
,
isTru
e
);
expect
(
reported
Type
,
RouteInformationReportingType
.
navigat
e
);
expect
(
reportedRouteInformation
!.
location
,
'update'
);
reported
IsNavigation
=
null
;
reported
Type
=
null
;
reportedRouteInformation
=
null
;
});
testWidgets
(
'router ignore navigating events updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
updatedRouteInformation
;
late
RouteInformation
nextRouteInformation
;
RouteInformationReportingType
?
reportingType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
// This should never be a navigation event.
expect
(
isNavigation
,
false
);
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
expect
(
reportingType
,
isNull
);
expect
(
updatedRouteInformation
,
isNull
);
updatedRouteInformation
=
information
;
reportingType
=
type
;
},
);
provider
.
value
=
const
RouteInformation
(
...
...
@@ -658,7 +665,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
updatedRouteInformation
=
null
;
reportingType
=
null
;
nextRouteInformation
=
const
RouteInformation
(
location:
'update'
,
...
...
@@ -668,17 +678,20 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
expect
(
updatedRouteInformation
!.
location
,
'update'
);
expect
(
reportingType
,
RouteInformationReportingType
.
neglect
);
});
testWidgets
(
'state change without location changes updates RouteInformationProvider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
updatedRouteInformation
;
late
RouteInformation
nextRouteInformation
;
RouteInformationReportingType
?
reportingType
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
onRouterReport:
(
RouteInformation
information
,
RouteInformationReportingType
type
)
{
// This should never be a navigation event.
expect
(
isNavigation
,
false
);
expect
(
reportingType
,
isNull
);
expect
(
updatedRouteInformation
,
isNull
);
updatedRouteInformation
=
information
;
reportingType
=
type
;
},
);
provider
.
value
=
const
RouteInformation
(
...
...
@@ -705,7 +718,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
updatedRouteInformation
,
isNull
);
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
updatedRouteInformation
=
null
;
reportingType
=
null
;
nextRouteInformation
=
const
RouteInformation
(
location:
'initial'
,
...
...
@@ -715,45 +731,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
await
tester
.
pump
();
expect
(
updatedRouteInformation
!.
location
,
'initial'
);
expect
(
updatedRouteInformation
!.
state
,
'state2'
);
});
testWidgets
(
'router does not report when route information is up to date with route information provider'
,
(
WidgetTester
tester
)
async
{
RouteInformation
?
reportedRouteInformation
;
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
information
,
bool
isNavigation
)
{
reportedRouteInformation
=
information
;
},
);
provider
.
value
=
const
RouteInformation
(
location:
'initial'
,
);
final
SimpleRouterDelegate
delegate
=
SimpleRouterDelegate
(
reportConfiguration:
true
);
delegate
.
builder
=
(
BuildContext
context
,
RouteInformation
?
routeInformation
)
{
return
Text
(
routeInformation
!.
location
!);
};
await
tester
.
pumpWidget
(
buildBoilerPlate
(
Router
<
RouteInformation
>(
routeInformationProvider:
provider
,
routeInformationParser:
SimpleRouteInformationParser
(),
routerDelegate:
delegate
,
),
));
expect
(
find
.
text
(
'initial'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isNull
);
// This will cause the router to rebuild.
provider
.
value
=
const
RouteInformation
(
location:
'update'
,
);
// This will schedule the route reporting.
delegate
.
notifyListeners
();
await
tester
.
pump
();
expect
(
find
.
text
(
'initial'
),
findsNothing
);
expect
(
find
.
text
(
'update'
),
findsOneWidget
);
// The router should not report because the route name is already up to
// date.
expect
(
reportedRouteInformation
,
isNull
);
expect
(
reportingType
,
RouteInformationReportingType
.
none
);
});
testWidgets
(
'PlatformRouteInformationProvider works'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -823,18 +801,33 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
true
));
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
true
),
type:
RouteInformationReportingType
.
none
);
// Implicit reporting pushes new history entry if the location changes.
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'a'
,
'state'
:
true
,
'replace'
:
false
}),
]);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'a'
,
state:
false
),
type:
RouteInformationReportingType
.
none
);
// Since the location is the same, the provider sends replaces message.
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'a'
,
'state'
:
false
,
'replace'
:
true
}),
]);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
isNavigation:
false
);
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
type:
RouteInformationReportingType
.
neglect
);
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'b'
,
'state'
:
false
,
'replace'
:
true
}),
]);
log
.
clear
();
provider
.
routerReportsNewRouteInformation
(
const
RouteInformation
(
location:
'b'
,
state:
false
),
type:
RouteInformationReportingType
.
navigate
);
expect
(
log
,
<
Object
>[
isMethodCall
(
'selectMultiEntryHistory'
,
arguments:
null
),
isMethodCall
(
'routeInformationUpdated'
,
arguments:
<
String
,
dynamic
>{
'location'
:
'b'
,
'state'
:
false
,
'replace'
:
false
}),
]);
});
testWidgets
(
'RootBackButtonDispatcher works'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -1239,7 +1232,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
testWidgets
(
'Router reports location if it is different from location given by OS'
,
(
WidgetTester
tester
)
async
{
final
List
<
RouteInformation
>
reportedRouteInformation
=
<
RouteInformation
>[];
final
SimpleRouteInformationProvider
provider
=
SimpleRouteInformationProvider
(
onRouterReport:
(
RouteInformation
info
,
bool
isNavigation
)
=>
reportedRouteInformation
.
add
(
info
),
onRouterReport:
(
RouteInformation
info
,
RouteInformationReportingType
type
)
=>
reportedRouteInformation
.
add
(
info
),
)..
value
=
const
RouteInformation
(
location:
'/home'
);
await
tester
.
pumpWidget
(
buildBoilerPlate
(
...
...
@@ -1256,13 +1249,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
));
expect
(
find
.
text
(
'Current route: /home'
),
findsOneWidget
);
expect
(
reportedRouteInformation
,
isEmpty
);
expect
(
reportedRouteInformation
.
single
.
location
,
'/home'
);
provider
.
value
=
const
RouteInformation
(
location:
'/doesNotExist'
);
await
tester
.
pump
();
expect
(
find
.
text
(
'Current route: /404'
),
findsOneWidget
);
expect
(
reportedRouteInformation
.
single
.
location
,
'/404'
);
expect
(
reportedRouteInformation
[
1
]
.
location
,
'/404'
);
});
}
...
...
@@ -1277,7 +1270,7 @@ Widget buildBoilerPlate(Widget child) {
typedef
SimpleRouterDelegateBuilder
=
Widget
Function
(
BuildContext
,
RouteInformation
?);
typedef
SimpleRouterDelegatePopRoute
=
Future
<
bool
>
Function
();
typedef
SimpleNavigatorRouterDelegatePopPage
<
T
>
=
bool
Function
(
Route
<
T
>
route
,
T
result
);
typedef
RouterReportRouterInformation
=
void
Function
(
RouteInformation
,
bool
);
typedef
RouterReportRouterInformation
=
void
Function
(
RouteInformation
,
RouteInformationReportingType
);
class
SimpleRouteInformationParser
extends
RouteInformationParser
<
RouteInformation
>
{
SimpleRouteInformationParser
();
...
...
@@ -1398,9 +1391,9 @@ class SimpleRouteInformationProvider extends RouteInformationProvider with Chang
}
@override
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
bool
isNavigation
=
tru
e
})
{
void
routerReportsNewRouteInformation
(
RouteInformation
routeInformation
,
{
required
RouteInformationReportingType
typ
e
})
{
_value
=
routeInformation
;
onRouterReport
?.
call
(
routeInformation
,
isNavigation
);
onRouterReport
?.
call
(
routeInformation
,
type
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment