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
0df0e2ea
Unverified
Commit
0df0e2ea
authored
Sep 12, 2022
by
chunhtai
Committed by
GitHub
Sep 12, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate android_semantics_testing to null safety (#111420)
parent
e3b9223a
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
81 additions
and
80 deletions
+81
-80
main.dart
...integration_tests/android_semantics_testing/lib/main.dart
+6
-6
common.dart
...ation_tests/android_semantics_testing/lib/src/common.dart
+11
-10
constants.dart
...on_tests/android_semantics_testing/lib/src/constants.dart
+2
-2
matcher.dart
...tion_tests/android_semantics_testing/lib/src/matcher.dart
+42
-42
controls_page.dart
...ndroid_semantics_testing/lib/src/tests/controls_page.dart
+5
-5
headings_page.dart
...ndroid_semantics_testing/lib/src/tests/headings_page.dart
+1
-1
popup_page.dart
...s/android_semantics_testing/lib/src/tests/popup_page.dart
+3
-3
text_field_page.dart
...roid_semantics_testing/lib/src/tests/text_field_page.dart
+1
-1
pubspec.yaml
dev/integration_tests/android_semantics_testing/pubspec.yaml
+1
-1
main_test.dart
...ests/android_semantics_testing/test_driver/main_test.dart
+9
-9
No files found.
dev/integration_tests/android_semantics_testing/lib/main.dart
View file @
0df0e2ea
...
...
@@ -23,11 +23,11 @@ void main() {
const
MethodChannel
kSemanticsChannel
=
MethodChannel
(
'semantics'
);
Future
<
String
>
dataHandler
(
String
message
)
async
{
if
(
message
.
contains
(
'getSemanticsNode'
))
{
Future
<
String
>
dataHandler
(
String
?
message
)
async
{
if
(
message
!=
null
&&
message
.
contains
(
'getSemanticsNode'
))
{
final
Completer
<
String
>
completer
=
Completer
<
String
>();
final
int
id
=
int
.
tryParse
(
message
.
split
(
'#'
)[
1
])
??
0
;
Future
<
void
>
completeSemantics
([
Object
_
])
async
{
Future
<
void
>
completeSemantics
([
Object
?
_
])
async
{
final
dynamic
result
=
await
kSemanticsChannel
.
invokeMethod
<
dynamic
>(
'getSemanticsNode'
,
<
String
,
dynamic
>{
'id'
:
id
,
});
...
...
@@ -40,10 +40,10 @@ Future<String> dataHandler(String message) async {
}
return
completer
.
future
;
}
if
(
message
.
contains
(
'setClipboard'
))
{
if
(
message
!=
null
&&
message
.
contains
(
'setClipboard'
))
{
final
Completer
<
String
>
completer
=
Completer
<
String
>();
final
String
str
=
message
.
split
(
'#'
)[
1
];
Future
<
void
>
completeSetClipboard
([
Object
_
])
async
{
Future
<
void
>
completeSetClipboard
([
Object
?
_
])
async
{
await
kSemanticsChannel
.
invokeMethod
<
dynamic
>(
'setClipboard'
,
<
String
,
dynamic
>{
'message'
:
str
,
});
...
...
@@ -67,7 +67,7 @@ Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
};
class
TestApp
extends
StatelessWidget
{
const
TestApp
({
Key
key
})
:
super
(
key:
key
);
const
TestApp
({
super
.
key
}
);
@override
Widget
build
(
BuildContext
context
)
{
...
...
dev/integration_tests/android_semantics_testing/lib/src/common.dart
View file @
0df0e2ea
...
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: avoid_dynamic_calls
import
'dart:convert'
;
import
'package:meta/meta.dart'
;
...
...
@@ -53,13 +55,13 @@ class AndroidSemanticsNode {
/// ]
/// }
factory
AndroidSemanticsNode
.
deserialize
(
String
value
)
{
return
AndroidSemanticsNode
.
_
(
json
.
decode
(
value
)
as
Map
<
String
,
Object
>
);
return
AndroidSemanticsNode
.
_
(
json
.
decode
(
value
));
}
final
Map
<
String
,
Object
>
_values
;
final
dynamic
_values
;
final
List
<
AndroidSemanticsNode
>
_children
=
<
AndroidSemanticsNode
>[];
Map
<
String
,
Object
>
get
_flags
=>
_values
[
'flags'
]
as
Map
<
String
,
Object
>
;
dynamic
get
_flags
=>
_values
[
'flags'
]
;
/// The text value of the semantics node.
///
...
...
@@ -132,13 +134,12 @@ class AndroidSemanticsNode {
/// Gets a [Rect] which defines the position and size of the semantics node.
Rect
getRect
()
{
final
Map
<
String
,
Object
>
rawRect
=
_values
[
'rect'
]
as
Map
<
String
,
Object
>;
final
Map
<
String
,
int
>
rect
=
rawRect
.
cast
<
String
,
int
>();
final
dynamic
rawRect
=
_values
[
'rect'
];
return
Rect
.
fromLTRB
(
rect
[
'left'
]
.
toDouble
(),
rect
[
'top'
]
.
toDouble
(),
rect
[
'right'
]
.
toDouble
(),
rect
[
'bottom'
]
.
toDouble
(),
(
rawRect
[
'left'
]!
as
int
)
.
toDouble
(),
(
rawRect
[
'top'
]!
as
int
)
.
toDouble
(),
(
rawRect
[
'right'
]!
as
int
)
.
toDouble
(),
(
rawRect
[
'bottom'
]!
as
int
)
.
toDouble
(),
);
}
...
...
@@ -150,7 +151,7 @@ class AndroidSemanticsNode {
/// Gets a list of [AndroidSemanticsActions] which are defined for the node.
List
<
AndroidSemanticsAction
>
getActions
()
=>
<
AndroidSemanticsAction
>[
for
(
final
int
id
in
(
_values
[
'actions'
]
as
List
<
dynamic
>).
cast
<
int
>())
AndroidSemanticsAction
.
deserialize
(
id
)
,
for
(
final
int
id
in
(
_values
[
'actions'
]
!
as
List
<
dynamic
>).
cast
<
int
>())
AndroidSemanticsAction
.
deserialize
(
id
)!
,
];
@override
...
...
dev/integration_tests/android_semantics_testing/lib/src/constants.dart
View file @
0df0e2ea
...
...
@@ -168,7 +168,7 @@ class AndroidSemanticsAction {
case
_kSetText:
return
'AndroidSemanticsAction.setText'
;
default
:
return
null
;
throw
UnimplementedError
()
;
}
}
...
...
@@ -211,7 +211,7 @@ class AndroidSemanticsAction {
/// Creates a new [AndroidSemanticsAction] from an integer `value`.
///
/// Returns `null` if the id is not a known Android accessibility action.
static
AndroidSemanticsAction
deserialize
(
int
value
)
{
static
AndroidSemanticsAction
?
deserialize
(
int
value
)
{
return
_kActionById
[
value
];
}
}
dev/integration_tests/android_semantics_testing/lib/src/matcher.dart
View file @
0df0e2ea
...
...
@@ -18,24 +18,24 @@ import 'constants.dart';
/// the Android accessibility bridge, and not the semantics object created by
/// the Flutter framework.
Matcher
hasAndroidSemantics
(
{
String
text
,
String
contentDescription
,
String
className
,
int
id
,
Rect
rect
,
Size
size
,
List
<
AndroidSemanticsAction
>
actions
,
List
<
AndroidSemanticsAction
>
ignoredActions
,
List
<
AndroidSemanticsNode
>
children
,
bool
isChecked
,
bool
isCheckable
,
bool
isEditable
,
bool
isEnabled
,
bool
isFocusable
,
bool
isFocused
,
bool
isHeading
,
bool
isPassword
,
bool
isLongClickable
,
String
?
text
,
String
?
contentDescription
,
String
?
className
,
int
?
id
,
Rect
?
rect
,
Size
?
size
,
List
<
AndroidSemanticsAction
>
?
actions
,
List
<
AndroidSemanticsAction
>
?
ignoredActions
,
List
<
AndroidSemanticsNode
>
?
children
,
bool
?
isChecked
,
bool
?
isCheckable
,
bool
?
isEditable
,
bool
?
isEnabled
,
bool
?
isFocusable
,
bool
?
isFocused
,
bool
?
isHeading
,
bool
?
isPassword
,
bool
?
isLongClickable
,
})
{
return
_AndroidSemanticsMatcher
(
text:
text
,
...
...
@@ -79,23 +79,23 @@ class _AndroidSemanticsMatcher extends Matcher {
this
.
isLongClickable
,
});
final
String
text
;
final
String
className
;
final
String
contentDescription
;
final
int
id
;
final
List
<
AndroidSemanticsAction
>
actions
;
final
List
<
AndroidSemanticsAction
>
ignoredActions
;
final
Rect
rect
;
final
Size
size
;
final
bool
isChecked
;
final
bool
isCheckable
;
final
bool
isEditable
;
final
bool
isEnabled
;
final
bool
isFocusable
;
final
bool
isFocused
;
final
bool
isHeading
;
final
bool
isPassword
;
final
bool
isLongClickable
;
final
String
?
text
;
final
String
?
className
;
final
String
?
contentDescription
;
final
int
?
id
;
final
List
<
AndroidSemanticsAction
>
?
actions
;
final
List
<
AndroidSemanticsAction
>
?
ignoredActions
;
final
Rect
?
rect
;
final
Size
?
size
;
final
bool
?
isChecked
;
final
bool
?
isCheckable
;
final
bool
?
isEditable
;
final
bool
?
isEnabled
;
final
bool
?
isFocusable
;
final
bool
?
isFocused
;
final
bool
?
isHeading
;
final
bool
?
isPassword
;
final
bool
?
isLongClickable
;
@override
Description
describe
(
Description
description
)
{
...
...
@@ -149,7 +149,7 @@ class _AndroidSemanticsMatcher extends Matcher {
}
@override
bool
matches
(
covariant
AndroidSemanticsNode
item
,
Map
<
Object
,
Object
>
matchState
)
{
bool
matches
(
covariant
AndroidSemanticsNode
item
,
Map
<
dynamic
,
dynamic
>
matchState
)
{
if
(
text
!=
null
&&
text
!=
item
.
text
)
{
return
_failWithMessage
(
'Expected text:
$text
'
,
matchState
);
}
...
...
@@ -170,13 +170,13 @@ class _AndroidSemanticsMatcher extends Matcher {
}
if
(
actions
!=
null
)
{
final
List
<
AndroidSemanticsAction
>
itemActions
=
item
.
getActions
();
if
(!
unorderedEquals
(
actions
).
matches
(
itemActions
,
matchState
))
{
final
List
<
String
>
actionsString
=
actions
.
map
<
String
>((
AndroidSemanticsAction
action
)
=>
action
.
toString
()).
toList
()..
sort
();
if
(!
unorderedEquals
(
actions
!
).
matches
(
itemActions
,
matchState
))
{
final
List
<
String
>
actionsString
=
actions
!
.
map
<
String
>((
AndroidSemanticsAction
action
)
=>
action
.
toString
()).
toList
()..
sort
();
final
List
<
String
>
itemActionsString
=
itemActions
.
map
<
String
>((
AndroidSemanticsAction
action
)
=>
action
.
toString
()).
toList
()..
sort
();
final
Set
<
AndroidSemanticsAction
>
unexpected
=
itemActions
.
toSet
().
difference
(
actions
.
toSet
());
final
Set
<
AndroidSemanticsAction
>
unexpected
=
itemActions
.
toSet
().
difference
(
actions
!
.
toSet
());
final
Set
<
String
>
unexpectedInString
=
itemActionsString
.
toSet
().
difference
(
actionsString
.
toSet
());
final
Set
<
String
>
missingInString
=
actionsString
.
toSet
().
difference
(
itemActionsString
.
toSet
());
if
(
missingInString
.
isEmpty
&&
ignoredActions
!=
null
&&
unexpected
.
every
(
ignoredActions
.
contains
))
{
if
(
missingInString
.
isEmpty
&&
ignoredActions
!=
null
&&
unexpected
.
every
(
ignoredActions
!
.
contains
))
{
return
true
;
}
return
_failWithMessage
(
'Expected actions:
$actionsString
\n
Actual actions:
$itemActionsString
\n
Unexpected:
$unexpectedInString
\n
Missing:
$missingInString
'
,
matchState
);
...
...
@@ -214,8 +214,8 @@ class _AndroidSemanticsMatcher extends Matcher {
}
@override
Description
describeMismatch
(
Object
item
,
Description
mismatchDescription
,
Map
<
Object
,
Object
>
matchState
,
bool
verbose
)
{
Description
describeMismatch
(
dynamic
item
,
Description
mismatchDescription
,
Map
<
dynamic
,
dynamic
>
matchState
,
bool
verbose
)
{
return
mismatchDescription
.
add
(
matchState
[
'failure'
]
as
String
);
}
...
...
dev/integration_tests/android_semantics_testing/lib/src/tests/controls_page.dart
View file @
0df0e2ea
...
...
@@ -9,7 +9,7 @@ export 'controls_constants.dart';
/// A test page with a checkbox, three radio buttons, and a switch.
class
SelectionControlsPage
extends
StatefulWidget
{
const
SelectionControlsPage
({
Key
key
})
:
super
(
key:
key
);
const
SelectionControlsPage
({
super
.
key
}
);
@override
State
<
StatefulWidget
>
createState
()
=>
_SelectionControlsPageState
();
...
...
@@ -28,15 +28,15 @@ class _SelectionControlsPageState extends State<SelectionControlsPage> {
bool
_isLabeledOn
=
false
;
int
_radio
=
0
;
void
_updateCheckbox
(
bool
newValue
)
{
void
_updateCheckbox
(
bool
?
newValue
)
{
setState
(()
{
_isChecked
=
newValue
;
_isChecked
=
newValue
!
;
});
}
void
_updateRadio
(
int
newValue
)
{
void
_updateRadio
(
int
?
newValue
)
{
setState
(()
{
_radio
=
newValue
;
_radio
=
newValue
!
;
});
}
...
...
dev/integration_tests/android_semantics_testing/lib/src/tests/headings_page.dart
View file @
0df0e2ea
...
...
@@ -9,7 +9,7 @@ export 'headings_constants.dart';
/// A test page with an app bar and some body text for testing heading flags.
class
HeadingsPage
extends
StatelessWidget
{
const
HeadingsPage
({
Key
key
})
:
super
(
key:
key
);
const
HeadingsPage
({
super
.
key
}
);
static
const
ValueKey
<
String
>
_appBarTitleKey
=
ValueKey
<
String
>(
appBarTitleKeyValue
);
static
const
ValueKey
<
String
>
_bodyTextKey
=
ValueKey
<
String
>(
bodyTextKeyValue
);
...
...
dev/integration_tests/android_semantics_testing/lib/src/tests/popup_page.dart
View file @
0df0e2ea
...
...
@@ -10,7 +10,7 @@ export 'popup_constants.dart';
/// A page with a popup menu, a dropdown menu, and a modal alert.
class
PopupControlsPage
extends
StatefulWidget
{
const
PopupControlsPage
({
Key
key
})
:
super
(
key:
key
);
const
PopupControlsPage
({
super
.
key
}
);
@override
State
<
StatefulWidget
>
createState
()
=>
_PopupControlsPageState
();
...
...
@@ -60,9 +60,9 @@ class _PopupControlsPageState extends State<PopupControlsPage> {
child:
Text
(
item
),
);
}).
toList
(),
onChanged:
(
String
value
)
{
onChanged:
(
String
?
value
)
{
setState
(()
{
dropdownValue
=
value
;
dropdownValue
=
value
!
;
});
},
),
...
...
dev/integration_tests/android_semantics_testing/lib/src/tests/text_field_page.dart
View file @
0df0e2ea
...
...
@@ -10,7 +10,7 @@ export 'text_field_constants.dart';
/// A page with a normal text field and a password field.
class
TextFieldPage
extends
StatefulWidget
{
const
TextFieldPage
({
Key
key
})
:
super
(
key:
key
);
const
TextFieldPage
({
super
.
key
}
);
@override
State
<
StatefulWidget
>
createState
()
=>
_TextFieldPageState
();
...
...
dev/integration_tests/android_semantics_testing/pubspec.yaml
View file @
0df0e2ea
name
:
android_semantics_testing
description
:
Integration testing library for Android semantics
environment
:
sdk
:
'
>=2.
9.
0
<3.0.0'
sdk
:
'
>=2.
17.0-
0
<3.0.0'
dependencies
:
flutter
:
...
...
dev/integration_tests/android_semantics_testing/test_driver/main_test.dart
View file @
0df0e2ea
...
...
@@ -20,7 +20,7 @@ const List<AndroidSemanticsAction> ignoredAccessibilityFocusActions = <AndroidSe
];
String
adbPath
(
)
{
final
String
androidHome
=
io
.
Platform
.
environment
[
'ANDROID_HOME'
]
??
io
.
Platform
.
environment
[
'ANDROID_SDK_ROOT'
];
final
String
androidHome
=
io
.
Platform
.
environment
[
'ANDROID_HOME'
]
??
io
.
Platform
.
environment
[
'ANDROID_SDK_ROOT'
]
!
;
if
(
androidHome
==
null
)
{
return
'adb'
;
}
else
{
...
...
@@ -30,7 +30,7 @@ String adbPath() {
void
main
(
)
{
group
(
'AccessibilityBridge'
,
()
{
FlutterDriver
driver
;
late
FlutterDriver
driver
;
Future
<
AndroidSemanticsNode
>
getSemantics
(
SerializableFinder
finder
)
async
{
final
int
id
=
await
driver
.
getSemanticsId
(
finder
);
final
String
data
=
await
driver
.
requestData
(
'getSemanticsNode#
$id
'
);
...
...
@@ -38,7 +38,7 @@ void main() {
}
// The version of TalkBack running on the device.
Version
talkbackVersion
;
Version
?
talkbackVersion
;
Future
<
Version
>
getTalkbackVersion
()
async
{
final
io
.
ProcessResult
result
=
await
io
.
Process
.
run
(
adbPath
(),
const
<
String
>[
...
...
@@ -51,7 +51,7 @@ void main() {
throw
Exception
(
'Failed to get TalkBack version:
${result.stdout as String}
\n
${result.stderr as String}
'
);
}
final
List
<
String
>
lines
=
(
result
.
stdout
as
String
).
split
(
'
\n
'
);
String
version
;
String
?
version
;
for
(
final
String
line
in
lines
)
{
if
(
line
.
contains
(
'versionName'
))
{
version
=
line
.
replaceAll
(
RegExp
(
r'\s*versionName='
),
''
);
...
...
@@ -64,14 +64,14 @@ void main() {
// Android doesn't quite use semver, so convert the version string to semver form.
final
RegExp
startVersion
=
RegExp
(
r'(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(\.(?<build>\d+))?'
);
final
RegExpMatch
match
=
startVersion
.
firstMatch
(
version
);
final
RegExpMatch
?
match
=
startVersion
.
firstMatch
(
version
);
if
(
match
==
null
)
{
return
Version
(
0
,
0
,
0
);
}
return
Version
(
int
.
parse
(
match
.
namedGroup
(
'major'
)),
int
.
parse
(
match
.
namedGroup
(
'minor'
)),
int
.
parse
(
match
.
namedGroup
(
'patch'
)),
int
.
parse
(
match
.
namedGroup
(
'major'
)
!
),
int
.
parse
(
match
.
namedGroup
(
'minor'
)
!
),
int
.
parse
(
match
.
namedGroup
(
'patch'
)
!
),
build:
match
.
namedGroup
(
'build'
),
);
}
...
...
@@ -104,7 +104,7 @@ void main() {
'null'
,
]);
await
run
.
exitCode
;
driver
?
.
close
();
driver
.
close
();
});
group
(
'TextField'
,
()
{
...
...
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