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
dd51afd1
Unverified
Commit
dd51afd1
authored
Jul 18, 2019
by
adazh
Committed by
GitHub
Jul 18, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Driver API that waits until frame sync. (#36334)
parent
db6c362b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
117 additions
and
0 deletions
+117
-0
find.dart
packages/flutter_driver/lib/src/common/find.dart
+13
-0
extension.dart
packages/flutter_driver/lib/src/extension/extension.dart
+27
-0
extension_test.dart
packages/flutter_driver/test/src/extension_test.dart
+77
-0
No files found.
packages/flutter_driver/lib/src/common/find.dart
View file @
dd51afd1
...
...
@@ -119,6 +119,19 @@ class WaitUntilNoTransientCallbacks extends Command {
String
get
kind
=>
'waitUntilNoTransientCallbacks'
;
}
/// A Flutter Driver command that waits until the frame is synced.
class
WaitUntilFrameSync
extends
Command
{
/// Creates a command that waits until there's no pending frame scheduled.
const
WaitUntilFrameSync
({
Duration
timeout
})
:
super
(
timeout:
timeout
);
/// Deserializes this command from the value generated by [serialize].
WaitUntilFrameSync
.
deserialize
(
Map
<
String
,
String
>
json
)
:
super
.
deserialize
(
json
);
@override
String
get
kind
=>
'waitUntilFrameSync'
;
}
/// Base class for Flutter Driver finders, objects that describe how the driver
/// should search for elements.
abstract
class
SerializableFinder
{
...
...
packages/flutter_driver/lib/src/extension/extension.dart
View file @
dd51afd1
...
...
@@ -113,6 +113,7 @@ class FlutterDriverExtension {
'waitFor'
:
_waitFor
,
'waitForAbsent'
:
_waitForAbsent
,
'waitUntilNoTransientCallbacks'
:
_waitUntilNoTransientCallbacks
,
'waitUntilFrameSync'
:
_waitUntilFrameSync
,
'get_semantics_id'
:
_getSemanticsId
,
'get_offset'
:
_getOffset
,
'get_diagnostics_tree'
:
_getDiagnosticsTree
,
...
...
@@ -133,6 +134,7 @@ class FlutterDriverExtension {
'waitFor'
:
(
Map
<
String
,
String
>
params
)
=>
WaitFor
.
deserialize
(
params
),
'waitForAbsent'
:
(
Map
<
String
,
String
>
params
)
=>
WaitForAbsent
.
deserialize
(
params
),
'waitUntilNoTransientCallbacks'
:
(
Map
<
String
,
String
>
params
)
=>
WaitUntilNoTransientCallbacks
.
deserialize
(
params
),
'waitUntilFrameSync'
:
(
Map
<
String
,
String
>
params
)
=>
WaitUntilFrameSync
.
deserialize
(
params
),
'get_semantics_id'
:
(
Map
<
String
,
String
>
params
)
=>
GetSemanticsId
.
deserialize
(
params
),
'get_offset'
:
(
Map
<
String
,
String
>
params
)
=>
GetOffset
.
deserialize
(
params
),
'get_diagnostics_tree'
:
(
Map
<
String
,
String
>
params
)
=>
GetDiagnosticsTree
.
deserialize
(
params
),
...
...
@@ -369,6 +371,31 @@ class FlutterDriverExtension {
return
null
;
}
/// Returns a future that waits until frame is synced.
///
/// Specifically, it checks:
/// * Whether the count of transient callbacks is zero.
/// * Whether there's no pending request for scheduling a new frame.
///
/// We consider the frame is synced when both conditions are met.
///
/// This method relies on a Flutter Driver mechanism called "frame sync",
/// which waits for transient animations to finish. Persistent animations will
/// cause this to wait forever.
///
/// If a test needs to interact with the app while animations are running, it
/// should avoid this method and instead disable the frame sync using
/// `set_frame_sync` method. See [FlutterDriver.runUnsynchronized] for more
/// details on how to do this. Note, disabling frame sync will require the
/// test author to use some other method to avoid flakiness.
Future
<
Result
>
_waitUntilFrameSync
(
Command
command
)
async
{
await
_waitUntilFrame
(()
{
return
SchedulerBinding
.
instance
.
transientCallbackCount
==
0
&&
!
SchedulerBinding
.
instance
.
hasScheduledFrame
;
});
return
null
;
}
Future
<
GetSemanticsIdResult
>
_getSemanticsId
(
Command
command
)
async
{
final
GetSemanticsId
semanticsCommand
=
command
;
final
Finder
target
=
await
_waitForElement
(
_createFinder
(
semanticsCommand
.
finder
));
...
...
packages/flutter_driver/test/src/extension_test.dart
View file @
dd51afd1
...
...
@@ -333,4 +333,81 @@ void main() {
children
=
result
[
'children'
];
expect
(
children
.
single
[
'children'
],
isEmpty
);
});
group
(
'waitUntilFrameSync'
,
()
{
FlutterDriverExtension
extension
;
Map
<
String
,
dynamic
>
result
;
setUp
(()
{
extension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
);
result
=
null
;
});
testWidgets
(
'returns immediately when frame is synced'
,
(
WidgetTester
tester
)
async
{
extension
.
call
(
const
WaitUntilFrameSync
().
serialize
())
.
then
<
void
>(
expectAsync1
((
Map
<
String
,
dynamic
>
r
)
{
result
=
r
;
}));
await
tester
.
idle
();
expect
(
result
,
<
String
,
dynamic
>{
'isError'
:
false
,
'response'
:
null
,
},
);
});
testWidgets
(
'waits until no transient callbacks'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
extension
.
call
(
const
WaitUntilFrameSync
().
serialize
())
.
then
<
void
>(
expectAsync1
((
Map
<
String
,
dynamic
>
r
)
{
result
=
r
;
}));
// Nothing should happen until the next frame.
await
tester
.
idle
();
expect
(
result
,
isNull
);
// NOW we should receive the result.
await
tester
.
pump
();
expect
(
result
,
<
String
,
dynamic
>{
'isError'
:
false
,
'response'
:
null
,
},
);
});
testWidgets
(
'waits until no pending scheduled frame'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrame
();
extension
.
call
(
const
WaitUntilFrameSync
().
serialize
())
.
then
<
void
>(
expectAsync1
((
Map
<
String
,
dynamic
>
r
)
{
result
=
r
;
}));
// Nothing should happen until the next frame.
await
tester
.
idle
();
expect
(
result
,
isNull
);
// NOW we should receive the result.
await
tester
.
pump
();
expect
(
result
,
<
String
,
dynamic
>{
'isError'
:
false
,
'response'
:
null
,
},
);
});
});
}
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