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
41646c95
Unverified
Commit
41646c95
authored
Jul 09, 2018
by
Jonah Williams
Committed by
GitHub
Jul 09, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new matcher and utility methods for testing semanics (#19046)
parent
32941a8c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
528 additions
and
77 deletions
+528
-77
back_button_test.dart
packages/flutter/test/material/back_button_test.dart
+32
-0
checkbox_test.dart
packages/flutter/test/material/checkbox_test.dart
+34
-77
matchers.dart
packages/flutter_test/lib/src/matchers.dart
+241
-0
widget_tester.dart
packages/flutter_test/lib/src/widget_tester.dart
+41
-0
matchers_test.dart
packages/flutter_test/test/matchers_test.dart
+93
-0
widget_tester_test.dart
packages/flutter_test/test/widget_tester_test.dart
+87
-0
No files found.
packages/flutter/test/material/back_button_test.dart
View file @
41646c95
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
...
...
@@ -59,4 +60,35 @@ void main() {
final
Icon
androidIcon
=
tester
.
widget
(
find
.
descendant
(
of:
find
.
byKey
(
androidKey
),
matching:
find
.
byType
(
Icon
)));
expect
(
iOSIcon
==
androidIcon
,
false
);
});
testWidgets
(
'BackButton semantics'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
handle
=
tester
.
ensureSemantics
();
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
const
Material
(
child:
const
Text
(
'Home'
)),
routes:
<
String
,
WidgetBuilder
>{
'/next'
:
(
BuildContext
context
)
{
return
const
Material
(
child:
const
Center
(
child:
const
BackButton
(),
),
);
},
},
),
);
tester
.
state
<
NavigatorState
>(
find
.
byType
(
Navigator
)).
pushNamed
(
'/next'
);
await
tester
.
pumpAndSettle
();
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
BackButton
)),
matchesSemanticsData
(
label:
'Back'
,
isButton:
true
,
hasEnabledState:
true
,
isEnabled:
true
,
hasTapAction:
true
,
));
handle
.
dispose
();
});
}
packages/flutter/test/material/checkbox_test.dart
View file @
41646c95
...
...
@@ -57,7 +57,7 @@ void main() {
});
testWidgets
(
'CheckBox semantics'
,
(
WidgetTester
tester
)
async
{
final
Semantics
Tester
semantics
=
new
SemanticsTester
(
tester
);
final
Semantics
Handle
handle
=
tester
.
ensureSemantics
(
);
await
tester
.
pumpWidget
(
new
Material
(
child:
new
Checkbox
(
...
...
@@ -66,21 +66,12 @@ void main() {
),
));
expect
(
semantics
,
hasSemantics
(
new
TestSemantics
.
root
(
children:
<
TestSemantics
>[
new
TestSemantics
.
rootChild
(
id:
1
,
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
hasCheckedState
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
,
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
,
],
),
],
),
ignoreRect:
true
,
ignoreTransform:
true
));
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
Checkbox
)),
matchesSemanticsData
(
hasCheckedState:
true
,
hasEnabledState:
true
,
isEnabled:
true
,
hasTapAction:
true
,
));
await
tester
.
pumpWidget
(
new
Material
(
child:
new
Checkbox
(
...
...
@@ -89,22 +80,13 @@ void main() {
),
));
expect
(
semantics
,
hasSemantics
(
new
TestSemantics
.
root
(
children:
<
TestSemantics
>[
new
TestSemantics
.
rootChild
(
id:
1
,
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
hasCheckedState
,
SemanticsFlag
.
isChecked
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
,
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
,
],
),
],
),
ignoreRect:
true
,
ignoreTransform:
true
));
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
Checkbox
)),
matchesSemanticsData
(
hasCheckedState:
true
,
hasEnabledState:
true
,
isChecked:
true
,
isEnabled:
true
,
hasTapAction:
true
,
));
await
tester
.
pumpWidget
(
const
Material
(
child:
const
Checkbox
(
...
...
@@ -113,17 +95,10 @@ void main() {
),
));
expect
(
semantics
,
hasSemantics
(
new
TestSemantics
.
root
(
children:
<
TestSemantics
>[
new
TestSemantics
.
rootChild
(
id:
1
,
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
hasCheckedState
,
SemanticsFlag
.
hasEnabledState
,
],
),
],
),
ignoreRect:
true
,
ignoreTransform:
true
));
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
Checkbox
)),
matchesSemanticsData
(
hasCheckedState:
true
,
hasEnabledState:
true
,
));
await
tester
.
pumpWidget
(
const
Material
(
child:
const
Checkbox
(
...
...
@@ -132,24 +107,16 @@ void main() {
),
));
expect
(
semantics
,
hasSemantics
(
new
TestSemantics
.
root
(
children:
<
TestSemantics
>[
new
TestSemantics
.
rootChild
(
id:
1
,
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
hasCheckedState
,
SemanticsFlag
.
isChecked
,
SemanticsFlag
.
hasEnabledState
,
],
),
],
),
ignoreRect:
true
,
ignoreTransform:
true
));
semantics
.
dispose
();
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
Checkbox
)),
matchesSemanticsData
(
hasCheckedState:
true
,
hasEnabledState:
true
,
isChecked:
true
,
));
handle
.
dispose
();
});
testWidgets
(
'Can wrap CheckBox with Semantics'
,
(
WidgetTester
tester
)
async
{
final
Semantics
Tester
semantics
=
new
SemanticsTester
(
tester
);
final
Semantics
Handle
handle
=
tester
.
ensureSemantics
(
);
await
tester
.
pumpWidget
(
new
Material
(
child:
new
Semantics
(
...
...
@@ -162,25 +129,15 @@ void main() {
),
));
expect
(
semantics
,
hasSemantics
(
new
TestSemantics
.
root
(
children:
<
TestSemantics
>[
new
TestSemantics
.
rootChild
(
id:
1
,
label:
'foo'
,
textDirection:
TextDirection
.
ltr
,
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
hasCheckedState
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
,
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
,
],
),
],
),
ignoreRect:
true
,
ignoreTransform:
true
));
semantics
.
dispose
();
expect
(
tester
.
getSemanticsData
(
find
.
byType
(
Checkbox
)),
matchesSemanticsData
(
label:
'foo'
,
textDirection:
TextDirection
.
ltr
,
hasCheckedState:
true
,
hasEnabledState:
true
,
isEnabled:
true
,
hasTapAction:
true
,
));
handle
.
dispose
();
});
testWidgets
(
'CheckBox tristate: true'
,
(
WidgetTester
tester
)
async
{
...
...
packages/flutter_test/lib/src/matchers.dart
View file @
41646c95
...
...
@@ -5,6 +5,7 @@
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
;
import
'package:meta/meta.dart'
;
import
'package:test/test.dart'
hide
TypeMatcher
,
isInstanceOf
;
...
...
@@ -277,6 +278,145 @@ Matcher matchesGoldenFile(dynamic key) {
throw
new
ArgumentError
(
'Unexpected type for golden file:
${key.runtimeType}
'
);
}
/// Asserts that a [SemanticsData] contains the specified information.
///
/// If either the label, hint, value, textDirection, or rect fields are not
/// provided, then they are not part of the comparison. All of the boolean
/// flag and action fields must match, and default to false.
///
/// To retrieve the semantics data of a widget, use [tester.getSemanticsData]
/// with a [Finder] that returns a single widget. Semantics must be enabled
/// in order to use this method.
///
/// ## Sample code
///
/// ```dart
/// final SemanticsHandle handle = tester.ensureSemantics();
/// final SemanticsData data = tester.getSemanticsData(find.text('hello'));
/// expect(data, matchesSemanticsData(label: 'hello'));
/// handle.dispose();
/// ```
///
/// See also:
///
/// * [WidgetTester.getSemanticsData], the tester method which retrieves data.
Matcher
matchesSemanticsData
(
{
String
label
,
String
hint
,
String
value
,
TextDirection
textDirection
,
Rect
rect
,
// Flags //
bool
hasCheckedState
=
false
,
bool
isChecked
=
false
,
bool
isSelected
=
false
,
bool
isButton
=
false
,
bool
isFocused
=
false
,
bool
isTextField
=
false
,
bool
hasEnabledState
=
false
,
bool
isEnabled
=
false
,
bool
isInMutuallyExclusiveGroup
=
false
,
bool
isHeader
=
false
,
bool
isObscured
=
false
,
bool
namesRoute
=
false
,
bool
scopesRoute
=
false
,
bool
isHidden
=
false
,
// Actions //
bool
hasTapAction
=
false
,
bool
hasLongPressAction
=
false
,
bool
hasScrollLeftAction
=
false
,
bool
hasScrollRightAction
=
false
,
bool
hasScrollUpAction
=
false
,
bool
hasScrollDownAction
=
false
,
bool
hasIncreaseAction
=
false
,
bool
hasDecreaseAction
=
false
,
bool
hasShowOnScreenAction
=
false
,
bool
hasMoveCursorForwardByCharacterAction
=
false
,
bool
hasMoveCursorBackwardByCharacterAction
=
false
,
bool
hasSetSelectionAction
=
false
,
bool
hasCopyAction
=
false
,
bool
hasCutAction
=
false
,
bool
hasPasteAction
=
false
,
bool
hasDidGainAccessibilityFocusAction
=
false
,
bool
hasDidLoseAccessibilityFocusAction
=
false
,
})
{
final
List
<
SemanticsFlag
>
flags
=
<
SemanticsFlag
>[];
if
(
hasCheckedState
)
flags
.
add
(
SemanticsFlag
.
hasCheckedState
);
if
(
isChecked
)
flags
.
add
(
SemanticsFlag
.
isChecked
);
if
(
isSelected
)
flags
.
add
(
SemanticsFlag
.
isSelected
);
if
(
isButton
)
flags
.
add
(
SemanticsFlag
.
isButton
);
if
(
isTextField
)
flags
.
add
(
SemanticsFlag
.
isTextField
);
if
(
isFocused
)
flags
.
add
(
SemanticsFlag
.
isFocused
);
if
(
hasEnabledState
)
flags
.
add
(
SemanticsFlag
.
hasEnabledState
);
if
(
isEnabled
)
flags
.
add
(
SemanticsFlag
.
isEnabled
);
if
(
isInMutuallyExclusiveGroup
)
flags
.
add
(
SemanticsFlag
.
isInMutuallyExclusiveGroup
);
if
(
isHeader
)
flags
.
add
(
SemanticsFlag
.
isHeader
);
if
(
isObscured
)
flags
.
add
(
SemanticsFlag
.
isObscured
);
if
(
namesRoute
)
flags
.
add
(
SemanticsFlag
.
namesRoute
);
if
(
scopesRoute
)
flags
.
add
(
SemanticsFlag
.
scopesRoute
);
if
(
isHidden
)
flags
.
add
(
SemanticsFlag
.
isHidden
);
final
List
<
SemanticsAction
>
actions
=
<
SemanticsAction
>[];
if
(
hasTapAction
)
actions
.
add
(
SemanticsAction
.
tap
);
if
(
hasLongPressAction
)
actions
.
add
(
SemanticsAction
.
longPress
);
if
(
hasScrollLeftAction
)
actions
.
add
(
SemanticsAction
.
scrollLeft
);
if
(
hasScrollRightAction
)
actions
.
add
(
SemanticsAction
.
scrollRight
);
if
(
hasScrollUpAction
)
actions
.
add
(
SemanticsAction
.
scrollUp
);
if
(
hasScrollDownAction
)
actions
.
add
(
SemanticsAction
.
scrollDown
);
if
(
hasIncreaseAction
)
actions
.
add
(
SemanticsAction
.
increase
);
if
(
hasDecreaseAction
)
actions
.
add
(
SemanticsAction
.
decrease
);
if
(
hasShowOnScreenAction
)
actions
.
add
(
SemanticsAction
.
showOnScreen
);
if
(
hasMoveCursorForwardByCharacterAction
)
actions
.
add
(
SemanticsAction
.
moveCursorForwardByCharacter
);
if
(
hasMoveCursorBackwardByCharacterAction
)
actions
.
add
(
SemanticsAction
.
moveCursorBackwardByCharacter
);
if
(
hasSetSelectionAction
)
actions
.
add
(
SemanticsAction
.
setSelection
);
if
(
hasCopyAction
)
actions
.
add
(
SemanticsAction
.
copy
);
if
(
hasCutAction
)
actions
.
add
(
SemanticsAction
.
cut
);
if
(
hasPasteAction
)
actions
.
add
(
SemanticsAction
.
paste
);
if
(
hasDidGainAccessibilityFocusAction
)
actions
.
add
(
SemanticsAction
.
didGainAccessibilityFocus
);
if
(
hasDidLoseAccessibilityFocusAction
)
actions
.
add
(
SemanticsAction
.
didLoseAccessibilityFocus
);
return
new
_MatchesSemanticsData
(
label:
label
,
hint:
hint
,
value:
value
,
actions:
actions
,
flags:
flags
,
textDirection:
textDirection
,
rect:
rect
,
);
}
class
_FindsWidgetMatcher
extends
Matcher
{
const
_FindsWidgetMatcher
(
this
.
min
,
this
.
max
);
...
...
@@ -1293,3 +1433,104 @@ class _MatchesGoldenFile extends AsyncMatcher {
Description
describe
(
Description
description
)
=>
description
.
add
(
'one widget whose rasterized image matches golden image "
$key
"'
);
}
class
_MatchesSemanticsData
extends
Matcher
{
_MatchesSemanticsData
({
this
.
label
,
this
.
value
,
this
.
hint
,
this
.
flags
,
this
.
actions
,
this
.
textDirection
,
this
.
rect
,
});
final
String
label
;
final
String
value
;
final
String
hint
;
final
List
<
SemanticsAction
>
actions
;
final
List
<
SemanticsFlag
>
flags
;
final
TextDirection
textDirection
;
final
Rect
rect
;
@override
Description
describe
(
Description
description
)
{
description
.
add
(
'has semantics'
);
if
(
label
!=
null
)
description
.
add
(
'with label:
$label
'
);
if
(
value
!=
null
)
description
.
add
(
'with value:
$value
'
);
if
(
hint
!=
null
)
description
.
add
(
'with hint:
$hint
'
);
if
(
actions
!=
null
)
description
.
add
(
'with actions:'
).
addDescriptionOf
(
actions
);
if
(
flags
!=
null
)
description
.
add
(
'with flags:'
).
addDescriptionOf
(
flags
);
if
(
textDirection
!=
null
)
description
.
add
(
'with textDirection:
$textDirection
'
);
if
(
rect
!=
null
)
description
.
add
(
'with rect:
$rect
'
);
return
description
;
}
@override
bool
matches
(
covariant
SemanticsData
data
,
Map
<
dynamic
,
dynamic
>
matchState
)
{
if
(
data
==
null
)
return
failWithDescription
(
matchState
,
'No SemanticsData provided. '
'Maybe you forgot to enabled semantics?'
);
if
(
label
!=
null
&&
label
!=
data
.
label
)
return
failWithDescription
(
matchState
,
'label was:
${data.label}
'
);
if
(
hint
!=
null
&&
hint
!=
data
.
hint
)
return
failWithDescription
(
matchState
,
'hint was:
${data.hint}
'
);
if
(
value
!=
null
&&
value
!=
data
.
value
)
return
failWithDescription
(
matchState
,
'value was:
${data.value}
'
);
if
(
textDirection
!=
null
&&
textDirection
!=
data
.
textDirection
)
return
failWithDescription
(
matchState
,
'textDirection was:
$textDirection
'
);
if
(
rect
!=
null
&&
rect
==
data
.
rect
)
{
return
failWithDescription
(
matchState
,
'rect was:
$rect
'
);
}
if
(
actions
!=
null
)
{
int
actionBits
=
0
;
for
(
SemanticsAction
action
in
actions
)
actionBits
|=
action
.
index
;
if
(
actionBits
!=
data
.
actions
)
{
final
List
<
String
>
actionSummary
=
<
String
>[];
for
(
SemanticsAction
action
in
SemanticsAction
.
values
.
values
)
{
if
((
data
.
actions
&
action
.
index
)
!=
0
)
actionSummary
.
add
(
describeEnum
(
action
));
}
return
failWithDescription
(
matchState
,
'actions were:
$actionSummary
'
);
}
}
if
(
flags
!=
null
)
{
int
flagBits
=
0
;
for
(
SemanticsFlag
flag
in
flags
)
flagBits
|=
flag
.
index
;
if
(
flagBits
!=
data
.
flags
)
{
final
List
<
String
>
flagSummary
=
<
String
>[];
for
(
SemanticsFlag
flag
in
SemanticsFlag
.
values
.
values
)
{
if
((
data
.
flags
&
flag
.
index
)
!=
0
)
flagSummary
.
add
(
describeEnum
(
flag
));
}
return
failWithDescription
(
matchState
,
'flags were:
$flagSummary
'
);
}
}
return
true
;
}
bool
failWithDescription
(
Map
<
dynamic
,
dynamic
>
matchState
,
String
description
)
{
matchState
[
'failure'
]
=
description
;
return
false
;
}
@override
Description
describeMismatch
(
dynamic
item
,
Description
mismatchDescription
,
Map
<
dynamic
,
dynamic
>
matchState
,
bool
verbose
)
{
return
mismatchDescription
.
add
(
matchState
[
'failure'
]);
}
}
\ No newline at end of file
packages/flutter_test/lib/src/widget_tester.dart
View file @
41646c95
...
...
@@ -21,6 +21,9 @@ import 'matchers.dart';
import
'test_async_utils.dart'
;
import
'test_text_input.dart'
;
/// Keep users from needing multiple imports to test semantics.
export
'package:flutter/rendering.dart'
show
SemanticsHandle
;
export
'package:test/test.dart'
hide
expect
,
// we have our own wrapper below
TypeMatcher
,
// matcher's TypeMatcher conflicts with the one in the Flutter framework
...
...
@@ -611,6 +614,44 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
await
tap
(
backButton
);
}
/// Attempts to find the [SemanticsData] of first result from `finder`.
///
/// If the object identified by the finder doesn't own it's semantic node,
/// this will return the semantics data of the first ancestor with semantics
/// data. The ancestor's semantic data will include the child's as well as
/// other nodes that have been merged together.
///
/// Will throw a [StateError] if the finder returns more than one element or
/// if no semantics are found or are not enabled.
SemanticsData
getSemanticsData
(
Finder
finder
)
{
if
(
binding
.
pipelineOwner
.
semanticsOwner
==
null
)
throw
new
StateError
(
'Semantics are not enabled.'
);
final
Iterable
<
Element
>
candidates
=
finder
.
evaluate
();
if
(
candidates
.
isEmpty
)
{
throw
new
StateError
(
'Finder returned no matching elements.'
);
}
if
(
candidates
.
length
>
1
)
{
throw
new
StateError
(
'Finder returned more than one element.'
);
}
final
Element
element
=
candidates
.
single
;
RenderObject
renderObject
=
element
.
findRenderObject
();
SemanticsNode
result
=
renderObject
.
debugSemantics
;
while
(
renderObject
!=
null
&&
result
==
null
)
{
renderObject
=
renderObject
?.
parent
;
result
=
renderObject
?.
debugSemantics
;
}
if
(
result
==
null
)
throw
new
StateError
(
'No Semantics data found.'
);
return
result
.
getSemanticsData
();
}
/// Enable semantics in a test by creating a [SemanticsHandle].
///
/// The handle must be disposed at the end of the test.
SemanticsHandle
ensureSemantics
()
{
return
binding
.
pipelineOwner
.
ensureSemantics
();
}
}
typedef
void
_TickerDisposeCallback
(
_TestTicker
ticker
);
...
...
packages/flutter_test/test/matchers_test.dart
View file @
41646c95
...
...
@@ -5,6 +5,7 @@
import
'dart:typed_data'
;
import
'dart:ui'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
@@ -382,6 +383,98 @@ void main() {
autoUpdateGoldenFiles
=
false
;
});
});
group
(
'matchesSemanticsData'
,
()
{
testWidgets
(
'matches SemanticsData'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
handle
=
tester
.
ensureSemantics
();
const
Key
key
=
const
Key
(
'semantics'
);
await
tester
.
pumpWidget
(
new
Semantics
(
key:
key
,
namesRoute:
true
,
header:
true
,
button:
true
,
onTap:
()
{},
label:
'foo'
,
hint:
'bar'
,
value:
'baz'
,
textDirection:
TextDirection
.
rtl
,
));
expect
(
tester
.
getSemanticsData
(
find
.
byKey
(
key
)),
matchesSemanticsData
(
label:
'foo'
,
hint:
'bar'
,
value:
'baz'
,
textDirection:
TextDirection
.
rtl
,
hasTapAction:
true
,
isButton:
true
,
isHeader:
true
,
namesRoute:
true
,
),
);
handle
.
dispose
();
});
testWidgets
(
'Can match all semantics flags and actions'
,
(
WidgetTester
tester
)
async
{
int
actions
=
0
;
int
flags
=
0
;
for
(
int
index
in
SemanticsAction
.
values
.
keys
)
actions
|=
index
;
for
(
int
index
in
SemanticsFlag
.
values
.
keys
)
flags
|=
index
;
final
SemanticsData
data
=
new
SemanticsData
(
flags:
flags
,
actions:
actions
,
label:
''
,
increasedValue:
''
,
value:
''
,
decreasedValue:
''
,
hint:
''
,
textDirection:
TextDirection
.
ltr
,
rect:
Rect
.
fromLTRB
(
0.0
,
0.0
,
10.0
,
10.0
),
textSelection:
null
,
scrollPosition:
null
,
scrollExtentMax:
null
,
scrollExtentMin:
null
,
);
expect
(
data
,
matchesSemanticsData
(
/* Flags */
hasCheckedState:
true
,
isChecked:
true
,
isSelected:
true
,
isButton:
true
,
isTextField:
true
,
hasEnabledState:
true
,
isFocused:
true
,
isEnabled:
true
,
isInMutuallyExclusiveGroup:
true
,
isHeader:
true
,
isObscured:
true
,
namesRoute:
true
,
scopesRoute:
true
,
isHidden:
true
,
/* Actions */
hasTapAction:
true
,
hasLongPressAction:
true
,
hasScrollLeftAction:
true
,
hasScrollRightAction:
true
,
hasScrollUpAction:
true
,
hasScrollDownAction:
true
,
hasIncreaseAction:
true
,
hasDecreaseAction:
true
,
hasShowOnScreenAction:
true
,
hasMoveCursorForwardByCharacterAction:
true
,
hasMoveCursorBackwardByCharacterAction:
true
,
hasSetSelectionAction:
true
,
hasCopyAction:
true
,
hasCutAction:
true
,
hasPasteAction:
true
,
hasDidGainAccessibilityFocusAction:
true
,
hasDidLoseAccessibilityFocusAction:
true
,
));
});
});
}
enum
_ComparatorBehavior
{
...
...
packages/flutter_test/test/widget_tester_test.dart
View file @
41646c95
...
...
@@ -4,9 +4,11 @@
import
'dart:async'
;
import
'dart:io'
;
import
'dart:ui'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:test/test.dart'
as
test_package
;
import
'package:test/src/frontend/async_matcher.dart'
show
AsyncMatcher
;
...
...
@@ -527,6 +529,91 @@ void main() {
await
tester
.
showKeyboard
(
find
.
byType
(
TextField
));
await
tester
.
pump
();
});
group
(
'getSemanticsData'
,
()
{
testWidgets
(
'throws when there are no semantics'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
const
Scaffold
(
body:
const
Text
(
'hello'
),
),
),
);
expect
(()
=>
tester
.
getSemanticsData
(
find
.
text
(
'hello'
)),
throwsA
(
isInstanceOf
<
StateError
>()));
});
testWidgets
(
'throws when there are multiple results from the finder'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
semanticsHandle
=
tester
.
ensureSemantics
();
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
body:
new
Row
(
children:
const
<
Widget
>[
const
Text
(
'hello'
),
const
Text
(
'hello'
),
],
),
),
),
);
expect
(()
=>
tester
.
getSemanticsData
(
find
.
text
(
'hello'
)),
throwsA
(
isInstanceOf
<
StateError
>()));
semanticsHandle
.
dispose
();
});
testWidgets
(
'Returns the correct SemanticsData'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
semanticsHandle
=
tester
.
ensureSemantics
();
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
body:
new
Container
(
child:
new
OutlineButton
(
onPressed:
()
{},
child:
const
Text
(
'hello'
)
),
),
),
),
);
final
SemanticsData
semantics
=
tester
.
getSemanticsData
(
find
.
text
(
'hello'
));
expect
(
semantics
.
label
,
'hello'
);
expect
(
semantics
.
hasAction
(
SemanticsAction
.
tap
),
true
);
expect
(
semantics
.
hasFlag
(
SemanticsFlag
.
isButton
),
true
);
semanticsHandle
.
dispose
();
});
testWidgets
(
'Returns merged SemanticsData'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
semanticsHandle
=
tester
.
ensureSemantics
();
const
Key
key
=
const
Key
(
'test'
);
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
body:
new
Semantics
(
label:
'A'
,
child:
new
Semantics
(
label:
'B'
,
child:
new
Semantics
(
key:
key
,
label:
'C'
,
child:
new
Container
(),
),
),
)
),
),
);
final
SemanticsData
semantics
=
tester
.
getSemanticsData
(
find
.
byKey
(
key
));
expect
(
semantics
.
label
,
'A
\n
B
\n
C'
);
semanticsHandle
.
dispose
();
});
});
}
class
FakeMatcher
extends
AsyncMatcher
{
...
...
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