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
a0099a90
Unverified
Commit
a0099a90
authored
Mar 27, 2018
by
Hans Muller
Committed by
GitHub
Mar 27, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make gallery tests more robust (#15957)
parent
8ca99327
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
200 additions
and
178 deletions
+200
-178
backdrop_demo.dart
...ples/flutter_gallery/lib/demo/material/backdrop_demo.dart
+6
-1
item.dart
examples/flutter_gallery/lib/gallery/item.dart
+1
-1
live_smoketest.dart
examples/flutter_gallery/test/live_smoketest.dart
+36
-75
smoke_test.dart
examples/flutter_gallery/test/smoke_test.dart
+8
-2
memory_nav_test.dart
examples/flutter_gallery/test_driver/memory_nav_test.dart
+0
-4
transitions_perf.dart
examples/flutter_gallery/test_driver/transitions_perf.dart
+12
-1
transitions_perf_test.dart
...es/flutter_gallery/test_driver/transitions_perf_test.dart
+76
-94
driver.dart
packages/flutter_driver/lib/src/driver/driver.dart
+61
-0
No files found.
examples/flutter_gallery/lib/demo/material/backdrop_demo.dart
View file @
a0099a90
...
@@ -14,6 +14,8 @@ class Category {
...
@@ -14,6 +14,8 @@ class Category {
const
Category
({
this
.
title
,
this
.
assets
});
const
Category
({
this
.
title
,
this
.
assets
});
final
String
title
;
final
String
title
;
final
List
<
String
>
assets
;
final
List
<
String
>
assets
;
@override
String
toString
()
=>
'
$runtimeType
("
$title
")'
;
}
}
const
List
<
Category
>
allCategories
=
const
<
Category
>[
const
List
<
Category
>
allCategories
=
const
<
Category
>[
...
@@ -178,10 +180,13 @@ class BackdropPanel extends StatelessWidget {
...
@@ -178,10 +180,13 @@ class BackdropPanel extends StatelessWidget {
alignment:
AlignmentDirectional
.
centerStart
,
alignment:
AlignmentDirectional
.
centerStart
,
child:
new
DefaultTextStyle
(
child:
new
DefaultTextStyle
(
style:
theme
.
textTheme
.
subhead
,
style:
theme
.
textTheme
.
subhead
,
child:
new
Tooltip
(
message:
'Tap to dismiss'
,
child:
title
,
child:
title
,
),
),
),
),
),
),
),
const
Divider
(
height:
1.0
),
const
Divider
(
height:
1.0
),
new
Expanded
(
child:
child
),
new
Expanded
(
child:
child
),
],
],
...
...
examples/flutter_gallery/lib/gallery/item.dart
View file @
a0099a90
...
@@ -118,7 +118,7 @@ List<GalleryItem> _buildGalleryItems() {
...
@@ -118,7 +118,7 @@ List<GalleryItem> _buildGalleryItems() {
),
),
new
GalleryItem
(
new
GalleryItem
(
title:
'Data tables'
,
title:
'Data tables'
,
subtitle:
'
Data table
s'
,
subtitle:
'
Rows and column
s'
,
category:
'Material Components'
,
category:
'Material Components'
,
routeName:
DataTableDemo
.
routeName
,
routeName:
DataTableDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
DataTableDemo
(),
buildRoute:
(
BuildContext
context
)
=>
new
DataTableDemo
(),
...
...
examples/flutter_gallery/test/live_smoketest.dart
View file @
a0099a90
...
@@ -11,30 +11,55 @@ import 'package:flutter/scheduler.dart';
...
@@ -11,30 +11,55 @@ import 'package:flutter/scheduler.dart';
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_gallery/gallery/app.dart'
;
import
'package:flutter_gallery/gallery/app.dart'
;
import
'package:flutter_gallery/gallery/item.dart'
;
//
/
Reports success or failure to the native code.
// Reports success or failure to the native code.
const
MethodChannel
_kTestChannel
=
const
MethodChannel
(
'io.flutter.demo.gallery/TestLifecycleListener'
);
const
MethodChannel
_kTestChannel
=
const
MethodChannel
(
'io.flutter.demo.gallery/TestLifecycleListener'
);
// The titles for all of the Gallery demos.
final
List
<
String
>
_kAllDemos
=
kAllGalleryItems
.
map
((
GalleryItem
item
)
=>
item
.
title
).
toList
();
// We don't want to wait for animations to complete before tapping the
// back button in the demos with these titles.
const
List
<
String
>
_kUnsynchronizedDemos
=
const
<
String
>[
'Progress indicators'
,
'Activity Indicator'
,
'Video'
,
];
// These demos can't be backed out of by tapping a button whose
// tooltip is 'Back'.
const
List
<
String
>
_kSkippedDemos
=
const
<
String
>[
'Backdrop'
,
'Pull to refresh'
,
];
Future
<
Null
>
main
()
async
{
Future
<
Null
>
main
()
async
{
try
{
try
{
runApp
(
const
GalleryApp
());
// Verify that _kUnsynchronizedDemos and _kSkippedDemos identify
// demos that actually exist.
if
(!
new
Set
<
String
>.
from
(
_kAllDemos
).
containsAll
(
_kUnsynchronizedDemos
))
fail
(
'Unrecognized demo names in _kUnsynchronizedDemos:
$_kUnsynchronizedDemos
'
);
if
(!
new
Set
<
String
>.
from
(
_kAllDemos
).
containsAll
(
_kSkippedDemos
))
fail
(
'Unrecognized demo names in _kSkippedDemos:
$_kSkippedDemos
'
);
const
Duration
kWaitBetweenActions
=
const
Duration
(
milliseconds:
250
);
runApp
(
const
GalleryApp
()
);
final
_LiveWidgetController
controller
=
new
_LiveWidgetController
();
final
_LiveWidgetController
controller
=
new
_LiveWidgetController
();
for
(
String
demo
in
_kAllDemos
)
{
for
(
Demo
demo
in
demos
)
{
print
(
'Testing "
$demo
" demo'
);
print
(
'Testing "
${demo.title}
" demo'
);
final
Finder
menuItem
=
find
.
text
(
demo
);
final
Finder
menuItem
=
find
.
text
(
demo
.
title
);
await
controller
.
scrollIntoView
(
menuItem
,
alignment:
0.5
);
await
controller
.
scrollIntoView
(
menuItem
,
alignment:
0.5
);
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
if
(
_kSkippedDemos
.
contains
(
demo
))
{
print
(
'> skipped
$demo
'
);
continue
;
}
for
(
int
i
=
0
;
i
<
2
;
i
+=
1
)
{
for
(
int
i
=
0
;
i
<
2
;
i
+=
1
)
{
await
controller
.
tap
(
menuItem
);
// Launch the demo
await
controller
.
tap
(
menuItem
);
// Launch the demo
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
controller
.
frameSync
=
!
_kUnsynchronizedDemos
.
contains
(
demo
);
controller
.
frameSync
=
demo
.
synchronized
;
await
controller
.
tap
(
find
.
byTooltip
(
'Back'
));
await
controller
.
tap
(
find
.
byTooltip
(
'Back'
));
controller
.
frameSync
=
true
;
controller
.
frameSync
=
true
;
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
}
}
print
(
'Success'
);
print
(
'Success'
);
}
}
...
@@ -45,70 +70,6 @@ Future<Null> main() async {
...
@@ -45,70 +70,6 @@ Future<Null> main() async {
}
}
}
}
class
Demo
{
const
Demo
(
this
.
title
,
{
this
.
synchronized
=
true
});
/// The title of the demo.
final
String
title
;
/// True if frameSync should be enabled for this test.
final
bool
synchronized
;
}
// Warning: this list must be kept in sync with the value of
// kAllGalleryItems.map((GalleryItem item) => item.title).toList();
const
List
<
Demo
>
demos
=
const
<
Demo
>[
// Demos
const
Demo
(
'Shrine'
),
const
Demo
(
'Contact profile'
),
const
Demo
(
'Animation'
),
// Material Components
const
Demo
(
'Bottom navigation'
),
const
Demo
(
'Buttons'
),
const
Demo
(
'Cards'
),
const
Demo
(
'Chips'
),
const
Demo
(
'Date and time pickers'
),
const
Demo
(
'Dialog'
),
const
Demo
(
'Drawer'
),
const
Demo
(
'Expand/collapse list control'
),
const
Demo
(
'Expansion panels'
),
const
Demo
(
'Floating action button'
),
const
Demo
(
'Grid'
),
const
Demo
(
'Icons'
),
const
Demo
(
'Leave-behind list items'
),
const
Demo
(
'List'
),
const
Demo
(
'Menus'
),
const
Demo
(
'Modal bottom sheet'
),
const
Demo
(
'Page selector'
),
const
Demo
(
'Persistent bottom sheet'
),
const
Demo
(
'Progress indicators'
,
synchronized:
false
),
const
Demo
(
'Pull to refresh'
),
const
Demo
(
'Scrollable tabs'
),
const
Demo
(
'Selection controls'
),
const
Demo
(
'Sliders'
),
const
Demo
(
'Snackbar'
),
const
Demo
(
'Tabs'
),
const
Demo
(
'Text fields'
),
const
Demo
(
'Tooltips'
),
// Cupertino Components
const
Demo
(
'Activity Indicator'
,
synchronized:
false
),
const
Demo
(
'Buttons'
),
const
Demo
(
'Dialogs'
),
const
Demo
(
'Navigation'
),
const
Demo
(
'Sliders'
),
const
Demo
(
'Switches'
),
// Media
const
Demo
(
'Animated images'
),
// Style
const
Demo
(
'Colors'
),
const
Demo
(
'Typography'
),
];
class
_LiveWidgetController
{
class
_LiveWidgetController
{
final
WidgetController
_controller
=
new
WidgetController
(
WidgetsBinding
.
instance
);
final
WidgetController
_controller
=
new
WidgetController
(
WidgetsBinding
.
instance
);
...
...
examples/flutter_gallery/test/smoke_test.dart
View file @
a0099a90
...
@@ -102,11 +102,19 @@ Future<Null> smokeDemo(WidgetTester tester, String routeName) async {
...
@@ -102,11 +102,19 @@ Future<Null> smokeDemo(WidgetTester tester, String routeName) async {
await
tester
.
pump
();
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
400
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
400
));
// This demo's back button isn't initially visible.
if
(
routeName
==
'/material/backdrop'
)
{
await
tester
.
tap
(
find
.
byTooltip
(
'Tap to dismiss'
));
await
tester
.
pumpAndSettle
();
}
// Go back
// Go back
await
tester
.
pageBack
();
await
tester
.
pageBack
();
await
tester
.
pumpAndSettle
();
await
tester
.
pump
();
// Start the pop "back" operation.
await
tester
.
pump
();
// Start the pop "back" operation.
await
tester
.
pump
();
// Complete the willPop() Future.
await
tester
.
pump
();
// Complete the willPop() Future.
await
tester
.
pump
(
const
Duration
(
milliseconds:
400
));
// Wait until it has finished.
await
tester
.
pump
(
const
Duration
(
milliseconds:
400
));
// Wait until it has finished.
return
null
;
return
null
;
}
}
...
@@ -126,8 +134,6 @@ Future<Null> runSmokeTest(WidgetTester tester) async {
...
@@ -126,8 +134,6 @@ Future<Null> runSmokeTest(WidgetTester tester) async {
final
Finder
finder
=
findGalleryItemByRouteName
(
tester
,
routeName
);
final
Finder
finder
=
findGalleryItemByRouteName
(
tester
,
routeName
);
Scrollable
.
ensureVisible
(
tester
.
element
(
finder
),
alignment:
0.5
);
Scrollable
.
ensureVisible
(
tester
.
element
(
finder
),
alignment:
0.5
);
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
if
(
routeName
==
'/material/backdrop'
)
continue
;
await
smokeDemo
(
tester
,
routeName
);
await
smokeDemo
(
tester
,
routeName
);
tester
.
binding
.
debugAssertNoTransientCallbacks
(
'A transient callback was still active after leaving route
$routeName
'
);
tester
.
binding
.
debugAssertNoTransientCallbacks
(
'A transient callback was still active after leaving route
$routeName
'
);
}
}
...
...
examples/flutter_gallery/test_driver/memory_nav_test.dart
View file @
a0099a90
...
@@ -23,18 +23,14 @@ void main() {
...
@@ -23,18 +23,14 @@ void main() {
final
SerializableFinder
menuItem
=
find
.
text
(
'Text fields'
);
final
SerializableFinder
menuItem
=
find
.
text
(
'Text fields'
);
driver
.
waitFor
(
menuItem
).
then
<
Null
>((
Null
value
)
async
{
driver
.
waitFor
(
menuItem
).
then
<
Null
>((
Null
value
)
async
{
scroll
=
false
;
scroll
=
false
;
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
for
(
int
i
=
0
;
i
<
15
;
i
++)
{
for
(
int
i
=
0
;
i
<
15
;
i
++)
{
await
driver
.
tap
(
menuItem
);
await
driver
.
tap
(
menuItem
);
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
}
}
completer
.
complete
();
completer
.
complete
();
});
});
while
(
scroll
)
{
while
(
scroll
)
{
await
driver
.
scroll
(
find
.
text
(
'Flutter Gallery'
),
0.0
,
-
500.0
,
const
Duration
(
milliseconds:
80
));
await
driver
.
scroll
(
find
.
text
(
'Flutter Gallery'
),
0.0
,
-
500.0
,
const
Duration
(
milliseconds:
80
));
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
}
}
await
completer
.
future
;
await
completer
.
future
;
},
timeout:
const
Timeout
(
const
Duration
(
minutes:
1
)));
},
timeout:
const
Timeout
(
const
Duration
(
minutes:
1
)));
...
...
examples/flutter_gallery/test_driver/transitions_perf.dart
View file @
a0099a90
...
@@ -2,10 +2,21 @@
...
@@ -2,10 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
show
JsonEncoder
;
import
'package:flutter_driver/driver_extension.dart'
;
import
'package:flutter_driver/driver_extension.dart'
;
import
'package:flutter_gallery/gallery/item.dart'
;
import
'package:flutter_gallery/main.dart'
as
app
;
import
'package:flutter_gallery/main.dart'
as
app
;
Future
<
String
>
_handleMessages
(
String
message
)
async
{
assert
(
message
==
'demoNames'
);
return
const
JsonEncoder
.
withIndent
(
' '
).
convert
(
kAllGalleryItems
.
map
((
GalleryItem
item
)
=>
item
.
title
).
toList
(),
);
}
void
main
(
)
{
void
main
(
)
{
enableFlutterDriverExtension
();
enableFlutterDriverExtension
(
handler:
_handleMessages
);
app
.
main
();
app
.
main
();
}
}
examples/flutter_gallery/test_driver/transitions_perf_test.dart
View file @
a0099a90
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
show
JsonEncoder
;
import
'dart:convert'
show
JsonEncoder
,
JsonDecoder
;
import
'package:file/file.dart'
;
import
'package:file/file.dart'
;
import
'package:file/local.dart'
;
import
'package:file/local.dart'
;
...
@@ -11,81 +11,46 @@ import 'package:flutter_driver/flutter_driver.dart';
...
@@ -11,81 +11,46 @@ import 'package:flutter_driver/flutter_driver.dart';
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
import
'package:test/test.dart'
;
import
'package:test/test.dart'
;
class
Demo
{
const
FileSystem
_fs
=
const
LocalFileSystem
();
const
Demo
(
this
.
title
,
{
this
.
synchronized
=
true
,
this
.
profiled
=
false
});
/// The title of the demo.
final
String
title
;
/// True if frameSync should be enabled for this test.
final
bool
synchronized
;
// True if timeline data should be collected for this test.
//
// Warning: The number of tests executed with timeline collection enabled
// significantly impacts heap size of the running app. When run with
// --trace-startup, as we do in this test, the VM stores trace events in an
// endless buffer instead of a ring buffer.
final
bool
profiled
;
}
// Warning: this list must be kept in sync with the value of
// Demos for which timeline data will be collected using
// kAllGalleryItems.map((GalleryItem item) => item.title).toList();
// FlutterDriver.traceAction().
const
List
<
Demo
>
demos
=
const
<
Demo
>[
//
// Demos
// Warning: The number of tests executed with timeline collection enabled
const
Demo
(
'Shrine'
,
profiled:
true
),
// significantly impacts heap size of the running app. When run with
const
Demo
(
'Contact profile'
,
profiled:
true
),
// --trace-startup, as we do in this test, the VM stores trace events in an
const
Demo
(
'Animation'
,
profiled:
true
),
// endless buffer instead of a ring buffer.
//
// Material Components
// These names must match GalleryItem titles from kAllGalleryItems
const
Demo
(
'Bottom navigation'
,
profiled:
true
),
// in examples/flutter_gallery/lib/gallery.item.dart
const
Demo
(
'Buttons'
,
profiled:
true
),
const
List
<
String
>
kProfiledDemos
=
const
<
String
>[
const
Demo
(
'Cards'
,
profiled:
true
),
'Shrine'
,
const
Demo
(
'Chips'
,
profiled:
true
),
'Contact profile'
,
const
Demo
(
'Date and time pickers'
,
profiled:
true
),
'Animation'
,
const
Demo
(
'Dialog'
,
profiled:
true
),
'Bottom navigation'
,
const
Demo
(
'Drawer'
),
'Buttons'
,
const
Demo
(
'Expand/collapse list control'
),
'Cards'
,
const
Demo
(
'Expansion panels'
),
'Chips'
,
const
Demo
(
'Floating action button'
),
'Date and time pickers'
,
const
Demo
(
'Grid'
),
'Dialog'
,
const
Demo
(
'Icons'
),
const
Demo
(
'Leave-behind list items'
),
const
Demo
(
'List'
),
const
Demo
(
'Menus'
),
const
Demo
(
'Modal bottom sheet'
),
const
Demo
(
'Page selector'
),
const
Demo
(
'Persistent bottom sheet'
),
const
Demo
(
'Progress indicators'
,
synchronized:
false
),
const
Demo
(
'Pull to refresh'
),
const
Demo
(
'Scrollable tabs'
),
const
Demo
(
'Selection controls'
),
const
Demo
(
'Sliders'
),
const
Demo
(
'Snackbar'
),
const
Demo
(
'Tabs'
),
const
Demo
(
'Text fields'
),
const
Demo
(
'Tooltips'
),
// Cupertino Components
const
Demo
(
'Activity Indicator'
,
synchronized:
false
),
const
Demo
(
'Buttons'
),
const
Demo
(
'Dialogs'
),
const
Demo
(
'Navigation'
),
const
Demo
(
'Pickers'
),
const
Demo
(
'Sliders'
),
const
Demo
(
'Switches'
),
// Media
const
Demo
(
'Animated images'
),
// Style
const
Demo
(
'Colors'
),
const
Demo
(
'Typography'
),
];
];
const
FileSystem
_fs
=
const
LocalFileSystem
();
// Demos that will be backed out of within FlutterDriver.runUnsynchronized();
//
// These names must match GalleryItem titles from kAllGalleryItems
// in examples/flutter_gallery/lib/gallery.item.dart
const
List
<
String
>
kUnsynchronizedDemos
=
const
<
String
>[
'Progress indicators'
,
'Activity Indicator'
,
'Video'
,
];
const
Duration
kWaitBetweenActions
=
const
Duration
(
milliseconds:
250
);
// All of the gallery demo titles in the order they appear on the
// gallery home page.
//
// These names are reported by the test app, see _handleMessages()
// in transitions_perf.dart.
List
<
String
>
_allDemos
=
<
String
>[];
/// Extracts event data from [events] recorded by timeline, validates it, turns
/// Extracts event data from [events] recorded by timeline, validates it, turns
/// it into a histogram, and saves to a JSON file.
/// it into a histogram, and saves to a JSON file.
...
@@ -155,25 +120,29 @@ Future<Null> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou
...
@@ -155,25 +120,29 @@ Future<Null> saveDurationsHistogram(List<Map<String, dynamic>> events, String ou
/// Scrolls each demo menu item into view, launches it, then returns to the
/// Scrolls each demo menu item into view, launches it, then returns to the
/// home screen twice.
/// home screen twice.
Future
<
Null
>
runDemos
(
Iterable
<
Demo
>
demos
,
FlutterDriver
driver
)
async
{
Future
<
Null
>
runDemos
(
List
<
String
>
demos
,
FlutterDriver
driver
)
async
{
for
(
Demo
demo
in
demos
)
{
for
(
String
demo
in
demos
)
{
print
(
'Testing "
${demo.title}
" demo'
);
print
(
'Testing "
$demo
" demo'
);
final
SerializableFinder
menuItem
=
find
.
text
(
demo
.
title
);
final
SerializableFinder
menuItem
=
find
.
text
(
demo
);
await
driver
.
scrollIntoView
(
menuItem
,
alignment:
0.5
);
await
driver
.
scrollUntilVisible
(
find
.
byType
(
'CustomScrollView'
),
menuItem
,
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
dyScroll:
-
48.0
,
alignment:
0.5
,
);
for
(
int
i
=
0
;
i
<
2
;
i
+=
1
)
{
for
(
int
i
=
0
;
i
<
2
;
i
+=
1
)
{
await
driver
.
tap
(
menuItem
);
// Launch the demo
await
driver
.
tap
(
menuItem
);
// Launch the demo
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
if
(
demo
.
synchronized
)
{
// This demo's back button isn't initially visible.
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
if
(
demo
==
'Backdrop'
)
}
else
{
await
driver
.
tap
(
find
.
byTooltip
(
'Tap to dismiss'
));
if
(
kUnsynchronizedDemos
.
contains
(
demo
))
{
await
driver
.
runUnsynchronized
<
Future
<
Null
>>(()
async
{
await
driver
.
runUnsynchronized
<
Future
<
Null
>>(()
async
{
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
});
});
}
else
{
await
driver
.
tap
(
find
.
byTooltip
(
'Back'
));
}
}
await
new
Future
<
Null
>.
delayed
(
kWaitBetweenActions
);
}
}
print
(
'Success'
);
print
(
'Success'
);
}
}
...
@@ -184,10 +153,16 @@ void main([List<String> args = const <String>[]]) {
...
@@ -184,10 +153,16 @@ void main([List<String> args = const <String>[]]) {
FlutterDriver
driver
;
FlutterDriver
driver
;
setUpAll
(()
async
{
setUpAll
(()
async
{
driver
=
await
FlutterDriver
.
connect
();
driver
=
await
FlutterDriver
.
connect
();
if
(
args
.
contains
(
'--with_semantics'
))
{
if
(
args
.
contains
(
'--with_semantics'
))
{
print
(
'Enabeling semantics...'
);
print
(
'Enabeling semantics...'
);
await
driver
.
setSemantics
(
true
);
await
driver
.
setSemantics
(
true
);
}
}
// See _handleMessages() in transitions_perf.dart.
_allDemos
=
const
JsonDecoder
().
convert
(
await
driver
.
requestData
(
'demoNames'
));
if
(
_allDemos
.
isEmpty
)
throw
'no demo names found'
;
});
});
tearDownAll
(()
async
{
tearDownAll
(()
async
{
...
@@ -197,14 +172,15 @@ void main([List<String> args = const <String>[]]) {
...
@@ -197,14 +172,15 @@ void main([List<String> args = const <String>[]]) {
test
(
'all demos'
,
()
async
{
test
(
'all demos'
,
()
async
{
// Collect timeline data for just a limited set of demos to avoid OOMs.
// Collect timeline data for just a limited set of demos to avoid OOMs.
final
Timeline
timeline
=
await
driver
.
traceAction
(
()
async
{
final
Timeline
timeline
=
await
driver
.
traceAction
(
final
Iterable
<
Demo
>
profiledDemos
=
demos
.
where
((
Demo
demo
)
=>
demo
.
profiled
);
()
async
{
await
runDemos
(
p
rofiledDemos
,
driver
);
await
runDemos
(
kP
rofiledDemos
,
driver
);
},
},
streams:
const
<
TimelineStream
>[
streams:
const
<
TimelineStream
>[
TimelineStream
.
dart
,
TimelineStream
.
dart
,
TimelineStream
.
embedder
,
TimelineStream
.
embedder
,
]);
],
);
// Save the duration (in microseconds) of the first timeline Frame event
// Save the duration (in microseconds) of the first timeline Frame event
// that follows a 'Start Transition' event. The Gallery app adds a
// that follows a 'Start Transition' event. The Gallery app adds a
...
@@ -214,9 +190,15 @@ void main([List<String> args = const <String>[]]) {
...
@@ -214,9 +190,15 @@ void main([List<String> args = const <String>[]]) {
final
String
histogramPath
=
path
.
join
(
testOutputsDirectory
,
'transition_durations.timeline.json'
);
final
String
histogramPath
=
path
.
join
(
testOutputsDirectory
,
'transition_durations.timeline.json'
);
await
saveDurationsHistogram
(
timeline
.
json
[
'traceEvents'
],
histogramPath
);
await
saveDurationsHistogram
(
timeline
.
json
[
'traceEvents'
],
histogramPath
);
// Scroll back to the top
await
driver
.
scrollUntilVisible
(
find
.
byType
(
'CustomScrollView'
),
find
.
text
(
_allDemos
[
0
]),
dyScroll:
200.0
,
alignment:
0.0
);
// Execute the remaining tests.
// Execute the remaining tests.
final
Iterable
<
Demo
>
unprofiledDemos
=
demos
.
where
((
Demo
demo
)
=>
!
demo
.
profiled
);
final
Set
<
String
>
unprofiledDemos
=
new
Set
<
String
>.
from
(
_allDemos
)..
removeAll
(
kProfiledDemos
);
await
runDemos
(
unprofiledDemos
,
driver
);
await
runDemos
(
unprofiledDemos
.
toList
()
,
driver
);
},
timeout:
const
Timeout
(
const
Duration
(
minutes:
5
)));
},
timeout:
const
Timeout
(
const
Duration
(
minutes:
5
)));
});
});
...
...
packages/flutter_driver/lib/src/driver/driver.dart
View file @
a0099a90
...
@@ -409,10 +409,71 @@ class FlutterDriver {
...
@@ -409,10 +409,71 @@ class FlutterDriver {
/// Scrolls the Scrollable ancestor of the widget located by [finder]
/// Scrolls the Scrollable ancestor of the widget located by [finder]
/// until the widget is completely visible.
/// until the widget is completely visible.
///
/// If the widget located by [finder] is contained by a scrolling widget
/// 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
<
Null
>
scrollIntoView
(
SerializableFinder
finder
,
{
double
alignment:
0.0
,
Duration
timeout
})
async
{
Future
<
Null
>
scrollIntoView
(
SerializableFinder
finder
,
{
double
alignment:
0.0
,
Duration
timeout
})
async
{
return
await
_sendCommand
(
new
ScrollIntoView
(
finder
,
alignment:
alignment
,
timeout:
timeout
)).
then
((
Map
<
String
,
dynamic
>
_
)
=>
null
);
return
await
_sendCommand
(
new
ScrollIntoView
(
finder
,
alignment:
alignment
,
timeout:
timeout
)).
then
((
Map
<
String
,
dynamic
>
_
)
=>
null
);
}
}
/// Repeatedly [scroll] the widget located by [scrollable] by [dxScroll] and
/// [dyScroll] until [item] is visible, and then use [scrollIntoView] to
/// ensure the item's final position matches [alignment].
///
/// The [scrollable] must locate the scrolling widget that contains [item].
/// Typically `find.byType('ListView') or `find.byType('CustomScrollView')`.
///
/// Atleast one of [dxScroll] and [dyScroll] must be non-zero.
///
/// If [item] is below the currently visible items, then specify a negative
/// value for [dyScroll] that's a small enough increment to expose [item]
/// without potentially scrolling it up and completely out of view. Similarly
/// if [item] is above, then specify a positve value for [dyScroll].
///
/// If [item] is to the right of the the currently visible items, then
/// specify a negative value for [dxScroll] that's a small enough increment to
/// expose [item] without potentially scrolling it up and completely out of
/// view. Similarly if [item] is to the left, then specify a positve value
/// for [dyScroll].
///
/// The [timeout] value should be long enough to accommodate as many scrolls
/// as needed to bring an item into view. The default is 10 seconds.
Future
<
Null
>
scrollUntilVisible
(
SerializableFinder
scrollable
,
SerializableFinder
item
,
{
double
alignment:
0.0
,
double
dxScroll:
0.0
,
double
dyScroll:
0.0
,
Duration
timeout:
const
Duration
(
seconds:
10
),
})
async
{
assert
(
scrollable
!=
null
);
assert
(
item
!=
null
);
assert
(
alignment
!=
null
);
assert
(
dxScroll
!=
null
);
assert
(
dyScroll
!=
null
);
assert
(
dxScroll
!=
0.0
||
dyScroll
!=
0.0
);
assert
(
timeout
!=
null
);
// If the item is already visible then we're done.
bool
isVisible
=
false
;
try
{
await
waitFor
(
item
,
timeout:
const
Duration
(
milliseconds:
100
));
isVisible
=
true
;
}
on
DriverError
{
// Assume that that waitFor timed out because the item isn't visible.
}
if
(!
isVisible
)
{
waitFor
(
item
,
timeout:
timeout
).
then
((
Null
_
)
{
isVisible
=
true
;
});
while
(!
isVisible
)
{
await
scroll
(
scrollable
,
dxScroll
,
dyScroll
,
const
Duration
(
milliseconds:
100
));
await
new
Future
<
Null
>.
delayed
(
const
Duration
(
milliseconds:
500
));
}
}
return
scrollIntoView
(
item
,
alignment:
alignment
);
}
/// Returns the text in the `Text` widget located by [finder].
/// 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
(
new
GetText
(
finder
,
timeout:
timeout
))).
text
;
return
GetTextResult
.
fromJson
(
await
_sendCommand
(
new
GetText
(
finder
,
timeout:
timeout
))).
text
;
...
...
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