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
6d35481c
Commit
6d35481c
authored
Feb 29, 2016
by
Yegor Jbanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add smoke driver test; find by tooltip; retry predicate
parent
6a1f47a5
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
266 additions
and
87 deletions
+266
-87
driver.dart
packages/flutter_driver/lib/src/driver.dart
+12
-1
enum_util.dart
packages/flutter_driver/lib/src/enum_util.dart
+2
-1
error.dart
packages/flutter_driver/lib/src/error.dart
+7
-1
extension.dart
packages/flutter_driver/lib/src/extension.dart
+82
-27
find.dart
packages/flutter_driver/lib/src/find.dart
+82
-9
retry.dart
packages/flutter_driver/lib/src/retry.dart
+15
-6
flutter_driver_test.dart
packages/flutter_driver/test/flutter_driver_test.dart
+3
-2
retry_test.dart
packages/flutter_driver/test/retry_test.dart
+20
-0
analyze.dart
packages/flutter_tools/lib/src/commands/analyze.dart
+30
-18
drive.dart
packages/flutter_tools/lib/src/commands/drive.dart
+1
-1
main.dart.tmpl
packages/flutter_tools/templates/create/lib/main.dart.tmpl
+8
-0
e2e.dart.tmpl
packages/flutter_tools/templates/driver/e2e.dart.tmpl
+0
-9
main_test.dart.tmpl
packages/flutter_tools/templates/driver/main_test.dart.tmpl
+4
-12
No files found.
packages/flutter_driver/lib/src/driver.dart
View file @
6d35481c
...
...
@@ -151,8 +151,19 @@ class FlutterDriver {
return
Health
.
fromJson
(
await
_sendCommand
(
new
GetHealth
()));
}
/// Finds the UI element with the given [key].
Future
<
ObjectRef
>
findByValueKey
(
dynamic
key
)
async
{
return
ObjectRef
.
fromJson
(
await
_sendCommand
(
new
FindByValueKey
(
key
)));
return
ObjectRef
.
fromJson
(
await
_sendCommand
(
new
Find
(
new
ByValueKey
(
key
))));
}
/// Finds the UI element for the tooltip with the given [message].
Future
<
ObjectRef
>
findByTooltipMessage
(
String
message
)
async
{
return
ObjectRef
.
fromJson
(
await
_sendCommand
(
new
Find
(
new
ByTooltipMessage
(
message
))));
}
/// Finds the text element with the given [text].
Future
<
ObjectRef
>
findByText
(
String
text
)
async
{
return
ObjectRef
.
fromJson
(
await
_sendCommand
(
new
Find
(
new
ByText
(
text
))));
}
Future
<
Null
>
tap
(
ObjectRef
ref
)
async
{
...
...
packages/flutter_driver/lib/src/enum_util.dart
View file @
6d35481c
...
...
@@ -6,7 +6,8 @@
///
/// In Dart enum names are prefixed with enum class name. For example, for
/// `enum Vote { yea, nay }`, `Vote.yea.toString()` produces `"Vote.yea"`
/// rather than just `"yea"` - the simple name.
/// rather than just `"yea"` - the simple name. This class provides methods for
/// getting and looking up by simple names.
///
/// Example:
///
...
...
packages/flutter_driver/lib/src/error.dart
View file @
6d35481c
...
...
@@ -15,7 +15,13 @@ class DriverError extends Error {
final
dynamic
originalError
;
final
dynamic
originalStackTrace
;
String
toString
()
=>
'DriverError:
$message
'
;
String
toString
()
{
return
'''DriverError:
$message
Original error:
$originalError
Original stack trace:
$originalStackTrace
'''
;
}
}
// Whether someone redirected the log messages somewhere.
...
...
packages/flutter_driver/lib/src/extension.dart
View file @
6d35481c
...
...
@@ -5,6 +5,7 @@
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:developer'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/src/instrumentation.dart'
;
...
...
@@ -50,14 +51,14 @@ class FlutterDriverExtension {
FlutterDriverExtension
()
{
_commandHandlers
=
{
'get_health'
:
getHealth
,
'find
_by_value_key'
:
findByValueKey
,
'find
'
:
find
,
'tap'
:
tap
,
'get_text'
:
getText
,
};
_commandDeserializers
=
{
'get_health'
:
GetHealth
.
fromJson
,
'find
_by_value_key'
:
FindByValueKey
.
fromJson
,
'find
'
:
Find
.
fromJson
,
'tap'
:
Tap
.
fromJson
,
'get_text'
:
GetText
.
fromJson
,
};
...
...
@@ -72,41 +73,95 @@ class FlutterDriverExtension {
<
String
,
CommandDeserializerCallback
>{};
Future
<
ServiceExtensionResponse
>
call
(
Map
<
String
,
String
>
params
)
async
{
String
commandKind
=
params
[
'kind'
];
CommandHandlerCallback
commandHandler
=
_commandHandlers
[
commandKind
];
CommandDeserializerCallback
commandDeserializer
=
_commandDeserializers
[
commandKind
];
if
(
commandHandler
==
null
||
commandDeserializer
==
null
)
{
return
new
ServiceExtensionResponse
.
error
(
ServiceExtensionResponse
.
kInvalidParams
,
'Extension
$_extensionMethod
does not support command
$commandKind
'
);
try
{
String
commandKind
=
params
[
'kind'
];
CommandHandlerCallback
commandHandler
=
_commandHandlers
[
commandKind
];
CommandDeserializerCallback
commandDeserializer
=
_commandDeserializers
[
commandKind
];
if
(
commandHandler
==
null
||
commandDeserializer
==
null
)
{
return
new
ServiceExtensionResponse
.
error
(
ServiceExtensionResponse
.
kInvalidParams
,
'Extension
$_extensionMethod
does not support command
$commandKind
'
);
}
Command
command
=
commandDeserializer
(
params
);
return
commandHandler
(
command
).
then
((
Result
result
)
{
return
new
ServiceExtensionResponse
.
result
(
JSON
.
encode
(
result
.
toJson
()));
},
onError:
(
e
,
s
)
{
_log
.
warning
(
'
$e
:
\n
$s
'
);
return
new
ServiceExtensionResponse
.
error
(
ServiceExtensionResponse
.
kExtensionError
,
'
$e
'
);
});
}
catch
(
error
,
stackTrace
)
{
_log
.
warning
(
'Uncaught extension error:
$error
\n
$stackTrace
'
);
}
Command
command
=
commandDeserializer
(
params
);
return
commandHandler
(
command
).
then
((
Result
result
)
{
return
new
ServiceExtensionResponse
.
result
(
JSON
.
encode
(
result
.
toJson
()));
},
onError:
(
e
,
s
)
{
_log
.
warning
(
'
$e
:
\n
$s
'
);
return
new
ServiceExtensionResponse
.
error
(
ServiceExtensionResponse
.
kExtensionError
,
'
$e
'
);
});
}
Future
<
Health
>
getHealth
(
GetHealth
command
)
async
=>
new
Health
(
HealthStatus
.
ok
);
Future
<
ObjectRef
>
findByValueKey
(
FindByValueKey
command
)
async
{
Element
elem
=
await
retry
(()
{
return
prober
.
findElementByKey
(
new
ValueKey
<
dynamic
>(
command
.
keyValue
));
},
_kDefaultTimeout
,
_kDefaultPauseBetweenRetries
);
Future
<
ObjectRef
>
find
(
Find
command
)
async
{
SearchSpecification
searchSpec
=
command
.
searchSpec
;
switch
(
searchSpec
.
runtimeType
)
{
case
ByValueKey:
return
findByValueKey
(
searchSpec
);
case
ByTooltipMessage:
return
findByTooltipMessage
(
searchSpec
);
case
ByText:
return
findByText
(
searchSpec
);
}
throw
new
DriverError
(
'Unsupported search specification type
${searchSpec.runtimeType}
'
);
}
ObjectRef
elemRef
=
elem
!=
null
?
new
ObjectRef
(
_registerObject
(
elem
))
/// Runs object [locator] repeatedly until it returns a non-`null` value.
///
/// [descriptionGetter] describes the object to be waited for. It is used in
/// the warning printed should timeout happen.
Future
<
ObjectRef
>
_waitForObject
(
String
descriptionGetter
(),
Object
locator
())
async
{
Object
object
=
await
retry
(
locator
,
_kDefaultTimeout
,
_kDefaultPauseBetweenRetries
,
predicate:
(
object
)
{
return
object
!=
null
;
}).
catchError
((
dynamic
error
,
stackTrace
)
{
_log
.
warning
(
'Timed out waiting for
${descriptionGetter()}
'
);
return
null
;
});
ObjectRef
elemRef
=
object
!=
null
?
new
ObjectRef
(
_registerObject
(
object
))
:
new
ObjectRef
.
notFound
();
return
new
Future
.
value
(
elemRef
);
}
Future
<
ObjectRef
>
findByValueKey
(
ByValueKey
byKey
)
async
{
return
_waitForObject
(
()
=>
'element with key "
${byKey.keyValue}
" of type
${byKey.keyValueType}
'
,
()
{
return
prober
.
findElementByKey
(
new
ValueKey
<
dynamic
>(
byKey
.
keyValue
));
}
);
}
Future
<
ObjectRef
>
findByTooltipMessage
(
ByTooltipMessage
byTooltipMessage
)
async
{
return
_waitForObject
(
()
=>
'tooltip with message "
${byTooltipMessage.text}
" on it'
,
()
{
return
prober
.
findElement
((
Element
element
)
{
Widget
widget
=
element
.
widget
;
if
(
widget
is
Tooltip
)
return
widget
.
message
==
byTooltipMessage
.
text
;
return
false
;
});
}
);
}
Future
<
ObjectRef
>
findByText
(
ByText
byText
)
async
{
return
await
_waitForObject
(
()
=>
'text "
${byText.text}
"'
,
()
{
return
prober
.
findText
(
byText
.
text
);
});
}
Future
<
TapResult
>
tap
(
Tap
command
)
async
{
Element
target
=
await
_dereferenceOrDie
(
command
.
targetRef
);
prober
.
tap
(
target
);
...
...
packages/flutter_driver/lib/src/find.dart
View file @
6d35481c
...
...
@@ -7,11 +7,84 @@ import 'message.dart';
const
List
<
Type
>
_supportedKeyValueTypes
=
const
<
Type
>[
String
,
int
];
/// Command to find an element
by a value key
.
class
Find
ByValueKey
extends
Command
{
final
String
kind
=
'find
_by_value_key
'
;
/// Command to find an element.
class
Find
extends
Command
{
final
String
kind
=
'find'
;
FindByValueKey
(
dynamic
keyValue
)
Find
(
this
.
searchSpec
);
final
SearchSpecification
searchSpec
;
Map
<
String
,
dynamic
>
toJson
()
=>
searchSpec
.
toJson
();
static
Find
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
return
new
Find
(
SearchSpecification
.
fromJson
(
json
));
}
static
_throwInvalidKeyValueType
(
String
invalidType
)
{
throw
new
DriverError
(
'Unsupported key value type
$invalidType
. Flutter Driver only supports
${_supportedKeyValueTypes.join(", ")}
'
);
}
}
/// Describes how to the driver should search for elements.
abstract
class
SearchSpecification
extends
Message
{
String
get
searchSpecType
;
static
SearchSpecification
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
String
searchSpecType
=
json
[
'searchSpecType'
];
switch
(
searchSpecType
)
{
case
'ByValueKey'
:
return
ByValueKey
.
fromJson
(
json
);
case
'ByTooltipMessage'
:
return
ByTooltipMessage
.
fromJson
(
json
);
case
'ByText'
:
return
ByText
.
fromJson
(
json
);
}
throw
new
DriverError
(
'Unsupported search specification type
$searchSpecType
'
);
}
Map
<
String
,
dynamic
>
toJson
()
=>
{
'searchSpecType'
:
searchSpecType
,
};
}
/// Tells [Find] to search by tooltip text.
class
ByTooltipMessage
extends
SearchSpecification
{
final
String
searchSpecType
=
'ByTooltipMessage'
;
ByTooltipMessage
(
this
.
text
);
/// Tooltip message text.
final
String
text
;
Map
<
String
,
dynamic
>
toJson
()
=>
super
.
toJson
()..
addAll
({
'text'
:
text
,
});
static
ByTooltipMessage
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
return
new
ByTooltipMessage
(
json
[
'text'
]);
}
}
/// Tells [Find] to search for `Text` widget by text.
class
ByText
extends
SearchSpecification
{
final
String
searchSpecType
=
'ByText'
;
ByText
(
this
.
text
);
final
String
text
;
Map
<
String
,
dynamic
>
toJson
()
=>
super
.
toJson
()..
addAll
({
'text'
:
text
,
});
static
ByText
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
return
new
ByText
(
json
[
'text'
]);
}
}
/// Tells [Find] to search by `ValueKey`.
class
ByValueKey
extends
SearchSpecification
{
final
String
searchSpecType
=
'ByValueKey'
;
ByValueKey
(
dynamic
keyValue
)
:
this
.
keyValue
=
keyValue
,
this
.
keyValueString
=
'
$keyValue
'
,
this
.
keyValueType
=
'
${keyValue.runtimeType}
'
{
...
...
@@ -30,19 +103,19 @@ class FindByValueKey extends Command {
/// May be one of "String", "int". The list of supported types may change.
final
String
keyValueType
;
Map
<
String
,
dynamic
>
toJson
()
=>
{
Map
<
String
,
dynamic
>
toJson
()
=>
super
.
toJson
()..
addAll
(
{
'keyValueString'
:
keyValueString
,
'keyValueType'
:
keyValueType
,
};
}
)
;
static
Find
ByValueKey
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
static
ByValueKey
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
String
keyValueString
=
json
[
'keyValueString'
];
String
keyValueType
=
json
[
'keyValueType'
];
switch
(
keyValueType
)
{
case
'int'
:
return
new
Find
ByValueKey
(
int
.
parse
(
keyValueString
));
return
new
ByValueKey
(
int
.
parse
(
keyValueString
));
case
'String'
:
return
new
Find
ByValueKey
(
keyValueString
);
return
new
ByValueKey
(
keyValueString
);
default
:
return
_throwInvalidKeyValueType
(
keyValueType
);
}
...
...
packages/flutter_driver/lib/src/retry.dart
View file @
6d35481c
...
...
@@ -8,13 +8,17 @@ import 'dart:async';
/// that evaluates to the result.
typedef
dynamic
Action
(
);
/// Determines if [value] is acceptable. For good style an implementation should
/// be idempotent.
typedef
bool
Predicate
(
dynamic
value
);
/// Performs [action] repeatedly until it either succeeds or [timeout] limit is
/// reached.
///
/// When the retry time out, the last seen error and stack trace are returned in
/// an error [Future].
Future
<
dynamic
>
retry
(
Action
action
,
Duration
timeout
,
Duration
pauseBetweenRetries
)
async
{
Duration
pauseBetweenRetries
,
{
Predicate
predicate
}
)
async
{
assert
(
action
!=
null
);
assert
(
timeout
!=
null
);
assert
(
pauseBetweenRetries
!=
null
);
...
...
@@ -28,20 +32,25 @@ Future<dynamic> retry(Action action, Duration timeout,
while
(!
success
&&
sw
.
elapsed
<
timeout
)
{
try
{
result
=
await
action
();
success
=
true
;
if
(
predicate
==
null
||
predicate
(
result
))
success
=
true
;
lastError
=
null
;
lastStackTrace
=
null
;
}
catch
(
error
,
stackTrace
)
{
lastError
=
error
;
lastStackTrace
=
stackTrace
;
if
(
sw
.
elapsed
<
timeout
)
{
await
new
Future
<
Null
>.
delayed
(
pauseBetweenRetries
);
}
}
if
(!
success
&&
sw
.
elapsed
<
timeout
)
await
new
Future
<
Null
>.
delayed
(
pauseBetweenRetries
);
}
if
(
success
)
return
result
;
else
else
if
(
lastError
!=
null
)
return
new
Future
.
error
(
lastError
,
lastStackTrace
);
else
return
new
Future
.
error
(
'Retry timed out'
);
}
/// A function that produces a [Stopwatch].
...
...
packages/flutter_driver/test/flutter_driver_test.dart
View file @
6d35481c
...
...
@@ -122,9 +122,10 @@ main() {
test
(
'finds by ValueKey'
,
()
async
{
when
(
mockIsolate
.
invokeExtension
(
any
,
any
)).
thenAnswer
((
Invocation
i
)
{
expect
(
i
.
positionalArguments
[
1
],
{
'kind'
:
'find_by_value_key'
,
'kind'
:
'find'
,
'searchSpecType'
:
'ByValueKey'
,
'keyValueString'
:
'foo'
,
'keyValueType'
:
'String'
,
'keyValueType'
:
'String'
});
return
new
Future
.
value
({
'objectReferenceKey'
:
'123'
,
...
...
packages/flutter_driver/test/retry_test.dart
View file @
6d35481c
...
...
@@ -51,6 +51,26 @@ main() {
});
});
test
(
'obeys predicates'
,
()
{
fakeAsync
.
run
((
_
)
{
int
retryCount
=
0
;
expect
(
// The predicate requires that the returned value is 2, so we expect
// that `retry` keeps trying until the counter reaches 2.
retry
(
()
async
=>
retryCount
++,
new
Duration
(
milliseconds:
30
),
new
Duration
(
milliseconds:
10
),
predicate:
(
value
)
=>
value
==
2
),
completion
(
2
)
);
fakeAsync
.
elapse
(
new
Duration
(
milliseconds:
50
));
});
});
test
(
'times out returning last error'
,
()
async
{
fakeAsync
.
run
((
_
)
{
bool
timedOut
=
false
;
...
...
packages/flutter_tools/lib/src/commands/analyze.dart
View file @
6d35481c
...
...
@@ -55,6 +55,20 @@ bool _addPackage(String directoryPath, List<String> dartFiles, Set<String> pubSp
}
}
Directory
testDriverDirectory
=
new
Directory
(
path
.
join
(
directoryPath
,
'test_driver'
));
if
(
testDriverDirectory
.
existsSync
())
{
for
(
FileSystemEntity
entry
in
testDriverDirectory
.
listSync
())
{
if
(
entry
is
Directory
)
{
for
(
FileSystemEntity
subentry
in
entry
.
listSync
())
{
if
(
isDartTestFile
(
subentry
))
dartFiles
.
add
(
subentry
.
path
);
}
}
else
if
(
isDartTestFile
(
entry
))
{
dartFiles
.
add
(
entry
.
path
);
}
}
}
Directory
benchmarkDirectory
=
new
Directory
(
path
.
join
(
directoryPath
,
'benchmark'
));
if
(
benchmarkDirectory
.
existsSync
())
{
for
(
FileSystemEntity
entry
in
benchmarkDirectory
.
listSync
())
{
...
...
@@ -76,6 +90,18 @@ bool _addPackage(String directoryPath, List<String> dartFiles, Set<String> pubSp
return
false
;
}
/// Adds all packages in [subPath], assuming a flat directory structure, i.e.
/// each direct child of [subPath] is a plain Dart package.
void
_addFlatPackageList
(
String
subPath
,
List
<
String
>
dartFiles
,
Set
<
String
>
pubSpecDirectories
)
{
Directory
subdirectory
=
new
Directory
(
path
.
join
(
ArtifactStore
.
flutterRoot
,
subPath
));
if
(
subdirectory
.
existsSync
())
{
for
(
FileSystemEntity
entry
in
subdirectory
.
listSync
())
{
if
(
entry
is
Directory
)
_addPackage
(
entry
.
path
,
dartFiles
,
pubSpecDirectories
);
}
}
}
class
FileChanged
{
}
class
AnalyzeCommand
extends
FlutterCommand
{
...
...
@@ -146,23 +172,10 @@ class AnalyzeCommand extends FlutterCommand {
//dev/manual_tests/*/ as package
//dev/manual_tests/*/ as files
Directory
subdirectory
;
subdirectory
=
new
Directory
(
path
.
join
(
ArtifactStore
.
flutterRoot
,
'packages'
));
if
(
subdirectory
.
existsSync
())
{
for
(
FileSystemEntity
entry
in
subdirectory
.
listSync
())
{
if
(
entry
is
Directory
)
_addPackage
(
entry
.
path
,
dartFiles
,
pubSpecDirectories
);
}
}
_addFlatPackageList
(
'packages'
,
dartFiles
,
pubSpecDirectories
);
_addFlatPackageList
(
'examples'
,
dartFiles
,
pubSpecDirectories
);
subdirectory
=
new
Directory
(
path
.
join
(
ArtifactStore
.
flutterRoot
,
'examples'
));
if
(
subdirectory
.
existsSync
())
{
for
(
FileSystemEntity
entry
in
subdirectory
.
listSync
())
{
if
(
entry
is
Directory
)
_addPackage
(
entry
.
path
,
dartFiles
,
pubSpecDirectories
);
}
}
Directory
subdirectory
;
subdirectory
=
new
Directory
(
path
.
join
(
ArtifactStore
.
flutterRoot
,
'examples'
,
'layers'
));
if
(
subdirectory
.
existsSync
())
{
...
...
@@ -198,7 +211,7 @@ class AnalyzeCommand extends FlutterCommand {
}
dartFiles
=
dartFiles
.
map
((
String
directory
)
=>
path
.
normalize
(
path
.
absolute
(
directory
))).
toSet
().
toList
();
dartFiles
=
dartFiles
.
map
((
String
directory
)
=>
path
.
normalize
(
path
.
absolute
(
directory
))).
toSet
().
toList
();
dartFiles
.
sort
();
// prepare a Dart file that references all the above Dart files
...
...
@@ -444,4 +457,3 @@ linter:
return
0
;
}
}
packages/flutter_tools/lib/src/commands/drive.dart
View file @
6d35481c
...
...
@@ -118,7 +118,7 @@ class DriveCommand extends RunCommandBase {
await
appStopper
(
this
);
}
catch
(
error
,
stackTrace
)
{
// TODO(yjbanov): remove this guard when this bug is fixed: https://github.com/dart-lang/sdk/issues/25862
print
Status
(
'Could not stop application:
$error
\n
$stackTrace
'
);
print
Trace
(
'Could not stop application:
$error
\n
$stackTrace
'
);
}
}
else
{
printStatus
(
'Leaving the application running.'
);
...
...
packages/flutter_tools/templates/create/lib/main.dart.tmpl
View file @
6d35481c
import 'package:flutter/material.dart';
{{#withDriverTest?}}
import 'package:flutter_driver/driver_extension.dart';
{{/withDriverTest?}}
void main() {
{{#withDriverTest?}}
// Starts the app with Flutter Driver extension enabled to allow Flutter Driver
// to test the app.
enableFlutterDriverExtension();
{{/withDriverTest?}}
runApp(
new MaterialApp(
title: 'Flutter Demo',
...
...
packages/flutter_tools/templates/driver/e2e.dart.tmpl
deleted
100644 → 0
View file @
6a1f47a5
// Starts the app with Flutter Driver extension enabled to allow Flutter Driver
// to test the app.
import 'package:{{projectName}}/main.dart' as app;
import 'package:flutter_driver/driver_extension.dart';
main() {
enableFlutterDriverExtension();
app.main();
}
packages/flutter_tools/templates/driver/
e2e
_test.dart.tmpl
→
packages/flutter_tools/templates/driver/
main
_test.dart.tmpl
View file @
6d35481c
...
...
@@ -22,28 +22,20 @@ main() {
});
tearDownAll(() async {
if (driver != null) driver.close();
});
test('find the floating action button by value key', () async {
ObjectRef elem = await driver.findByValueKey('fab');
expect(elem, isNotNull);
expect(elem.objectReferenceKey, isNotNull);
if (driver != null)
driver.close();
});
test('tap on the floating action button; verify counter', () async {
// Find floating action button (fab) to tap on
ObjectRef fab = await driver.findBy
ValueKey('fab
');
ObjectRef fab = await driver.findBy
TooltipMessage('Increment
');
expect(fab, isNotNull);
// Tap on the fab
await driver.tap(fab);
// Wait for text to change to the desired value
await driver.waitFor(() async {
ObjectRef counter = await driver.findByValueKey('counter');
return await driver.getText(counter);
}, contains("Button tapped 1 times."));
expect(await driver.findByText('Button tapped 1 time.'), isNotNull);
});
});
}
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