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
3ece9c63
Unverified
Commit
3ece9c63
authored
Jan 28, 2021
by
Dan Field
Committed by
GitHub
Jan 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Flutter_driver nnbd (#74856)
parent
650b2406
Changes
27
Show whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
291 additions
and
380 deletions
+291
-380
test.dart
dev/bots/test.dart
+1
-1
flutter_driver.dart
packages/flutter_driver/lib/flutter_driver.dart
+0
-2
error.dart
packages/flutter_driver/lib/src/common/error.dart
+2
-2
fuchsia_compat.dart
packages/flutter_driver/lib/src/common/fuchsia_compat.dart
+4
-6
common.dart
packages/flutter_driver/lib/src/driver/common.dart
+0
-2
driver.dart
packages/flutter_driver/lib/src/driver/driver.dart
+41
-43
percentile_utils.dart
packages/flutter_driver/lib/src/driver/percentile_utils.dart
+0
-2
profiling_summarizer.dart
...s/flutter_driver/lib/src/driver/profiling_summarizer.dart
+7
-11
scene_display_lag_summarizer.dart
...r_driver/lib/src/driver/scene_display_lag_summarizer.dart
+2
-4
timeline.dart
packages/flutter_driver/lib/src/driver/timeline.dart
+25
-26
timeline_summary.dart
packages/flutter_driver/lib/src/driver/timeline_summary.dart
+7
-9
vmservice_driver.dart
packages/flutter_driver/lib/src/driver/vmservice_driver.dart
+49
-51
web_driver.dart
packages/flutter_driver/lib/src/driver/web_driver.dart
+8
-10
pubspec.yaml
packages/flutter_driver/pubspec.yaml
+6
-7
common.dart
packages/flutter_driver/test/common.dart
+0
-2
flutter_driver_test.dart
packages/flutter_driver/test/flutter_driver_test.dart
+39
-80
extension_test.dart
...es/flutter_driver/test/src/real_tests/extension_test.dart
+82
-84
find_test.dart
packages/flutter_driver/test/src/real_tests/find_test.dart
+0
-2
io_extension_test.dart
...flutter_driver/test/src/real_tests/io_extension_test.dart
+1
-3
request_data_test.dart
...flutter_driver/test/src/real_tests/request_data_test.dart
+0
-2
timeline_summary_test.dart
...ter_driver/test/src/real_tests/timeline_summary_test.dart
+3
-5
timeline_test.dart
...ges/flutter_driver/test/src/real_tests/timeline_test.dart
+14
-16
wait_test.dart
packages/flutter_driver/test/src/real_tests/wait_test.dart
+0
-2
failure.dart
packages/flutter_driver/test_driver/failure.dart
+0
-2
failure_test.dart
packages/flutter_driver/test_driver/failure_test.dart
+0
-2
success.dart
packages/flutter_driver/test_driver/success.dart
+0
-2
success_test.dart
packages/flutter_driver/test_driver/success_test.dart
+0
-2
No files found.
dev/bots/test.dart
View file @
3ece9c63
...
...
@@ -669,7 +669,7 @@ Future<void> _runFrameworkTests() async {
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'examples'
,
'hello_world'
),
options:
soundNullSafetyOptions
);
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'examples'
,
'layers'
),
options:
soundNullSafetyOptions
);
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'dev'
,
'benchmarks'
,
'test_apps'
,
'stocks'
));
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'packages'
,
'flutter_driver'
),
tests:
<
String
>[
path
.
join
(
'test'
,
'src'
,
'real_tests'
)]);
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'packages'
,
'flutter_driver'
),
tests:
<
String
>[
path
.
join
(
'test'
,
'src'
,
'real_tests'
)]
,
options:
soundNullSafetyOptions
);
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'packages'
,
'integration_test'
));
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'packages'
,
'flutter_goldens'
),
options:
soundNullSafetyOptions
);
await
_runFlutterTest
(
path
.
join
(
flutterRoot
,
'packages'
,
'flutter_localizations'
),
options:
soundNullSafetyOptions
);
...
...
packages/flutter_driver/lib/flutter_driver.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Provides API to test Flutter applications that run on real
/// devices and emulators.
///
...
...
packages/flutter_driver/lib/src/common/error.dart
View file @
3ece9c63
...
...
@@ -14,10 +14,10 @@ class DriverError extends Error {
final
String
message
;
/// The error object that was caught and wrapped by this error object, if any.
final
dynamic
originalError
;
final
Object
?
originalError
;
/// The stack trace that was caught and wrapped by this error object, if any.
final
dynamic
originalStackTrace
;
final
Object
?
originalStackTrace
;
@override
String
toString
()
{
...
...
packages/flutter_driver/lib/src/common/fuchsia_compat.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Convenience methods for Flutter application driving on Fuchsia. Can
/// be run on either a host machine (making a remote connection to a Fuchsia
/// device), or on the target Fuchsia machine.
...
...
@@ -40,13 +38,13 @@ class _DummySshCommandRunner implements SshCommandRunner {
}
@override
String
get
sshConfigPath
=>
null
;
String
get
sshConfigPath
=>
''
;
@override
String
get
address
=>
InternetAddress
.
loopbackIPv4
.
address
;
@override
String
get
interface
=>
null
;
String
get
interface
=>
''
;
@
override
Future
<
List
<
String
>>
run
(
String
command
)
async
{
...
...
@@ -72,8 +70,8 @@ class _DummySshCommandRunner implements SshCommandRunner {
Future
<
PortForwarder
>
_dummyPortForwardingFunction
(
String
address
,
int
remotePort
,
[
String
interface
=
''
,
String
configFile
,
String
?
interface
,
String
?
configFile
,
])
async
{
return
_DummyPortForwarder
(
remotePort
,
remotePort
);
}
...
...
packages/flutter_driver/lib/src/driver/common.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
show
Platform
;
import
'package:file/file.dart'
;
...
...
packages/flutter_driver/lib/src/driver/driver.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'package:meta/meta.dart'
;
...
...
@@ -95,14 +93,14 @@ abstract class FlutterDriver {
/// for the VM.
@visibleForTesting
factory
FlutterDriver
.
connectedTo
({
FlutterWebConnection
webConnection
,
vms
.
VmService
serviceClient
,
vms
.
Isolate
appIsolate
,
FlutterWebConnection
?
webConnection
,
vms
.
VmService
?
serviceClient
,
vms
.
Isolate
?
appIsolate
,
})
{
if
(
webConnection
!=
null
)
{
return
WebFlutterDriver
.
connectedTo
(
webConnection
);
}
return
VMServiceFlutterDriver
.
connectedTo
(
serviceClient
,
appIsolate
);
return
VMServiceFlutterDriver
.
connectedTo
(
serviceClient
!,
appIsolate
!
);
}
/// Connects to a Flutter application.
...
...
@@ -140,13 +138,13 @@ abstract class FlutterDriver {
/// fail (completing with an error). A timeout can be applied by the caller
/// using [Future.timeout] if necessary.
static
Future
<
FlutterDriver
>
connect
({
String
dartVmServiceUrl
,
String
?
dartVmServiceUrl
,
bool
printCommunication
=
false
,
bool
logCommunicationToFile
=
true
,
int
isolateNumber
,
Pattern
fuchsiaModuleTarget
,
Duration
timeout
,
Map
<
String
,
dynamic
>
headers
,
int
?
isolateNumber
,
Pattern
?
fuchsiaModuleTarget
,
Duration
?
timeout
,
Map
<
String
,
dynamic
>
?
headers
,
})
async
{
if
(
Platform
.
environment
[
'FLUTTER_WEB_TEST'
]
!=
null
)
{
return
WebFlutterDriver
.
connectWeb
(
hostUrl:
dartVmServiceUrl
,
timeout:
timeout
);
...
...
@@ -185,22 +183,22 @@ abstract class FlutterDriver {
Future
<
Map
<
String
,
dynamic
>>
sendCommand
(
Command
command
)
async
=>
throw
UnimplementedError
();
/// Checks the status of the Flutter Driver extension.
Future
<
Health
>
checkHealth
({
Duration
timeout
})
async
{
Future
<
Health
>
checkHealth
({
Duration
?
timeout
})
async
{
return
Health
.
fromJson
(
await
sendCommand
(
GetHealth
(
timeout:
timeout
)));
}
/// Returns a dump of the render tree.
Future
<
RenderTree
>
getRenderTree
({
Duration
timeout
})
async
{
Future
<
RenderTree
>
getRenderTree
({
Duration
?
timeout
})
async
{
return
RenderTree
.
fromJson
(
await
sendCommand
(
GetRenderTree
(
timeout:
timeout
)));
}
/// Returns a dump of the layer tree.
Future
<
LayerTree
>
getLayerTree
({
Duration
timeout
})
async
{
Future
<
LayerTree
>
getLayerTree
({
Duration
?
timeout
})
async
{
return
LayerTree
.
fromJson
(
await
sendCommand
(
GetLayerTree
(
timeout:
timeout
)));
}
/// Taps at the center of the widget located by [finder].
Future
<
void
>
tap
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
void
>
tap
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
await
sendCommand
(
Tap
(
finder
,
timeout:
timeout
));
}
...
...
@@ -213,17 +211,17 @@ abstract class FlutterDriver {
///
/// * [FlutterDriver.runUnsynchronized], which will execute an action
/// with frame sync disabled even while frames are pending.
Future
<
void
>
waitFor
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
void
>
waitFor
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
await
sendCommand
(
WaitFor
(
finder
,
timeout:
timeout
));
}
/// Waits until [finder] can no longer locate the target.
Future
<
void
>
waitForAbsent
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
void
>
waitForAbsent
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
await
sendCommand
(
WaitForAbsent
(
finder
,
timeout:
timeout
));
}
/// Waits until the given [waitCondition] is satisfied.
Future
<
void
>
waitForCondition
(
SerializableWaitCondition
waitCondition
,
{
Duration
timeout
})
async
{
Future
<
void
>
waitForCondition
(
SerializableWaitCondition
waitCondition
,
{
Duration
?
timeout
})
async
{
await
sendCommand
(
WaitForCondition
(
waitCondition
,
timeout:
timeout
));
}
...
...
@@ -231,7 +229,7 @@ abstract class FlutterDriver {
///
/// Use this method when you need to wait for the moment when the application
/// becomes "stable", for example, prior to taking a [screenshot].
Future
<
void
>
waitUntilNoTransientCallbacks
({
Duration
timeout
})
async
{
Future
<
void
>
waitUntilNoTransientCallbacks
({
Duration
?
timeout
})
async
{
await
sendCommand
(
WaitForCondition
(
const
NoTransientCallbacks
(),
timeout:
timeout
));
}
...
...
@@ -246,7 +244,7 @@ abstract class FlutterDriver {
await
sendCommand
(
const
WaitForCondition
(
FirstFrameRasterized
()));
}
Future
<
DriverOffset
>
_getOffset
(
SerializableFinder
finder
,
OffsetType
type
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
_getOffset
(
SerializableFinder
finder
,
OffsetType
type
,
{
Duration
?
timeout
})
async
{
final
GetOffset
command
=
GetOffset
(
finder
,
type
,
timeout:
timeout
);
final
GetOffsetResult
result
=
GetOffsetResult
.
fromJson
(
await
sendCommand
(
command
));
return
DriverOffset
(
result
.
dx
,
result
.
dy
);
...
...
@@ -256,7 +254,7 @@ abstract class FlutterDriver {
///
/// The offset is expressed in logical pixels and can be translated to
/// device pixels via [dart:ui.FlutterView.devicePixelRatio].
Future
<
DriverOffset
>
getTopLeft
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
getTopLeft
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
_getOffset
(
finder
,
OffsetType
.
topLeft
,
timeout:
timeout
);
}
...
...
@@ -264,7 +262,7 @@ abstract class FlutterDriver {
///
/// The offset is expressed in logical pixels and can be translated to
/// device pixels via [dart:ui.FlutterView.devicePixelRatio].
Future
<
DriverOffset
>
getTopRight
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
getTopRight
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
_getOffset
(
finder
,
OffsetType
.
topRight
,
timeout:
timeout
);
}
...
...
@@ -272,7 +270,7 @@ abstract class FlutterDriver {
///
/// The offset is expressed in logical pixels and can be translated to
/// device pixels via [dart:ui.FlutterView.devicePixelRatio].
Future
<
DriverOffset
>
getBottomLeft
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
getBottomLeft
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
_getOffset
(
finder
,
OffsetType
.
bottomLeft
,
timeout:
timeout
);
}
...
...
@@ -280,7 +278,7 @@ abstract class FlutterDriver {
///
/// The offset is expressed in logical pixels and can be translated to
/// device pixels via [dart:ui.FlutterView.devicePixelRatio].
Future
<
DriverOffset
>
getBottomRight
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
getBottomRight
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
_getOffset
(
finder
,
OffsetType
.
bottomRight
,
timeout:
timeout
);
}
...
...
@@ -288,7 +286,7 @@ abstract class FlutterDriver {
///
/// The offset is expressed in logical pixels and can be translated to
/// device pixels via [dart:ui.FlutterView.devicePixelRatio].
Future
<
DriverOffset
>
getCenter
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
DriverOffset
>
getCenter
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
_getOffset
(
finder
,
OffsetType
.
center
,
timeout:
timeout
);
}
...
...
@@ -317,7 +315,7 @@ abstract class FlutterDriver {
SerializableFinder
finder
,
{
int
subtreeDepth
=
0
,
bool
includeProperties
=
true
,
Duration
timeout
,
Duration
?
timeout
,
})
async
{
return
sendCommand
(
GetDiagnosticsTree
(
finder
,
...
...
@@ -325,7 +323,7 @@ abstract class FlutterDriver {
subtreeDepth:
subtreeDepth
,
includeProperties:
includeProperties
,
timeout:
timeout
,
));
))
as
Map
<
String
,
Object
>
;
}
/// Returns a JSON map of the [DiagnosticsNode] that is associated with the
...
...
@@ -350,7 +348,7 @@ abstract class FlutterDriver {
SerializableFinder
finder
,
{
int
subtreeDepth
=
0
,
bool
includeProperties
=
true
,
Duration
timeout
,
Duration
?
timeout
,
})
async
{
return
sendCommand
(
GetDiagnosticsTree
(
finder
,
...
...
@@ -358,7 +356,7 @@ abstract class FlutterDriver {
subtreeDepth:
subtreeDepth
,
includeProperties:
includeProperties
,
timeout:
timeout
,
));
))
as
Map
<
String
,
Object
>
;
}
/// Tell the driver to perform a scrolling action.
...
...
@@ -374,7 +372,7 @@ abstract class FlutterDriver {
///
/// The move events are generated at a given [frequency] in Hz (or events per
/// second). It defaults to 60Hz.
Future
<
void
>
scroll
(
SerializableFinder
finder
,
double
dx
,
double
dy
,
Duration
duration
,
{
int
frequency
=
60
,
Duration
timeout
})
async
{
Future
<
void
>
scroll
(
SerializableFinder
finder
,
double
dx
,
double
dy
,
Duration
duration
,
{
int
frequency
=
60
,
Duration
?
timeout
})
async
{
await
sendCommand
(
Scroll
(
finder
,
dx
,
dy
,
duration
,
frequency
,
timeout:
timeout
));
}
...
...
@@ -385,7 +383,7 @@ abstract class FlutterDriver {
/// that lazily creates its children, like [ListView] or [CustomScrollView],
/// then this method may fail because [finder] doesn't actually exist.
/// The [scrollUntilVisible] method can be used in this case.
Future
<
void
>
scrollIntoView
(
SerializableFinder
finder
,
{
double
alignment
=
0.0
,
Duration
timeout
})
async
{
Future
<
void
>
scrollIntoView
(
SerializableFinder
finder
,
{
double
alignment
=
0.0
,
Duration
?
timeout
})
async
{
await
sendCommand
(
ScrollIntoView
(
finder
,
alignment:
alignment
,
timeout:
timeout
));
}
...
...
@@ -417,7 +415,7 @@ abstract class FlutterDriver {
double
alignment
=
0.0
,
double
dxScroll
=
0.0
,
double
dyScroll
=
0.0
,
Duration
timeout
,
Duration
?
timeout
,
})
async
{
assert
(
scrollable
!=
null
);
assert
(
item
!=
null
);
...
...
@@ -442,7 +440,7 @@ abstract class FlutterDriver {
}
/// Returns the text in the `Text` widget located by [finder].
Future
<
String
>
getText
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
String
>
getText
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
return
GetTextResult
.
fromJson
(
await
sendCommand
(
GetText
(
finder
,
timeout:
timeout
))).
text
;
}
...
...
@@ -478,7 +476,7 @@ abstract class FlutterDriver {
/// await driver.waitFor(find.text('World!')); // verify new text appears
/// });
/// ```
Future
<
void
>
enterText
(
String
text
,
{
Duration
timeout
})
async
{
Future
<
void
>
enterText
(
String
text
,
{
Duration
?
timeout
})
async
{
await
sendCommand
(
EnterText
(
text
,
timeout:
timeout
));
}
...
...
@@ -495,7 +493,7 @@ abstract class FlutterDriver {
/// When enabled, the operating system's configured keyboard will not be
/// invoked when the widget is focused, as the [SystemChannels.textInput]
/// channel will be mocked out.
Future
<
void
>
setTextEntryEmulation
({
@required
bool
enabled
,
Duration
timeout
})
async
{
Future
<
void
>
setTextEntryEmulation
({
required
bool
enabled
,
Duration
?
timeout
})
async
{
assert
(
enabled
!=
null
);
await
sendCommand
(
SetTextEntryEmulation
(
enabled
,
timeout:
timeout
));
}
...
...
@@ -506,7 +504,7 @@ abstract class FlutterDriver {
/// It's expected that the application has registered a [DataHandler]
/// callback in [enableFlutterDriverExtension] that can successfully handle
/// these requests.
Future
<
String
>
requestData
(
String
message
,
{
Duration
timeout
})
async
{
Future
<
String
>
requestData
(
String
message
,
{
Duration
?
timeout
})
async
{
return
RequestDataResult
.
fromJson
(
await
sendCommand
(
RequestData
(
message
,
timeout:
timeout
))).
message
;
}
...
...
@@ -514,7 +512,7 @@ abstract class FlutterDriver {
///
/// Returns true when the call actually changed the state from on to off or
/// vice versa.
Future
<
bool
>
setSemantics
(
bool
enabled
,
{
Duration
timeout
})
async
{
Future
<
bool
>
setSemantics
(
bool
enabled
,
{
Duration
?
timeout
})
async
{
final
SetSemanticsResult
result
=
SetSemanticsResult
.
fromJson
(
await
sendCommand
(
SetSemantics
(
enabled
,
timeout:
timeout
)));
return
result
.
changedState
;
}
...
...
@@ -527,7 +525,7 @@ abstract class FlutterDriver {
///
/// Semantics must be enabled to use this method, either using a platform
/// specific shell command or [setSemantics].
Future
<
int
>
getSemanticsId
(
SerializableFinder
finder
,
{
Duration
timeout
})
async
{
Future
<
int
>
getSemanticsId
(
SerializableFinder
finder
,
{
Duration
?
timeout
})
async
{
final
Map
<
String
,
dynamic
>
jsonResponse
=
await
sendCommand
(
GetSemanticsId
(
finder
,
timeout:
timeout
));
final
GetSemanticsIdResult
result
=
GetSemanticsIdResult
.
fromJson
(
jsonResponse
);
return
result
.
id
;
...
...
@@ -693,7 +691,7 @@ abstract class FlutterDriver {
/// With frame sync disabled, it's the responsibility of the test author to
/// ensure that no action is performed while the app is undergoing a
/// transition to avoid flakiness.
Future
<
T
>
runUnsynchronized
<
T
>(
Future
<
T
>
action
(),
{
Duration
timeout
})
async
{
Future
<
T
>
runUnsynchronized
<
T
>(
Future
<
T
>
action
(),
{
Duration
?
timeout
})
async
{
await
sendCommand
(
SetFrameSync
(
false
,
timeout:
timeout
));
T
result
;
try
{
...
...
@@ -750,8 +748,8 @@ class CommonFinders {
/// If `firstMatchOnly` is true then only the first ancestor matching
/// `matching` will be returned. Defaults to false.
SerializableFinder
ancestor
({
@
required
SerializableFinder
of
,
@
required
SerializableFinder
matching
,
required
SerializableFinder
of
,
required
SerializableFinder
matching
,
bool
matchRoot
=
false
,
bool
firstMatchOnly
=
false
,
})
=>
Ancestor
(
of:
of
,
matching:
matching
,
matchRoot:
matchRoot
,
firstMatchOnly:
firstMatchOnly
);
...
...
@@ -765,8 +763,8 @@ class CommonFinders {
/// If `firstMatchOnly` is true then only the first descendant matching
/// `matching` will be returned. Defaults to false.
SerializableFinder
descendant
({
@
required
SerializableFinder
of
,
@
required
SerializableFinder
matching
,
required
SerializableFinder
of
,
required
SerializableFinder
matching
,
bool
matchRoot
=
false
,
bool
firstMatchOnly
=
false
,
})
=>
Descendant
(
of:
of
,
matching:
matching
,
matchRoot:
matchRoot
,
firstMatchOnly:
firstMatchOnly
);
...
...
packages/flutter_driver/lib/src/driver/percentile_utils.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Returns the [p]-th percentile element from the [doubles].
/// `List<doubles>` will be sorted.
double
findPercentile
(
List
<
double
>
doubles
,
double
p
)
{
...
...
packages/flutter_driver/lib/src/driver/profiling_summarizer.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'percentile_utils.dart'
;
import
'timeline.dart'
;
...
...
@@ -63,7 +61,7 @@ class ProfilingSummarizer {
assert
(
kProfilingEvents
.
contains
(
event
.
name
));
final
ProfileType
type
=
_getProfileType
(
event
.
name
);
eventsByType
[
type
]
??=
<
TimelineEvent
>[];
eventsByType
[
type
].
add
(
event
);
eventsByType
[
type
]
!
.
add
(
event
);
}
return
ProfilingSummarizer
.
_
(
eventsByType
);
}
...
...
@@ -96,7 +94,7 @@ class ProfilingSummarizer {
/// Returns true if there are events in the timeline corresponding to [profileType].
bool
hasProfilingInfo
(
ProfileType
profileType
)
{
if
(
eventByType
.
containsKey
(
profileType
))
{
return
eventByType
[
profileType
].
isNotEmpty
;
return
eventByType
[
profileType
]
!
.
isNotEmpty
;
}
else
{
return
false
;
}
...
...
@@ -104,7 +102,7 @@ class ProfilingSummarizer {
/// Computes the average of the `profileType` over the recorded events.
double
computeAverage
(
ProfileType
profileType
)
{
final
List
<
TimelineEvent
>
events
=
eventByType
[
profileType
];
final
List
<
TimelineEvent
>
events
=
eventByType
[
profileType
]
!
;
assert
(
events
.
isNotEmpty
);
final
double
total
=
events
.
map
((
TimelineEvent
e
)
=>
_getProfileValue
(
profileType
,
e
))
...
...
@@ -114,7 +112,7 @@ class ProfilingSummarizer {
/// The [percentile]-th percentile `profileType` over the recorded events.
double
computePercentile
(
ProfileType
profileType
,
double
percentile
)
{
final
List
<
TimelineEvent
>
events
=
eventByType
[
profileType
];
final
List
<
TimelineEvent
>
events
=
eventByType
[
profileType
]
!
;
assert
(
events
.
isNotEmpty
);
final
List
<
double
>
doubles
=
events
.
map
((
TimelineEvent
e
)
=>
_getProfileValue
(
profileType
,
e
))
...
...
@@ -122,7 +120,7 @@ class ProfilingSummarizer {
return
findPercentile
(
doubles
,
percentile
);
}
static
ProfileType
_getProfileType
(
String
eventName
)
{
static
ProfileType
_getProfileType
(
String
?
eventName
)
{
switch
(
eventName
)
{
case
_kCpuProfile:
return
ProfileType
.
CPU
;
...
...
@@ -147,13 +145,11 @@ class ProfilingSummarizer {
_getArgValue
(
'owned_shared_memory_usage'
,
e
);
return
dirtyMem
+
ownedSharedMem
;
}
throw
Exception
(
'Invalid
$profileType
.'
);
}
double
_getArgValue
(
String
argKey
,
TimelineEvent
e
)
{
assert
(
e
.
arguments
.
containsKey
(
argKey
));
final
dynamic
argVal
=
e
.
arguments
[
argKey
];
assert
(
e
.
arguments
!
.
containsKey
(
argKey
));
final
dynamic
argVal
=
e
.
arguments
!
[
argKey
];
assert
(
argVal
is
String
);
return
double
.
parse
(
argVal
as
String
);
}
...
...
packages/flutter_driver/lib/src/driver/scene_display_lag_summarizer.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'percentile_utils.dart'
;
import
'timeline.dart'
;
...
...
@@ -68,8 +66,8 @@ class SceneDisplayLagSummarizer {
double
_getVsyncTransitionsMissed
(
TimelineEvent
e
)
{
assert
(
e
.
name
==
kSceneDisplayLagEvent
);
assert
(
e
.
arguments
.
containsKey
(
_kVsyncTransitionsMissed
));
final
dynamic
transitionsMissed
=
e
.
arguments
[
_kVsyncTransitionsMissed
];
assert
(
e
.
arguments
!
.
containsKey
(
_kVsyncTransitionsMissed
));
final
dynamic
transitionsMissed
=
e
.
arguments
!
[
_kVsyncTransitionsMissed
];
assert
(
transitionsMissed
is
String
);
return
double
.
parse
(
transitionsMissed
as
String
);
}
...
...
packages/flutter_driver/lib/src/driver/timeline.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Timeline data recorded by the Flutter runtime.
class
Timeline
{
/// Creates a timeline given JSON-encoded timeline data.
...
...
@@ -25,27 +23,29 @@ class Timeline {
///
/// This is parsed from "traceEvents" data within [json] and sorted by
/// timestamp. Anything without a valid timestamp is put in the beginning.
final
List
<
TimelineEvent
>
events
;
///
/// This will be null if there are are no "traceEvents" in the [json].
final
List
<
TimelineEvent
>?
events
;
}
/// A single timeline event.
class
TimelineEvent
{
/// Creates a timeline event given JSON-encoded event data.
TimelineEvent
(
this
.
json
)
:
name
=
json
[
'name'
]
as
String
,
category
=
json
[
'cat'
]
as
String
,
phase
=
json
[
'ph'
]
as
String
,
processId
=
json
[
'pid'
]
as
int
,
threadId
=
json
[
'tid'
]
as
int
,
:
name
=
json
[
'name'
]
as
String
?
,
category
=
json
[
'cat'
]
as
String
?
,
phase
=
json
[
'ph'
]
as
String
?
,
processId
=
json
[
'pid'
]
as
int
?
,
threadId
=
json
[
'tid'
]
as
int
?
,
duration
=
json
[
'dur'
]
!=
null
?
Duration
(
microseconds:
json
[
'dur'
]
as
int
)
:
null
,
threadDuration
=
json
[
'tdur'
]
!=
null
?
Duration
(
microseconds:
json
[
'tdur'
]
as
int
)
:
null
,
timestampMicros
=
json
[
'ts'
]
as
int
,
threadTimestampMicros
=
json
[
'tts'
]
as
int
,
arguments
=
json
[
'args'
]
as
Map
<
String
,
dynamic
>;
timestampMicros
=
json
[
'ts'
]
as
int
?
,
threadTimestampMicros
=
json
[
'tts'
]
as
int
?
,
arguments
=
json
[
'args'
]
as
Map
<
String
,
dynamic
>
?
;
/// The original event JSON.
final
Map
<
String
,
dynamic
>
json
;
...
...
@@ -53,28 +53,28 @@ class TimelineEvent {
/// The name of the event.
///
/// Corresponds to the "name" field in the JSON event.
final
String
name
;
final
String
?
name
;
/// Event category. Events with different names may share the same category.
///
/// Corresponds to the "cat" field in the JSON event.
final
String
category
;
final
String
?
category
;
/// For a given long lasting event, denotes the phase of the event, such as
/// "B" for "event began", and "E" for "event ended".
///
/// Corresponds to the "ph" field in the JSON event.
final
String
phase
;
final
String
?
phase
;
/// ID of process that emitted the event.
///
/// Corresponds to the "pid" field in the JSON event.
final
int
processId
;
final
int
?
processId
;
/// ID of thread that issues the event.
///
/// Corresponds to the "tid" field in the JSON event.
final
int
threadId
;
final
int
?
threadId
;
/// The duration of the event.
///
...
...
@@ -82,7 +82,7 @@ class TimelineEvent {
/// pair of begin/end events.
///
/// Corresponds to the "dur" field in the JSON event.
final
Duration
duration
;
final
Duration
?
duration
;
/// The thread duration of the event.
///
...
...
@@ -90,32 +90,31 @@ class TimelineEvent {
/// pair of begin/end events.
///
/// Corresponds to the "tdur" field in the JSON event.
final
Duration
threadDuration
;
final
Duration
?
threadDuration
;
/// Time passed since tracing was enabled, in microseconds.
///
/// Corresponds to the "ts" field in the JSON event.
final
int
timestampMicros
;
final
int
?
timestampMicros
;
/// Thread clock time, in microseconds.
///
/// Corresponds to the "tts" field in the JSON event.
final
int
threadTimestampMicros
;
final
int
?
threadTimestampMicros
;
/// Arbitrary data attached to the event.
///
/// Corresponds to the "args" field in the JSON event.
final
Map
<
String
,
dynamic
>
arguments
;
final
Map
<
String
,
dynamic
>
?
arguments
;
}
List
<
TimelineEvent
>
_parseEvents
(
Map
<
String
,
dynamic
>
json
)
{
final
List
<
dynamic
>
jsonEvents
=
json
[
'traceEvents'
]
as
List
<
dynamic
>
;
List
<
TimelineEvent
>
?
_parseEvents
(
Map
<
String
,
dynamic
>
json
)
{
final
List
<
dynamic
>
?
jsonEvents
=
json
[
'traceEvents'
]
as
List
<
dynamic
>?
;
if
(
jsonEvents
==
null
)
{
return
null
;
}
// TODO(vegorov): use instance method version of castFrom when it is available.
final
List
<
TimelineEvent
>
timelineEvents
=
Iterable
.
castFrom
<
dynamic
,
Map
<
String
,
dynamic
>>(
jsonEvents
)
.
map
<
TimelineEvent
>(
...
...
@@ -123,8 +122,8 @@ List<TimelineEvent> _parseEvents(Map<String, dynamic> json) {
.
toList
();
timelineEvents
.
sort
((
TimelineEvent
e1
,
TimelineEvent
e2
)
{
final
int
ts1
=
e1
.
timestampMicros
;
final
int
ts2
=
e2
.
timestampMicros
;
final
int
?
ts1
=
e1
.
timestampMicros
;
final
int
?
ts2
=
e2
.
timestampMicros
;
if
(
ts1
==
null
)
{
if
(
ts2
==
null
)
{
return
0
;
...
...
packages/flutter_driver/lib/src/driver/timeline_summary.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:convert'
show
json
,
JsonEncoder
;
import
'dart:math'
as
math
;
...
...
@@ -197,7 +195,7 @@ class TimelineSummary {
/// * [Timeline.fromJson], which explains detail about the timeline data.
Future
<
void
>
writeTimelineToFile
(
String
traceName
,
{
String
destinationDirectory
,
String
?
destinationDirectory
,
bool
pretty
=
false
,
})
async
{
destinationDirectory
??=
testOutputsDirectory
;
...
...
@@ -209,7 +207,7 @@ class TimelineSummary {
/// Writes [summaryJson] to a file.
Future
<
void
>
writeSummaryToFile
(
String
traceName
,
{
String
destinationDirectory
,
String
?
destinationDirectory
,
bool
pretty
=
false
,
})
async
{
destinationDirectory
??=
testOutputsDirectory
;
...
...
@@ -225,13 +223,13 @@ class TimelineSummary {
}
List
<
TimelineEvent
>
_extractNamedEvents
(
String
name
)
{
return
_timeline
.
events
return
_timeline
.
events
!
.
where
((
TimelineEvent
event
)
=>
event
.
name
==
name
)
.
toList
();
}
List
<
TimelineEvent
>
_extractEventsWithNames
(
Set
<
String
>
names
)
{
return
_timeline
.
events
return
_timeline
.
events
!
.
where
((
TimelineEvent
event
)
=>
names
.
contains
(
event
.
name
))
.
toList
();
}
...
...
@@ -244,7 +242,7 @@ class TimelineSummary {
final
List
<
TimelineEvent
>
events
=
_extractNamedEvents
(
name
);
// Timeline does not guarantee that the first event is the "begin" event.
TimelineEvent
begin
;
TimelineEvent
?
begin
;
for
(
final
TimelineEvent
event
in
events
)
{
if
(
event
.
phase
==
'B'
)
{
begin
=
event
;
...
...
@@ -273,7 +271,7 @@ class TimelineSummary {
return
_extractDurations
(
name
,
(
TimelineEvent
beginEvent
,
TimelineEvent
endEvent
)
{
return
Duration
(
microseconds:
endEvent
.
timestampMicros
-
beginEvent
.
timestampMicros
);
return
Duration
(
microseconds:
endEvent
.
timestampMicros
!
-
beginEvent
.
timestampMicros
!
);
},
);
}
...
...
@@ -282,7 +280,7 @@ class TimelineSummary {
final
List
<
Duration
>
result
=
_extractDurations
(
name
,
(
TimelineEvent
beginEvent
,
TimelineEvent
endEvent
)
{
return
Duration
(
microseconds:
beginEvent
.
timestampMicros
);
return
Duration
(
microseconds:
beginEvent
.
timestampMicros
!
);
},
);
...
...
packages/flutter_driver/lib/src/driver/vmservice_driver.dart
View file @
3ece9c63
...
...
@@ -2,15 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:file/file.dart'
as
f
;
import
'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart'
as
fuchsia
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
p
;
import
'package:vm_service/vm_service.dart'
as
vms
;
import
'package:webdriver/async_io.dart'
as
async_io
;
...
...
@@ -41,12 +38,12 @@ class VMServiceFlutterDriver extends FlutterDriver {
///
/// See [FlutterDriver.connect] for more documentation.
static
Future
<
FlutterDriver
>
connect
({
String
dartVmServiceUrl
,
String
?
dartVmServiceUrl
,
bool
printCommunication
=
false
,
bool
logCommunicationToFile
=
true
,
int
isolateNumber
,
Pattern
fuchsiaModuleTarget
,
Map
<
String
,
dynamic
>
headers
,
int
?
isolateNumber
,
Pattern
?
fuchsiaModuleTarget
,
Map
<
String
,
dynamic
>
?
headers
,
})
async
{
// If running on a Fuchsia device, connect to the first isolate whose name
// matches FUCHSIA_MODULE_TARGET.
...
...
@@ -93,32 +90,32 @@ class VMServiceFlutterDriver extends FlutterDriver {
_log
(
'Connecting to Flutter application at
$dartVmServiceUrl
'
);
final
vms
.
VmService
client
=
await
vmServiceConnectFunction
(
dartVmServiceUrl
,
headers
);
Future
<
vms
.
IsolateRef
>
_waitForRootIsolate
()
async
{
Future
<
vms
.
IsolateRef
?
>
_waitForRootIsolate
()
async
{
bool
_checkIsolate
(
vms
.
IsolateRef
ref
)
=>
ref
.
number
==
isolateNumber
.
toString
();
while
(
true
)
{
final
vms
.
VM
vm
=
await
client
.
getVM
();
if
(
vm
.
isolates
.
isEmpty
||
(
isolateNumber
!=
null
&&
!
vm
.
isolates
.
any
(
_checkIsolate
)))
{
if
(
vm
.
isolates
!.
isEmpty
||
(
isolateNumber
!=
null
&&
!
vm
.
isolates
!
.
any
(
_checkIsolate
)))
{
await
Future
<
void
>.
delayed
(
_kPauseBetweenReconnectAttempts
);
continue
;
}
return
isolateNumber
==
null
?
vm
.
isolates
.
first
:
vm
.
isolates
.
firstWhere
(
_checkIsolate
);
?
vm
.
isolates
!
.
first
:
vm
.
isolates
!
.
firstWhere
(
_checkIsolate
);
}
}
final
vms
.
IsolateRef
isolateRef
=
await
_warnIfSlow
<
vms
.
IsolateRef
>(
final
vms
.
IsolateRef
isolateRef
=
(
await
_warnIfSlow
<
vms
.
IsolateRef
?
>(
future:
_waitForRootIsolate
(),
timeout:
kUnusuallyLongTimeout
,
message:
isolateNumber
==
null
?
'The root isolate is taking an unuusally long time to start.'
:
'Isolate
$isolateNumber
is taking an unusually long time to start.'
,
);
)
)!
;
_log
(
'Isolate found with number:
${isolateRef.number}
'
);
vms
.
Isolate
isolate
=
await
client
.
getIsolate
(
isolateRef
.
id
);
vms
.
Isolate
isolate
=
await
client
.
getIsolate
(
isolateRef
.
id
!
);
if
(
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kNone
)
{
isolate
=
await
client
.
getIsolate
(
isolateRef
.
id
);
if
(
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kNone
)
{
isolate
=
await
client
.
getIsolate
(
isolateRef
.
id
!
);
}
final
VMServiceFlutterDriver
driver
=
VMServiceFlutterDriver
.
connectedTo
(
...
...
@@ -143,7 +140,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
_log
(
'Failed to set pause_isolates_on_start=false, proceeding. Error:
$e
'
);
}
return
client
.
resume
(
isolate
.
id
).
catchError
((
dynamic
e
)
{
return
client
.
resume
(
isolate
.
id
!).
catchError
((
Object
e
)
{
const
int
vmMustBePausedCode
=
101
;
if
(
e
is
vms
.
RPCError
&&
e
.
code
==
vmMustBePausedCode
)
{
// No biggie; something else must have resumed the isolate
...
...
@@ -167,9 +164,9 @@ class VMServiceFlutterDriver extends FlutterDriver {
await
client
.
streamListen
(
vms
.
EventStreams
.
kIsolate
);
final
Future
<
void
>
extensionAlreadyAdded
=
client
.
getIsolate
(
isolateRef
.
id
)
.
getIsolate
(
isolateRef
.
id
!
)
.
then
((
vms
.
Isolate
isolate
)
async
{
if
(
isolate
.
extensionRPCs
.
contains
(
_flutterExtensionMethodName
))
{
if
(
isolate
.
extensionRPCs
!
.
contains
(
_flutterExtensionMethodName
))
{
return
;
}
// Never complete. Rely on the stream listener to find the service
...
...
@@ -178,7 +175,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
});
final
Completer
<
void
>
extensionAdded
=
Completer
<
void
>();
StreamSubscription
<
vms
.
Event
>
isolateAddedSubscription
;
late
StreamSubscription
<
vms
.
Event
>
isolateAddedSubscription
;
isolateAddedSubscription
=
client
.
onIsolateEvent
.
listen
(
(
vms
.
Event
data
)
{
...
...
@@ -200,19 +197,19 @@ class VMServiceFlutterDriver extends FlutterDriver {
}
// Attempt to resume isolate if it was paused
if
(
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kPauseStart
)
{
if
(
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kPauseStart
)
{
_log
(
'Isolate is paused at start.'
);
await
resumeLeniently
();
}
else
if
(
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kPauseExit
||
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kPauseBreakpoint
||
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kPauseException
||
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kPauseInterrupted
)
{
}
else
if
(
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kPauseExit
||
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kPauseBreakpoint
||
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kPauseException
||
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kPauseInterrupted
)
{
// If the isolate is paused for any other reason, assume the extension is
// already there.
_log
(
'Isolate is paused mid-flight.'
);
await
resumeLeniently
();
}
else
if
(
isolate
.
pauseEvent
.
kind
==
vms
.
EventKind
.
kResume
)
{
}
else
if
(
isolate
.
pauseEvent
!
.
kind
==
vms
.
EventKind
.
kResume
)
{
_log
(
'Isolate is not paused. Assuming application is ready.'
);
}
else
{
_log
(
...
...
@@ -306,7 +303,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
@override
Future
<
Map
<
String
,
dynamic
>>
sendCommand
(
Command
command
)
async
{
Map
<
String
,
dynamic
>
response
;
late
Map
<
String
,
dynamic
>
response
;
try
{
final
Map
<
String
,
String
>
serialized
=
command
.
serialize
();
_logCommunication
(
'>>>
$serialized
'
);
...
...
@@ -314,12 +311,12 @@ class VMServiceFlutterDriver extends FlutterDriver {
_flutterExtensionMethodName
,
isolateId:
_appIsolate
.
id
,
args:
serialized
,
).
then
<
Map
<
String
,
dynamic
>>((
vms
.
Response
value
)
=>
value
.
json
);
response
=
await
_warnIfSlow
<
Map
<
String
,
dynamic
>>(
).
then
<
Map
<
String
,
dynamic
>>((
vms
.
Response
value
)
=>
value
.
json
!
);
response
=
(
await
_warnIfSlow
<
Map
<
String
,
dynamic
>>(
future:
future
,
timeout:
command
.
timeout
??
kUnusuallyLongTimeout
,
message:
'
${command.kind}
message is taking a long time to complete...'
,
);
)
)!
;
_logCommunication
(
'<<<
$response
'
);
}
catch
(
error
,
stackTrace
)
{
throw
DriverError
(
...
...
@@ -328,7 +325,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
stackTrace
,
);
}
if
(
response
[
'isError'
]
as
bool
)
if
(
(
response
[
'isError'
]
as
bool
?)
==
true
)
throw
DriverError
(
'Error in Flutter application:
${response['response']}
'
);
return
response
[
'response'
]
as
Map
<
String
,
dynamic
>;
}
...
...
@@ -348,14 +345,14 @@ class VMServiceFlutterDriver extends FlutterDriver {
await
Future
<
void
>.
delayed
(
const
Duration
(
seconds:
2
));
final
vms
.
Response
result
=
await
_serviceClient
.
callMethod
(
'_flutter.screenshot'
);
return
base64
.
decode
(
result
.
json
[
'screenshot'
]
as
String
);
return
base64
.
decode
(
result
.
json
!
[
'screenshot'
]
as
String
);
}
@override
Future
<
List
<
Map
<
String
,
dynamic
>>>
getVmFlags
()
async
{
final
vms
.
FlagList
result
=
await
_serviceClient
.
getFlagList
();
return
result
!=
null
?
result
.
flags
.
map
((
vms
.
Flag
flag
)
=>
flag
.
toJson
()).
toList
()
return
result
.
flags
!=
null
?
result
.
flags
!
.
map
((
vms
.
Flag
flag
)
=>
flag
.
toJson
()).
toList
()
:
const
<
Map
<
String
,
dynamic
>>[];
}
...
...
@@ -390,8 +387,8 @@ class VMServiceFlutterDriver extends FlutterDriver {
@override
Future
<
Timeline
>
stopTracingAndDownloadTimeline
({
Duration
timeout
=
kUnusuallyLongTimeout
,
int
startTime
,
int
endTime
,
int
?
startTime
,
int
?
endTime
,
})
async
{
assert
(
timeout
!=
null
);
assert
((
startTime
==
null
&&
endTime
==
null
)
||
...
...
@@ -405,12 +402,12 @@ class VMServiceFlutterDriver extends FlutterDriver {
);
if
(
startTime
==
null
)
{
final
vms
.
Timeline
timeline
=
await
_serviceClient
.
getVMTimeline
();
return
Timeline
.
fromJson
(
timeline
.
json
);
return
Timeline
.
fromJson
(
timeline
.
json
!
);
}
const
int
kSecondInMicros
=
1000000
;
int
currentStart
=
startTime
;
int
currentEnd
=
startTime
+
kSecondInMicros
;
// 1 second of timeline
final
List
<
Map
<
String
,
Object
>>
chunks
=
<
Map
<
String
,
Object
>
>[];
final
List
<
Map
<
String
,
Object
?>?>
chunks
=
<
Map
<
String
,
Object
>?
>[];
do
{
final
vms
.
Timeline
chunk
=
await
_serviceClient
.
getVMTimeline
(
timeOriginMicros:
currentStart
,
...
...
@@ -421,11 +418,11 @@ class VMServiceFlutterDriver extends FlutterDriver {
chunks
.
add
(
chunk
.
json
);
currentStart
=
currentEnd
;
currentEnd
+=
kSecondInMicros
;
}
while
(
currentStart
<
endTime
);
}
while
(
currentStart
<
endTime
!
);
return
Timeline
.
fromJson
(<
String
,
Object
>{
'traceEvents'
:
<
Object
>
[
for
(
Map
<
String
,
Object
>
chunk
in
chunks
)
...
chunk
[
'traceEvents'
]
as
List
<
Object
>,
for
(
Map
<
String
,
Object
?>?
chunk
in
chunks
)
...
chunk
![
'traceEvents'
]!
as
List
<
Object
>,
],
});
}
catch
(
error
,
stackTrace
)
{
...
...
@@ -502,7 +499,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
}
@override
Future
<
T
>
runUnsynchronized
<
T
>(
Future
<
T
>
action
(),
{
Duration
timeout
})
async
{
Future
<
T
>
runUnsynchronized
<
T
>(
Future
<
T
>
action
(),
{
Duration
?
timeout
})
async
{
await
sendCommand
(
SetFrameSync
(
false
,
timeout:
timeout
));
T
result
;
try
{
...
...
@@ -560,10 +557,10 @@ String _getWebSocketUrl(String url) {
/// Waits for a real Dart VM service to become available, then connects using
/// the [VMServiceClient].
Future
<
vms
.
VmService
>
_waitAndConnect
(
String
url
,
Map
<
String
,
dynamic
>
headers
)
async
{
Future
<
vms
.
VmService
>
_waitAndConnect
(
String
url
,
Map
<
String
,
dynamic
>
?
headers
)
async
{
final
String
webSocketUrl
=
_getWebSocketUrl
(
url
);
int
attempts
=
0
;
WebSocket
socket
;
late
WebSocket
socket
;
while
(
true
)
{
try
{
socket
=
await
WebSocket
.
connect
(
webSocketUrl
,
headers:
headers
);
...
...
@@ -585,7 +582,7 @@ Future<vms.VmService> _waitAndConnect(String url, Map<String, dynamic> headers)
await
service
.
getVersion
();
return
service
;
}
catch
(
e
)
{
await
socket
?
.
close
();
await
socket
.
close
();
if
(
attempts
>
5
)
{
_log
(
'It is taking an unusually long time to connect to the VM...'
);
}
...
...
@@ -623,10 +620,11 @@ List<String> _timelineStreamsToString(List<TimelineStream> streams) {
void
_log
(
String
message
)
{
driverLog
(
'VMServiceFlutterDriver'
,
message
);
}
Future
<
T
>
_warnIfSlow
<
T
>({
@required
Future
<
T
>
future
,
@required
Duration
timeout
,
@required
String
message
,
Future
<
T
?>
_warnIfSlow
<
T
>({
required
Future
<
T
?>
future
,
required
Duration
timeout
,
required
String
message
,
})
{
assert
(
future
!=
null
);
assert
(
timeout
!=
null
);
...
...
@@ -637,10 +635,10 @@ Future<T> _warnIfSlow<T>({
return
null
;
})
// Don't duplicate errors if [future] completes with an error.
.
catchError
((
dynamic
e
)
=>
null
);
.
catchError
((
Object
e
,
StackTrace
s
)
=>
null
);
return
future
;
}
/// A function that connects to a Dart VM service given the `url` and `headers`.
typedef
VMServiceConnectFunction
=
Future
<
vms
.
VmService
>
Function
(
String
url
,
Map
<
String
,
dynamic
>
headers
);
typedef
VMServiceConnectFunction
=
Future
<
vms
.
VmService
>
Function
(
String
url
,
Map
<
String
,
dynamic
>
?
headers
);
packages/flutter_driver/lib/src/driver/web_driver.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:convert'
;
import
'dart:io'
;
...
...
@@ -53,7 +51,7 @@ class WebFlutterDriver extends FlutterDriver {
/// DRIVER_SESSION_CAPABILITIES and ANDROID_CHROME_ON_EMULATOR for
/// configurations.
static
Future
<
FlutterDriver
>
connectWeb
(
{
String
hostUrl
,
Duration
timeout
})
async
{
{
String
?
hostUrl
,
Duration
?
timeout
})
async
{
hostUrl
??=
Platform
.
environment
[
'VM_SERVICE_URL'
];
final
Map
<
String
,
dynamic
>
settings
=
<
String
,
dynamic
>{
'support-timeline-action'
:
Platform
.
environment
[
'SUPPORT_TIMELINE_ACTION'
]
==
'true'
,
...
...
@@ -64,7 +62,7 @@ class WebFlutterDriver extends FlutterDriver {
'session-capabilities'
:
Platform
.
environment
[
'DRIVER_SESSION_CAPABILITIES'
],
};
final
FlutterWebConnection
connection
=
await
FlutterWebConnection
.
connect
(
hostUrl
,
settings
,
timeout:
timeout
);
(
hostUrl
!
,
settings
,
timeout:
timeout
);
return
WebFlutterDriver
.
connectedTo
(
connection
);
}
...
...
@@ -90,7 +88,7 @@ class WebFlutterDriver extends FlutterDriver {
final
Map
<
String
,
String
>
serialized
=
command
.
serialize
();
try
{
final
dynamic
data
=
await
_connection
.
sendCommand
(
"window.
\
$flutterDriver
('
${jsonEncode(serialized)}
')"
,
command
.
timeout
);
response
=
data
!=
null
?
json
.
decode
(
data
as
String
)
as
Map
<
String
,
dynamic
>
:
<
String
,
dynamic
>{};
response
=
data
!=
null
?
(
json
.
decode
(
data
as
String
)
as
Map
<
String
,
dynamic
>?)!
:
<
String
,
dynamic
>{};
}
catch
(
error
,
stackTrace
)
{
throw
DriverError
(
"Failed to respond to
$command
due to remote error
\n
:
\
$flutterDriver
('
${jsonEncode(serialized)}
')"
,
error
,
...
...
@@ -132,7 +130,7 @@ class WebFlutterDriver extends FlutterDriver {
final
List
<
Map
<
String
,
dynamic
>>
events
=
<
Map
<
String
,
dynamic
>>[];
for
(
final
async_io
.
LogEntry
entry
in
await
_connection
.
logs
.
toList
())
{
if
(
_startTime
.
isBefore
(
entry
.
timestamp
))
{
final
Map
<
String
,
dynamic
>
data
=
jsonDecode
(
entry
.
message
)[
'message'
]
as
Map
<
String
,
dynamic
>;
final
Map
<
String
,
dynamic
>
data
=
jsonDecode
(
entry
.
message
!
)[
'message'
]
as
Map
<
String
,
dynamic
>;
if
(
data
[
'method'
]
==
'Tracing.dataCollected'
)
{
// 'ts' data collected from Chrome is in double format, conversion needed
try
{
...
...
@@ -142,7 +140,7 @@ class WebFlutterDriver extends FlutterDriver {
// data is corrupted, skip
continue
;
}
events
.
add
(
data
[
'params'
]
as
Map
<
String
,
dynamic
>);
events
.
add
(
data
[
'params'
]
!
as
Map
<
String
,
dynamic
>);
}
}
}
...
...
@@ -203,7 +201,7 @@ class FlutterWebConnection {
static
Future
<
FlutterWebConnection
>
connect
(
String
url
,
Map
<
String
,
dynamic
>
settings
,
{
Duration
timeout
})
async
{
{
Duration
?
timeout
})
async
{
final
String
sessionId
=
settings
[
'session-id'
].
toString
();
final
Uri
sessionUri
=
Uri
.
parse
(
settings
[
'session-uri'
].
toString
());
final
async_io
.
WebDriver
driver
=
async_io
.
WebDriver
(
...
...
@@ -226,7 +224,7 @@ class FlutterWebConnection {
}
/// Sends command via WebDriver to Flutter web application.
Future
<
dynamic
>
sendCommand
(
String
script
,
Duration
duration
)
async
{
Future
<
dynamic
>
sendCommand
(
String
script
,
Duration
?
duration
)
async
{
dynamic
result
;
try
{
await
_driver
.
execute
(
script
,
<
void
>[]);
...
...
@@ -265,7 +263,7 @@ class FlutterWebConnection {
}
/// Waits until extension is installed.
Future
<
void
>
waitUntilExtensionInstalled
(
async_io
.
WebDriver
driver
,
Duration
timeout
)
async
{
Future
<
void
>
waitUntilExtensionInstalled
(
async_io
.
WebDriver
driver
,
Duration
?
timeout
)
async
{
await
waitFor
<
void
>(()
=>
driver
.
execute
(
r'return typeof(window.$flutterDriver)'
,
<
String
>[]),
matcher:
'function'
,
...
...
packages/flutter_driver/pubspec.yaml
View file @
3ece9c63
...
...
@@ -8,16 +8,16 @@ environment:
dependencies
:
file
:
6.0.0-nullsafety.4
meta
:
1.3.0-nullsafety.6
path
:
1.8.0-nullsafety.3
vm_service
:
6.0.1-nullsafety.0
webdriver
:
3.0.0-nullsafety.1
flutter
:
sdk
:
flutter
flutter_test
:
sdk
:
flutter
fuchsia_remote_debug_protocol
:
sdk
:
flutter
path
:
1.8.0-nullsafety.3
meta
:
1.3.0-nullsafety.6
vm_service
:
6.0.1-nullsafety.0
webdriver
:
3.0.0-nullsafety.1
archive
:
3.0.0-nullsafety.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
async
:
2.5.0-nullsafety.3
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
...
...
@@ -27,7 +27,6 @@ dependencies:
clock
:
1.1.0-nullsafety.3
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
collection
:
1.15.0-nullsafety.5
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
crypto
:
3.0.0-nullsafety.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
fake_async
:
1.2.0-nullsafety.3
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
matcher
:
0.12.10-nullsafety.3
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
platform
:
3.0.0-nullsafety.4
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
process
:
4.0.0-nullsafety.4
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
...
...
@@ -42,7 +41,7 @@ dependencies:
vector_math
:
2.1.0-nullsafety.5
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies
:
quiver
:
2.1.5
fake_async
:
1.2.0-nullsafety.3
test
:
1.16.0-nullsafety.16
_fe_analyzer_shared
:
14.0.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
...
...
@@ -77,4 +76,4 @@ dev_dependencies:
webkit_inspection_protocol
:
0.7.4
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
yaml
:
2.2.1
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
# PUBSPEC CHECKSUM:
91b1
# PUBSPEC CHECKSUM:
62c3
packages/flutter_driver/test/common.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'package:flutter_driver/src/common/error.dart'
;
...
...
packages/flutter_driver/test/flutter_driver_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:convert'
;
...
...
@@ -13,8 +11,8 @@ import 'package:flutter_driver/src/common/layer_tree.dart';
import
'package:flutter_driver/src/common/wait.dart'
;
import
'package:flutter_driver/src/driver/driver.dart'
;
import
'package:flutter_driver/src/driver/timeline.dart'
;
import
'package:fake_async/fake_async.dart'
;
import
'package:vm_service/vm_service.dart'
as
vms
;
import
'package:quiver/testing/async.dart'
;
import
'common.dart'
;
...
...
@@ -31,9 +29,9 @@ void main() {
};
group
(
'VMServiceFlutterDriver.connect'
,
()
{
FakeVmService
fakeClient
;
FakeVM
fakeVM
;
FakeIsolate
fakeIsolate
;
late
FakeVmService
fakeClient
;
late
FakeVM
fakeVM
;
late
FakeIsolate
fakeIsolate
;
void
expectLogContains
(
String
message
)
{
expect
(
log
,
anyElement
(
contains
(
message
)));
...
...
@@ -44,7 +42,7 @@ void main() {
fakeIsolate
=
FakeIsolate
();
fakeVM
=
FakeVM
(
fakeIsolate
);
fakeClient
=
FakeVmService
(
fakeVM
);
vmServiceConnectFunction
=
(
String
url
,
Map
<
String
,
dynamic
>
headers
)
async
{
vmServiceConnectFunction
=
(
String
url
,
Map
<
String
,
dynamic
>
?
headers
)
async
{
return
fakeClient
;
};
fakeClient
.
responses
[
'get_health'
]
=
makeFakeResponse
(<
String
,
dynamic
>{
'status'
:
'ok'
});
...
...
@@ -176,10 +174,10 @@ void main() {
});
group
(
'VMServiceFlutterDriver'
,
()
{
FakeVmService
fakeClient
;
late
FakeVmService
fakeClient
;
FakeVM
fakeVM
;
FakeIsolate
fakeIsolate
;
VMServiceFlutterDriver
driver
;
late
VMServiceFlutterDriver
driver
;
setUp
(()
{
fakeIsolate
=
FakeIsolate
();
...
...
@@ -230,10 +228,6 @@ void main() {
});
group
(
'tap'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
tap
(
null
),
throwsAssertionError
);
});
test
(
'sends the tap command'
,
()
async
{
await
driver
.
tap
(
find
.
text
(
'foo'
),
timeout:
_kTestTimeout
);
expect
(
fakeClient
.
commandLog
,
<
String
>[
...
...
@@ -243,10 +237,6 @@ void main() {
});
group
(
'getText'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
getText
(
null
),
throwsAssertionError
);
});
test
(
'sends the getText command'
,
()
async
{
fakeClient
.
responses
[
'get_text'
]
=
makeFakeResponse
(<
String
,
dynamic
>{
'text'
:
'hello'
});
final
String
result
=
await
driver
.
getText
(
find
.
byValueKey
(
123
),
timeout:
_kTestTimeout
);
...
...
@@ -274,10 +264,6 @@ void main() {
});
group
(
'waitFor'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
waitFor
(
null
),
throwsAssertionError
);
});
test
(
'sends the waitFor command'
,
()
async
{
fakeClient
.
responses
[
'waitFor'
]
=
makeFakeResponse
(<
String
,
dynamic
>{});
await
driver
.
waitFor
(
find
.
byTooltip
(
'foo'
),
timeout:
_kTestTimeout
);
...
...
@@ -363,14 +349,6 @@ void main() {
});
});
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
getCenter
(
null
),
throwsAssertionError
);
expect
(
driver
.
getTopLeft
(
null
),
throwsAssertionError
);
expect
(
driver
.
getTopRight
(
null
),
throwsAssertionError
);
expect
(
driver
.
getBottomLeft
(
null
),
throwsAssertionError
);
expect
(
driver
.
getBottomRight
(
null
),
throwsAssertionError
);
});
test
(
'sends the getCenter command'
,
()
async
{
final
DriverOffset
result
=
await
driver
.
getCenter
(
find
.
byValueKey
(
123
),
timeout:
_kTestTimeout
);
expect
(
result
,
const
DriverOffset
(
11
,
12
));
...
...
@@ -432,7 +410,7 @@ void main() {
'setVMTimelineFlags []'
,
'getVMTimeline null null'
,
]);
expect
(
timeline
.
events
.
single
.
name
,
'test event'
);
expect
(
timeline
.
events
!
.
single
.
name
,
'test event'
);
});
test
(
'with clearing timeline'
,
()
async
{
...
...
@@ -450,7 +428,7 @@ void main() {
'setVMTimelineFlags []'
,
'getVMTimeline 1 999999'
,
]);
expect
(
timeline
.
events
.
single
.
name
,
'test event'
);
expect
(
timeline
.
events
!
.
single
.
name
,
'test event'
);
});
test
(
'with time interval'
,
()
async
{
...
...
@@ -479,7 +457,7 @@ void main() {
'getVMTimeline 1 999999'
,
'getVMTimeline 1000001 999999'
,
]);
expect
(
timeline
.
events
.
map
((
TimelineEvent
event
)
=>
event
.
name
),
<
String
>[
expect
(
timeline
.
events
!
.
map
((
TimelineEvent
event
)
=>
event
.
name
),
<
String
>[
'test event'
,
'test event 2'
,
]);
...
...
@@ -508,7 +486,7 @@ void main() {
'getVMTimeline null null'
]);
expect
(
timeline
.
events
.
single
.
name
,
'test event'
);
expect
(
timeline
.
events
!
.
single
.
name
,
'test event'
);
});
});
...
...
@@ -545,7 +523,7 @@ void main() {
fail
(
'expected an exception'
);
}
catch
(
error
)
{
expect
(
error
,
isA
<
DriverError
>());
expect
(
error
.
message
,
'Error in Flutter application: {message: This is a failure}'
);
expect
(
(
error
as
DriverError
)
.
message
,
'Error in Flutter application: {message: This is a failure}'
);
}
});
...
...
@@ -570,10 +548,10 @@ void main() {
});
group
(
'VMServiceFlutterDriver with custom timeout'
,
()
{
FakeVmService
fakeClient
;
late
FakeVmService
fakeClient
;
FakeVM
fakeVM
;
FakeIsolate
fakeIsolate
;
VMServiceFlutterDriver
driver
;
late
VMServiceFlutterDriver
driver
;
setUp
(()
{
fakeIsolate
=
FakeIsolate
();
...
...
@@ -601,8 +579,8 @@ void main() {
});
group
(
'WebFlutterDriver'
,
()
{
FakeFlutterWebConnection
fakeConnection
;
WebFlutterDriver
driver
;
late
FakeFlutterWebConnection
fakeConnection
;
late
WebFlutterDriver
driver
;
setUp
(()
{
fakeConnection
=
FakeFlutterWebConnection
();
...
...
@@ -648,10 +626,6 @@ void main() {
});
group
(
'tap'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
tap
(
null
),
throwsAssertionError
);
});
test
(
'sends the tap command'
,
()
async
{
fakeConnection
.
responses
[
'tap'
]
=
jsonEncode
(
makeFakeResponse
(<
String
,
dynamic
>{}));
await
driver
.
tap
(
find
.
text
(
'foo'
),
timeout:
_kTestTimeout
);
...
...
@@ -662,10 +636,6 @@ void main() {
});
group
(
'getText'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
getText
(
null
),
throwsAssertionError
);
});
test
(
'sends the getText command'
,
()
async
{
fakeConnection
.
responses
[
'get_text'
]
=
jsonEncode
(
makeFakeResponse
(<
String
,
dynamic
>{
'text'
:
'hello'
}));
final
String
result
=
await
driver
.
getText
(
find
.
byValueKey
(
123
),
timeout:
_kTestTimeout
);
...
...
@@ -677,10 +647,6 @@ void main() {
});
group
(
'waitFor'
,
()
{
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
waitFor
(
null
),
throwsAssertionError
);
});
test
(
'sends the waitFor command'
,
()
async
{
fakeConnection
.
responses
[
'waitFor'
]
=
jsonEncode
(
makeFakeResponse
(<
String
,
dynamic
>{
'text'
:
'hello'
}));
await
driver
.
waitFor
(
find
.
byTooltip
(
'foo'
),
timeout:
_kTestTimeout
);
...
...
@@ -737,13 +703,6 @@ void main() {
'dy'
:
12
,
}));
});
test
(
'requires a target reference'
,
()
async
{
expect
(
driver
.
getCenter
(
null
),
throwsAssertionError
);
expect
(
driver
.
getTopLeft
(
null
),
throwsAssertionError
);
expect
(
driver
.
getTopRight
(
null
),
throwsAssertionError
);
expect
(
driver
.
getBottomLeft
(
null
),
throwsAssertionError
);
expect
(
driver
.
getBottomRight
(
null
),
throwsAssertionError
);
});
test
(
'sends the getCenter command'
,
()
async
{
final
DriverOffset
result
=
await
driver
.
getCenter
(
find
.
byValueKey
(
123
),
timeout:
_kTestTimeout
);
...
...
@@ -824,7 +783,7 @@ void main() {
group
(
'WebFlutterDriver with non-chrome browser'
,
()
{
FakeFlutterWebConnection
fakeConnection
;
WebFlutterDriver
driver
;
late
WebFlutterDriver
driver
;
setUp
(()
{
fakeConnection
=
FakeFlutterWebConnection
();
...
...
@@ -848,15 +807,15 @@ void main() {
/// and return the actual script.
/// script will be in the following format:
// window.flutterDriver('[actual script]')
String
_checkAndEncode
(
dynamic
script
)
{
String
?
_checkAndEncode
(
dynamic
script
)
{
expect
(
script
,
isA
<
String
>());
expect
(
script
.
startsWith
(
_kWebScriptPrefix
),
isTrue
);
expect
(
script
.
endsWith
(
_kWebScriptSuffix
),
isTrue
);
// Strip prefix and suffix
return
script
.
substring
(
_kWebScriptPrefix
.
length
,
script
.
length
-
2
)
as
String
;
return
script
.
substring
(
_kWebScriptPrefix
.
length
,
script
.
length
-
2
)
as
String
?
;
}
vms
.
Response
makeFakeResponse
(
vms
.
Response
?
makeFakeResponse
(
Map
<
String
,
dynamic
>
response
,
{
bool
isError
=
false
,
})
{
...
...
@@ -873,9 +832,9 @@ class FakeFlutterWebConnection extends Fake implements FlutterWebConnection {
Map
<
String
,
dynamic
>
responses
=
<
String
,
dynamic
>{};
List
<
String
>
commandLog
=
<
String
>[];
@override
Future
<
dynamic
>
sendCommand
(
String
script
,
Duration
duration
)
async
{
Future
<
dynamic
>
sendCommand
(
String
script
,
Duration
?
duration
)
async
{
commandLog
.
add
(
'
$script
$duration
'
);
final
Map
<
String
,
dynamic
>
decoded
=
jsonDecode
(
_checkAndEncode
(
script
))
as
Map
<
String
,
dynamic
>;
final
Map
<
String
,
dynamic
>
decoded
=
jsonDecode
(
_checkAndEncode
(
script
)
!
)
as
Map
<
String
,
dynamic
>;
final
dynamic
response
=
responses
[
decoded
[
'command'
]];
assert
(
response
!=
null
,
'Missing
${decoded['command']}
in responses.'
);
return
response
;
...
...
@@ -890,27 +849,27 @@ class FakeFlutterWebConnection extends Fake implements FlutterWebConnection {
class
FakeVmService
extends
Fake
implements
vms
.
VmService
{
FakeVmService
(
this
.
vm
);
FakeVM
vm
;
FakeVM
?
vm
;
bool
failOnSetFlag
=
false
;
bool
failOnResumeWith101
=
false
;
final
List
<
String
>
connectionLog
=
<
String
>[];
@override
Future
<
vms
.
VM
>
getVM
()
async
=>
vm
;
Future
<
vms
.
VM
>
getVM
()
async
=>
vm
!
;
@override
Future
<
vms
.
Isolate
>
getIsolate
(
String
isolateId
)
async
{
connectionLog
.
add
(
'getIsolate'
);
if
(
isolateId
==
vm
.
isolate
.
id
)
{
return
vm
.
isolate
;
if
(
isolateId
==
vm
!.
isolate
!
.
id
)
{
return
vm
!.
isolate
!
;
}
return
null
;
throw
UnimplementedError
(
'getIsolate called with unrecognized
$isolateId
'
)
;
}
@override
Future
<
vms
.
Success
>
resume
(
String
isolateId
,
{
String
step
,
int
frameIndex
})
async
{
assert
(
isolateId
==
vm
.
isolate
.
id
);
Future
<
vms
.
Success
>
resume
(
String
isolateId
,
{
String
?
step
,
int
?
frameIndex
})
async
{
assert
(
isolateId
==
vm
!.
isolate
!
.
id
);
connectionLog
.
add
(
'resume'
);
if
(
failOnResumeWith101
)
{
throw
vms
.
RPCError
(
'resume'
,
101
,
''
);
...
...
@@ -950,15 +909,15 @@ class FakeVmService extends Fake implements vms.VmService {
}
List
<
String
>
commandLog
=
<
String
>[];
Map
<
String
,
vms
.
Response
>
responses
=
<
String
,
vms
.
Response
>{};
Future
<
void
>
artificialExtensionDelay
;
Map
<
String
,
vms
.
Response
?>
responses
=
<
String
,
vms
.
Response
?
>{};
Future
<
void
>
?
artificialExtensionDelay
;
@override
Future
<
vms
.
Response
>
callServiceExtension
(
String
method
,
{
Map
<
dynamic
,
dynamic
>
args
,
String
isolateId
})
async
{
Future
<
vms
.
Response
>
callServiceExtension
(
String
method
,
{
Map
<
dynamic
,
dynamic
>
?
args
,
String
?
isolateId
})
async
{
commandLog
.
add
(
'
$method
$args
'
);
await
artificialExtensionDelay
;
final
vms
.
Response
response
=
responses
[
args
[
'command'
]]
;
final
vms
.
Response
response
=
responses
[
args
![
'command'
]]!
;
assert
(
response
!=
null
,
'Failed to create a response for
${args['command']}
'
);
return
response
;
}
...
...
@@ -993,7 +952,7 @@ class FakeVmService extends Fake implements vms.VmService {
return
vms
.
Success
();
}
final
Map
<
int
,
vms
.
Timeline
>
timelineResponses
=
<
int
,
vms
.
Timeline
>{
final
Map
<
int
,
vms
.
Timeline
?>
timelineResponses
=
<
int
,
vms
.
Timeline
?
>{
1
:
vms
.
Timeline
.
parse
(<
String
,
dynamic
>{
'traceEvents'
:
<
dynamic
>[
<
String
,
dynamic
>{
...
...
@@ -1006,9 +965,9 @@ class FakeVmService extends Fake implements vms.VmService {
};
@override
Future
<
vms
.
Timeline
>
getVMTimeline
({
int
timeOriginMicros
,
int
timeExtentMicros
})
async
{
Future
<
vms
.
Timeline
>
getVMTimeline
({
int
?
timeOriginMicros
,
int
?
timeExtentMicros
})
async
{
connectionLog
.
add
(
'getVMTimeline
$timeOriginMicros
$timeExtentMicros
'
);
final
vms
.
Timeline
timeline
=
timelineResponses
[
timeOriginMicros
??
1
];
final
vms
.
Timeline
timeline
=
timelineResponses
[
timeOriginMicros
??
1
]
!
;
assert
(
timeline
!=
null
,
'Missing entry in timelineResponses[
$timeOriginMicros
]'
);
return
timeline
;
}
...
...
@@ -1025,7 +984,7 @@ class FakeVmService extends Fake implements vms.VmService {
class
FakeVM
extends
Fake
implements
vms
.
VM
{
FakeVM
(
this
.
isolate
);
vms
.
Isolate
isolate
;
vms
.
Isolate
?
isolate
;
int
numberOfTriesBeforeResolvingIsolate
=
0
;
...
...
@@ -1034,7 +993,7 @@ class FakeVM extends Fake implements vms.VM {
numberOfTriesBeforeResolvingIsolate
-=
1
;
return
<
vms
.
Isolate
>[
if
(
numberOfTriesBeforeResolvingIsolate
<=
0
)
isolate
,
isolate
!
,
];
}
}
...
...
@@ -1047,7 +1006,7 @@ class FakeIsolate extends Fake implements vms.Isolate {
String
get
id
=>
number
;
@override
vms
.
Event
pauseEvent
;
vms
.
Event
?
pauseEvent
;
@override
List
<
String
>
get
extensionRPCs
=>
<
String
>[];
...
...
packages/flutter_driver/test/src/real_tests/extension_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
...
...
@@ -37,14 +35,14 @@ Future<void> silenceDriverLogger(AsyncCallback callback) async {
void
main
(
)
{
group
(
'waitUntilNoTransientCallbacks'
,
()
{
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
result
;
late
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
?
result
;
int
messageId
=
0
;
final
List
<
String
>
log
=
<
String
>[];
final
List
<
String
?>
log
=
<
String
?
>[];
setUp
(()
{
result
=
null
;
driverExtension
=
FlutterDriverExtension
((
String
message
)
async
{
log
.
add
(
message
);
return
(
messageId
+=
1
).
toString
();
},
false
,
true
);
driverExtension
=
FlutterDriverExtension
((
String
?
message
)
async
{
log
.
add
(
message
);
return
(
messageId
+=
1
).
toString
();
},
false
,
true
);
});
testWidgets
(
'returns immediately when transient callback queue is empty'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -64,7 +62,7 @@ void main() {
});
testWidgets
(
'waits until no transient callbacks'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
SchedulerBinding
.
instance
!
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
...
...
@@ -98,14 +96,14 @@ void main() {
});
group
(
'waitForCondition'
,
()
{
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
result
;
late
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
?
result
;
int
messageId
=
0
;
final
List
<
String
>
log
=
<
String
>[];
final
List
<
String
?>
log
=
<
String
?
>[];
setUp
(()
{
result
=
null
;
driverExtension
=
FlutterDriverExtension
((
String
message
)
async
{
log
.
add
(
message
);
return
(
messageId
+=
1
).
toString
();
},
false
,
true
);
driverExtension
=
FlutterDriverExtension
((
String
?
message
)
async
{
log
.
add
(
message
);
return
(
messageId
+=
1
).
toString
();
},
false
,
true
);
});
testWidgets
(
'waiting for NoTransientCallbacks returns immediately when transient callback queue is empty'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -125,7 +123,7 @@ void main() {
});
testWidgets
(
'waiting for NoTransientCallbacks returns until no transient callbacks'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
SchedulerBinding
.
instance
!
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
...
...
@@ -167,7 +165,7 @@ void main() {
});
testWidgets
(
'waiting for NoPendingFrame returns until no pending scheduled frame'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrame
();
SchedulerBinding
.
instance
!
.
scheduleFrame
();
driverExtension
.
call
(
const
WaitForCondition
(
NoPendingFrame
()).
serialize
())
.
then
<
void
>(
expectAsync1
((
Map
<
String
,
dynamic
>
r
)
{
...
...
@@ -210,8 +208,8 @@ void main() {
testWidgets
(
'waiting for combined conditions returns until no transient callbacks'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrame
();
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
SchedulerBinding
.
instance
!
.
scheduleFrame
();
SchedulerBinding
.
instance
!
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
...
...
@@ -239,8 +237,8 @@ void main() {
testWidgets
(
'waiting for combined conditions returns until no pending scheduled frame'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrame
();
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
SchedulerBinding
.
instance
!
.
scheduleFrame
();
SchedulerBinding
.
instance
!
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
...
...
@@ -288,11 +286,11 @@ void main() {
'waiting for NoPendingPlatformMessages returns until a single method channel call returns'
,
(
WidgetTester
tester
)
async
{
const
MethodChannel
channel
=
MethodChannel
(
'helloChannel'
,
JSONMethodCodec
());
const
MessageCodec
<
dynamic
>
jsonMessage
=
JSONMessageCodec
();
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
10
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
channel
.
invokeMethod
<
String
>(
'sayHello'
,
'hello'
);
...
...
@@ -322,20 +320,20 @@ void main() {
const
MessageCodec
<
dynamic
>
jsonMessage
=
JSONMessageCodec
();
// Configures channel 1
const
MethodChannel
channel1
=
MethodChannel
(
'helloChannel1'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
10
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
// Configures channel 2
const
MethodChannel
channel2
=
MethodChannel
(
'helloChannel2'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
20
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
channel1
.
invokeMethod
<
String
>(
'sayHello'
,
'hello'
);
...
...
@@ -371,20 +369,20 @@ void main() {
const
MessageCodec
<
dynamic
>
jsonMessage
=
JSONMessageCodec
();
// Configures channel 1
const
MethodChannel
channel1
=
MethodChannel
(
'helloChannel1'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
10
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
// Configures channel 2
const
MethodChannel
channel2
=
MethodChannel
(
'helloChannel2'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
20
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
channel1
.
invokeMethod
<
String
>(
'sayHello'
,
'hello'
);
...
...
@@ -422,20 +420,20 @@ void main() {
const
MessageCodec
<
dynamic
>
jsonMessage
=
JSONMessageCodec
();
// Configures channel 1
const
MethodChannel
channel1
=
MethodChannel
(
'helloChannel1'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel1'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
20
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
// Configures channel 2
const
MethodChannel
channel2
=
MethodChannel
(
'helloChannel2'
,
JSONMethodCodec
());
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
message
)
{
ServicesBinding
.
instance
!
.
defaultBinaryMessenger
.
setMockMessageHandler
(
'helloChannel2'
,
(
ByteData
?
message
)
{
return
Future
<
ByteData
>.
delayed
(
const
Duration
(
milliseconds:
10
),
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
]));
()
=>
jsonMessage
.
encodeMessage
(<
dynamic
>[
'hello world'
])
!
);
});
channel1
.
invokeMethod
<
String
>(
'sayHello'
,
'hello'
);
...
...
@@ -469,13 +467,13 @@ void main() {
});
group
(
'getSemanticsId'
,
()
{
FlutterDriverExtension
driverExtension
;
late
FlutterDriverExtension
driverExtension
;
setUp
(()
{
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
});
testWidgets
(
'works when semantics are enabled'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
semantics
=
RendererBinding
.
instance
.
pipelineOwner
.
ensureSemantics
();
final
SemanticsHandle
semantics
=
RendererBinding
.
instance
!
.
pipelineOwner
.
ensureSemantics
();
await
tester
.
pumpWidget
(
const
Text
(
'hello'
,
textDirection:
TextDirection
.
ltr
));
...
...
@@ -499,7 +497,7 @@ void main() {
},
semanticsEnabled:
false
);
testWidgets
(
'throws state error multiple matches are found'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
semantics
=
RendererBinding
.
instance
.
pipelineOwner
.
ensureSemantics
();
final
SemanticsHandle
semantics
=
RendererBinding
.
instance
!
.
pipelineOwner
.
ensureSemantics
();
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
...
...
@@ -520,7 +518,7 @@ void main() {
});
testWidgets
(
'getOffset'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
Offset
>
getOffset
(
OffsetType
offset
)
async
{
final
Map
<
String
,
String
>
arguments
=
GetOffset
(
ByValueKey
(
1
),
offset
).
serialize
();
...
...
@@ -552,9 +550,9 @@ void main() {
testWidgets
(
'getText'
,
(
WidgetTester
tester
)
async
{
await
silenceDriverLogger
(()
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
String
>
getTextInternal
(
SerializableFinder
search
)
async
{
Future
<
String
?
>
getTextInternal
(
SerializableFinder
search
)
async
{
final
Map
<
String
,
String
>
arguments
=
GetText
(
search
,
timeout:
const
Duration
(
seconds:
1
)).
serialize
();
final
Map
<
String
,
dynamic
>
result
=
await
driverExtension
.
call
(
arguments
);
if
(
result
[
'isError'
]
as
bool
)
{
...
...
@@ -622,9 +620,9 @@ void main() {
testWidgets
(
'descendant finder'
,
(
WidgetTester
tester
)
async
{
await
silenceDriverLogger
(()
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
String
>
getDescendantText
({
String
of
,
bool
matchRoot
=
false
})
async
{
Future
<
String
?>
getDescendantText
({
String
?
of
,
bool
matchRoot
=
false
})
async
{
final
Map
<
String
,
String
>
arguments
=
GetText
(
Descendant
(
of:
ByValueKey
(
of
),
matching:
ByValueKey
(
'text2'
),
...
...
@@ -655,7 +653,7 @@ void main() {
expect
(
await
getDescendantText
(
of:
'text2'
,
matchRoot:
true
),
'Hello2'
);
// Find nothing
Future
<
String
>
result
=
getDescendantText
(
of:
'text1'
,
matchRoot:
true
);
Future
<
String
?
>
result
=
getDescendantText
(
of:
'text1'
,
matchRoot:
true
);
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
expect
(
await
result
,
null
);
...
...
@@ -667,9 +665,9 @@ void main() {
testWidgets
(
'descendant finder firstMatchOnly'
,
(
WidgetTester
tester
)
async
{
await
silenceDriverLogger
(()
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
String
>
getDescendantText
()
async
{
Future
<
String
?
>
getDescendantText
()
async
{
final
Map
<
String
,
String
>
arguments
=
GetText
(
Descendant
(
of:
ByValueKey
(
'column'
),
matching:
const
ByType
(
'Text'
),
...
...
@@ -701,9 +699,9 @@ void main() {
testWidgets
(
'ancestor finder'
,
(
WidgetTester
tester
)
async
{
await
silenceDriverLogger
(()
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
Offset
>
getAncestorTopLeft
({
String
of
,
String
matching
,
bool
matchRoot
=
false
})
async
{
Future
<
Offset
?>
getAncestorTopLeft
({
String
?
of
,
String
?
matching
,
bool
matchRoot
=
false
})
async
{
final
Map
<
String
,
String
>
arguments
=
GetOffset
(
Ancestor
(
of:
ByValueKey
(
of
),
matching:
ByValueKey
(
matching
),
...
...
@@ -759,7 +757,7 @@ void main() {
);
// Find nothing
Future
<
Offset
>
result
=
getAncestorTopLeft
(
of:
'leftchild'
,
matching:
'leftchild'
);
Future
<
Offset
?
>
result
=
getAncestorTopLeft
(
of:
'leftchild'
,
matching:
'leftchild'
);
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
expect
(
await
result
,
null
);
...
...
@@ -771,9 +769,9 @@ void main() {
testWidgets
(
'ancestor finder firstMatchOnly'
,
(
WidgetTester
tester
)
async
{
await
silenceDriverLogger
(()
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
Offset
>
getAncestorTopLeft
()
async
{
Future
<
Offset
?
>
getAncestorTopLeft
()
async
{
final
Map
<
String
,
String
>
arguments
=
GetOffset
(
Ancestor
(
of:
ByValueKey
(
'leaf'
),
matching:
const
ByType
(
'Container'
),
...
...
@@ -819,9 +817,9 @@ void main() {
});
testWidgets
(
'GetDiagnosticsTree'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
Future
<
Map
<
String
,
Object
>>
getDiagnosticsTree
(
DiagnosticsType
type
,
SerializableFinder
finder
,
{
int
depth
=
0
,
bool
properties
=
true
})
async
{
Future
<
Map
<
String
,
dynamic
>>
getDiagnosticsTree
(
DiagnosticsType
type
,
SerializableFinder
finder
,
{
int
depth
=
0
,
bool
properties
=
true
})
async
{
final
Map
<
String
,
String
>
arguments
=
GetDiagnosticsTree
(
finder
,
type
,
subtreeDepth:
depth
,
includeProperties:
properties
).
serialize
();
final
Map
<
String
,
dynamic
>
response
=
await
driverExtension
.
call
(
arguments
);
final
DiagnosticsTreeResult
result
=
DiagnosticsTreeResult
(
response
[
'response'
]
as
Map
<
String
,
dynamic
>);
...
...
@@ -838,12 +836,12 @@ void main() {
);
// Widget
Map
<
String
,
Object
>
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
widget
,
ByValueKey
(
'Text'
),
depth:
0
);
Map
<
String
,
dynamic
>
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
widget
,
ByValueKey
(
'Text'
),
depth:
0
);
expect
(
result
[
'children'
],
isNull
);
// depth: 0
expect
(
result
[
'widgetRuntimeType'
],
'Text'
);
List
<
Map
<
String
,
Object
>>
properties
=
(
result
[
'properties'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
Map
<
String
,
Object
>
stringProperty
=
properties
.
singleWhere
((
Map
<
String
,
Object
>
property
)
=>
property
[
'name'
]
==
'data'
);
List
<
Map
<
String
,
dynamic
>>
properties
=
(
result
[
'properties'
]!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
Map
<
String
,
dynamic
>
stringProperty
=
properties
.
singleWhere
((
Map
<
String
,
dynamic
>
property
)
=>
property
[
'name'
]
==
'data'
);
expect
(
stringProperty
[
'description'
],
'"Hello World"'
);
expect
(
stringProperty
[
'propertyType'
],
'String'
);
...
...
@@ -852,11 +850,11 @@ void main() {
expect
(
result
[
'properties'
],
isNull
);
// properties: false
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
widget
,
ByValueKey
(
'Text'
),
depth:
1
);
List
<
Map
<
String
,
Object
>>
children
=
(
result
[
'children'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
List
<
Map
<
String
,
dynamic
>>
children
=
(
result
[
'children'
]!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
expect
(
children
.
single
[
'children'
],
isNull
);
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
widget
,
ByValueKey
(
'Text'
),
depth:
100
);
children
=
(
result
[
'children'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
children
=
(
result
[
'children'
]
!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
expect
(
children
.
single
[
'children'
],
isEmpty
);
// RenderObject
...
...
@@ -870,22 +868,22 @@ void main() {
expect
(
result
[
'description'
],
startsWith
(
'RenderParagraph'
));
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
renderObject
,
ByValueKey
(
'Text'
),
depth:
1
);
children
=
(
result
[
'children'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
final
Map
<
String
,
Object
>
textSpan
=
children
.
single
;
children
=
(
result
[
'children'
]
!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
final
Map
<
String
,
dynamic
>
textSpan
=
children
.
single
;
expect
(
textSpan
[
'description'
],
'TextSpan'
);
properties
=
(
textSpan
[
'properties'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
stringProperty
=
properties
.
singleWhere
((
Map
<
String
,
Object
>
property
)
=>
property
[
'name'
]
==
'text'
);
properties
=
(
textSpan
[
'properties'
]
!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
stringProperty
=
properties
.
singleWhere
((
Map
<
String
,
dynamic
>
property
)
=>
property
[
'name'
]
==
'text'
);
expect
(
stringProperty
[
'description'
],
'"Hello World"'
);
expect
(
stringProperty
[
'propertyType'
],
'String'
);
expect
(
children
.
single
[
'children'
],
isNull
);
result
=
await
getDiagnosticsTree
(
DiagnosticsType
.
renderObject
,
ByValueKey
(
'Text'
),
depth:
100
);
children
=
(
result
[
'children'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
Object
>>();
children
=
(
result
[
'children'
]
!
as
List
<
Object
>).
cast
<
Map
<
String
,
dynamic
>>();
expect
(
children
.
single
[
'children'
],
isEmpty
);
});
group
(
'enableTextEntryEmulation'
,
()
{
FlutterDriverExtension
driverExtension
;
late
FlutterDriverExtension
driverExtension
;
Future
<
Map
<
String
,
dynamic
>>
enterText
()
async
{
final
Map
<
String
,
String
>
arguments
=
const
EnterText
(
'foo'
).
serialize
();
...
...
@@ -905,7 +903,7 @@ void main() {
);
testWidgets
(
'enableTextEntryEmulation false'
,
(
WidgetTester
tester
)
async
{
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
false
);
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
false
);
await
tester
.
pumpWidget
(
testWidget
);
...
...
@@ -914,7 +912,7 @@ void main() {
});
testWidgets
(
'enableTextEntryEmulation true'
,
(
WidgetTester
tester
)
async
{
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
await
tester
.
pumpWidget
(
testWidget
);
...
...
@@ -944,7 +942,7 @@ void main() {
testWidgets
(
'unknown extension finder'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
finders:
<
FinderExtension
>[],
...
...
@@ -960,12 +958,12 @@ void main() {
final
Map
<
String
,
dynamic
>
result
=
await
getText
(
StubFinder
(
'Text1'
));
expect
(
result
[
'isError'
],
true
);
expect
(
result
[
'response'
]
is
String
,
true
);
expect
(
result
[
'response'
]
as
String
,
contains
(
'Unsupported search specification type Stub'
));
expect
(
result
[
'response'
]
as
String
?
,
contains
(
'Unsupported search specification type Stub'
));
});
testWidgets
(
'simple extension finder'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
finders:
<
FinderExtension
>[
...
...
@@ -987,7 +985,7 @@ void main() {
testWidgets
(
'complex extension finder'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
finders:
<
FinderExtension
>[
...
...
@@ -1009,7 +1007,7 @@ void main() {
testWidgets
(
'extension finder with command'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
finders:
<
FinderExtension
>[
...
...
@@ -1054,7 +1052,7 @@ void main() {
testWidgets
(
'unknown extension command'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
commands:
<
CommandExtension
>[],
...
...
@@ -1070,12 +1068,12 @@ void main() {
final
Map
<
String
,
dynamic
>
result
=
await
invokeCommand
(
ByValueKey
(
'Button'
),
10
);
expect
(
result
[
'isError'
],
true
);
expect
(
result
[
'response'
]
is
String
,
true
);
expect
(
result
[
'response'
]
as
String
,
contains
(
'Unsupported command kind StubNestedCommand'
));
expect
(
result
[
'response'
]
as
String
?
,
contains
(
'Unsupported command kind StubNestedCommand'
));
});
testWidgets
(
'nested command'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
commands:
<
CommandExtension
>[
...
...
@@ -1101,7 +1099,7 @@ void main() {
testWidgets
(
'prober command'
,
(
WidgetTester
tester
)
async
{
final
FlutterDriverExtension
driverExtension
=
FlutterDriverExtension
(
(
String
arg
)
async
=>
''
,
(
String
?
arg
)
async
=>
''
,
true
,
true
,
commands:
<
CommandExtension
>[
...
...
@@ -1127,11 +1125,11 @@ void main() {
});
group
(
'waitUntilFrameSync'
,
()
{
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
result
;
late
FlutterDriverExtension
driverExtension
;
Map
<
String
,
dynamic
>
?
result
;
setUp
(()
{
driverExtension
=
FlutterDriverExtension
((
String
arg
)
async
=>
''
,
true
,
true
);
driverExtension
=
FlutterDriverExtension
((
String
?
arg
)
async
=>
''
,
true
,
true
);
result
=
null
;
});
...
...
@@ -1154,7 +1152,7 @@ void main() {
testWidgets
(
'waits until no transient callbacks'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrameCallback
((
_
)
{
SchedulerBinding
.
instance
!
.
scheduleFrameCallback
((
_
)
{
// Intentionally blank. We only care about existence of a callback.
});
...
...
@@ -1180,7 +1178,7 @@ void main() {
testWidgets
(
'waits until no pending scheduled frame'
,
(
WidgetTester
tester
)
async
{
SchedulerBinding
.
instance
.
scheduleFrame
();
SchedulerBinding
.
instance
!
.
scheduleFrame
();
driverExtension
.
call
(
const
WaitForCondition
(
NoPendingFrame
()).
serialize
())
.
then
<
void
>(
expectAsync1
((
Map
<
String
,
dynamic
>
r
)
{
...
...
packages/flutter_driver/test/src/real_tests/find_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/driver_extension.dart'
;
import
'package:flutter_driver/flutter_driver.dart'
;
import
'package:flutter_driver/src/common/find.dart'
;
...
...
packages/flutter_driver/test/src/real_tests/io_extension_test.dart
View file @
3ece9c63
...
...
@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/src/extension/_extension_io.dart'
;
import
'../../common.dart'
;
void
main
(
)
{
group
(
'test io_extension'
,()
{
Future
<
Map
<
String
,
dynamic
>>
Function
(
Map
<
String
,
String
>)
call
;
late
Future
<
Map
<
String
,
dynamic
>>
Function
(
Map
<
String
,
String
>)
call
;
setUp
(()
{
call
=
(
Map
<
String
,
String
>
args
)
async
{
...
...
packages/flutter_driver/test/src/real_tests/request_data_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/flutter_driver.dart'
;
import
'../../common.dart'
;
...
...
packages/flutter_driver/test/src/real_tests/timeline_summary_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:convert'
show
json
;
import
'package:file/file.dart'
;
...
...
@@ -409,7 +407,7 @@ void main() {
group
(
'writeTimelineToFile'
,
()
{
Directory
tempDir
;
late
Directory
tempDir
;
setUp
(()
{
useMemoryFileSystemForTesting
();
...
...
@@ -480,7 +478,7 @@ void main() {
final
Timeline
timeline
=
Timeline
.
fromJson
(<
String
,
dynamic
>{
'traceEvents'
:
traceEvents
,
});
return
SceneDisplayLagSummarizer
(
timeline
.
events
);
return
SceneDisplayLagSummarizer
(
timeline
.
events
!
);
}
test
(
'average_vsyncs_missed'
,
()
async
{
...
...
@@ -531,7 +529,7 @@ void main() {
final
Timeline
timeline
=
Timeline
.
fromJson
(<
String
,
dynamic
>{
'traceEvents'
:
traceEvents
,
});
return
ProfilingSummarizer
.
fromEvents
(
timeline
.
events
);
return
ProfilingSummarizer
.
fromEvents
(
timeline
.
events
!
);
}
test
(
'has_both_cpu_and_memory_usage'
,
()
async
{
...
...
packages/flutter_driver/test/src/real_tests/timeline_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/src/driver/timeline.dart'
;
import
'../../common.dart'
;
...
...
@@ -34,7 +32,7 @@ void main() {
expect
(
timeline
.
events
,
hasLength
(
2
));
final
TimelineEvent
e1
=
timeline
.
events
[
1
];
final
TimelineEvent
e1
=
timeline
.
events
!
[
1
];
expect
(
e1
.
name
,
'test event'
);
expect
(
e1
.
category
,
'test category'
);
expect
(
e1
.
phase
,
'B'
);
...
...
@@ -46,7 +44,7 @@ void main() {
expect
(
e1
.
threadTimestampMicros
,
567
);
expect
(
e1
.
arguments
,
<
String
,
dynamic
>{
'arg1'
:
true
});
final
TimelineEvent
e2
=
timeline
.
events
[
0
];
final
TimelineEvent
e2
=
timeline
.
events
!
[
0
];
expect
(
e2
.
name
,
isNull
);
expect
(
e2
.
category
,
isNull
);
expect
(
e2
.
phase
,
isNull
);
...
...
@@ -74,10 +72,10 @@ void main() {
});
expect
(
timeline
.
events
,
hasLength
(
2
));
expect
(
timeline
.
events
[
0
].
timestampMicros
,
equals
(
456
));
expect
(
timeline
.
events
[
1
].
timestampMicros
,
equals
(
457
));
expect
(
timeline
.
events
[
0
].
name
,
equals
(
'test event 2'
));
expect
(
timeline
.
events
[
1
].
name
,
equals
(
'test event 1'
));
expect
(
timeline
.
events
!
[
0
].
timestampMicros
,
equals
(
456
));
expect
(
timeline
.
events
!
[
1
].
timestampMicros
,
equals
(
457
));
expect
(
timeline
.
events
!
[
0
].
name
,
equals
(
'test event 2'
));
expect
(
timeline
.
events
!
[
1
].
name
,
equals
(
'test event 1'
));
});
test
(
'sorts JSON nulls first'
,
()
{
...
...
@@ -103,14 +101,14 @@ void main() {
});
expect
(
timeline
.
events
,
hasLength
(
4
));
expect
(
timeline
.
events
[
0
].
timestampMicros
,
isNull
);
expect
(
timeline
.
events
[
1
].
timestampMicros
,
isNull
);
expect
(
timeline
.
events
[
2
].
timestampMicros
,
equals
(
456
));
expect
(
timeline
.
events
[
3
].
timestampMicros
,
equals
(
457
));
expect
(
timeline
.
events
[
0
].
name
,
equals
(
'test event 0'
));
expect
(
timeline
.
events
[
1
].
name
,
equals
(
'test event 3'
));
expect
(
timeline
.
events
[
2
].
name
,
equals
(
'test event 2'
));
expect
(
timeline
.
events
[
3
].
name
,
equals
(
'test event 1'
));
expect
(
timeline
.
events
!
[
0
].
timestampMicros
,
isNull
);
expect
(
timeline
.
events
!
[
1
].
timestampMicros
,
isNull
);
expect
(
timeline
.
events
!
[
2
].
timestampMicros
,
equals
(
456
));
expect
(
timeline
.
events
!
[
3
].
timestampMicros
,
equals
(
457
));
expect
(
timeline
.
events
!
[
0
].
name
,
equals
(
'test event 0'
));
expect
(
timeline
.
events
!
[
1
].
name
,
equals
(
'test event 3'
));
expect
(
timeline
.
events
!
[
2
].
name
,
equals
(
'test event 2'
));
expect
(
timeline
.
events
!
[
3
].
name
,
equals
(
'test event 1'
));
});
});
}
packages/flutter_driver/test/src/real_tests/wait_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/src/common/wait.dart'
;
import
'../../common.dart'
;
...
...
packages/flutter_driver/test_driver/failure.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/driver_extension.dart'
;
void
main
(
)
{
...
...
packages/flutter_driver/test_driver/failure_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'../test/common.dart'
;
void
main
(
)
{
...
...
packages/flutter_driver/test_driver/success.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'package:flutter_driver/driver_extension.dart'
;
void
main
(
)
{
...
...
packages/flutter_driver/test_driver/success_test.dart
View file @
3ece9c63
...
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'../test/common.dart'
;
void
main
(
)
{
...
...
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