Unverified Commit 6ad88bd5 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Propagate textfield character limits to semantics (#40468)

parent 31029f93
......@@ -688,6 +688,8 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
bool get _isEnabled => widget.enabled ?? widget.decoration?.enabled ?? true;
int get _currentLength => _effectiveController.value.text.runes.length;
InputDecoration _getEffectiveDecoration() {
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final ThemeData themeData = Theme.of(context);
......@@ -704,7 +706,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
// If buildCounter was provided, use it to generate a counter widget.
Widget counter;
final int currentLength = _effectiveController.value.text.runes.length;
final int currentLength = _currentLength;
if (effectiveDecoration.counter == null
&& effectiveDecoration.counterText == null
&& widget.buildCounter != null) {
......@@ -1034,18 +1036,27 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
child: child,
);
}
return Semantics(
onTap: () {
if (!_effectiveController.selection.isValid)
_effectiveController.selection = TextSelection.collapsed(offset: _effectiveController.text.length);
_requestKeyboard();
},
return IgnorePointer(
ignoring: !_isEnabled,
child: MouseRegion(
onEnter: _handleMouseEnter,
onExit: _handleMouseExit,
child: IgnorePointer(
ignoring: !_isEnabled,
child: AnimatedBuilder(
animation: controller, // changes the _currentLength
builder: (BuildContext context, Widget child) {
return Semantics(
maxValueLength: widget.maxLengthEnforced && widget.maxLength != null && widget.maxLength > 0
? widget.maxLength
: null,
currentValueLength: _currentLength,
onTap: () {
if (!_effectiveController.selection.isValid)
_effectiveController.selection = TextSelection.collapsed(offset: _effectiveController.text.length);
_requestKeyboard();
},
child: child,
);
},
child: _selectionGestureDetectorBuilder.buildGestureDetector(
behavior: HitTestBehavior.translucent,
child: child,
......
......@@ -864,6 +864,12 @@ class RenderCustomPaint extends RenderProxyBox {
if (properties.liveRegion != null) {
config.liveRegion = properties.liveRegion;
}
if (properties.maxValueLength != null) {
config.maxValueLength = properties.maxValueLength;
}
if (properties.currentValueLength != null) {
config.currentValueLength = properties.currentValueLength;
}
if (properties.toggled != null) {
config.isToggled = properties.toggled;
}
......
......@@ -3497,6 +3497,8 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
bool hidden,
bool image,
bool liveRegion,
int maxValueLength,
int currentValueLength,
String label,
String value,
String increasedValue,
......@@ -3544,6 +3546,8 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
_scopesRoute = scopesRoute,
_namesRoute = namesRoute,
_liveRegion = liveRegion,
_maxValueLength = maxValueLength,
_currentValueLength = currentValueLength,
_hidden = hidden,
_image = image,
_onDismiss = onDismiss,
......@@ -3799,6 +3803,28 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.maxValueLength] semantic to the given
/// value.
int get maxValueLength => _maxValueLength;
int _maxValueLength;
set maxValueLength(int value) {
if (_maxValueLength == value)
return;
_maxValueLength = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.currentValueLength] semantic to the
/// given value.
int get currentValueLength => _currentValueLength;
int _currentValueLength;
set currentValueLength(int value) {
if (_currentValueLength == value)
return;
_currentValueLength = value;
markNeedsSemanticsUpdate();
}
/// If non-null, sets the [SemanticsNode.isToggled] semantic to the given
/// value.
bool get toggled => _toggled;
......@@ -4370,6 +4396,12 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
config.namesRoute = namesRoute;
if (liveRegion != null)
config.liveRegion = liveRegion;
if (maxValueLength != null) {
config.maxValueLength = maxValueLength;
}
if (currentValueLength != null) {
config.currentValueLength = currentValueLength;
}
if (textDirection != null)
config.textDirection = textDirection;
if (sortKey != null)
......
......@@ -197,6 +197,8 @@ class SemanticsData extends Diagnosticable {
@required this.scrollExtentMax,
@required this.scrollExtentMin,
@required this.platformViewId,
@required this.maxValueLength,
@required this.currentValueLength,
this.tags,
this.transform,
this.customSemanticsActionIds,
......@@ -309,6 +311,26 @@ class SemanticsData extends Diagnosticable {
/// * [UiKitView], which is the platform view for iOS.
final int platformViewId;
/// The maximum number of characters that can be entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
/// to null, which means no limit is imposed on the text field.
final int maxValueLength;
/// The current number of characters that have been entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [SemanticsFlag.isTextField] is set. This must
/// be set when [maxValueLength] is set.
final int currentValueLength;
/// The bounding box for this node in its coordinate system.
final Rect rect;
......@@ -389,6 +411,8 @@ class SemanticsData extends Diagnosticable {
if (textSelection?.isValid == true)
properties.add(MessageProperty('textSelection', '[${textSelection.start}, ${textSelection.end}]'));
properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
......@@ -418,6 +442,8 @@ class SemanticsData extends Diagnosticable {
&& typedOther.scrollExtentMax == scrollExtentMax
&& typedOther.scrollExtentMin == scrollExtentMin
&& typedOther.platformViewId == platformViewId
&& typedOther.maxValueLength == maxValueLength
&& typedOther.currentValueLength == currentValueLength
&& typedOther.transform == transform
&& typedOther.elevation == elevation
&& typedOther.thickness == thickness
......@@ -445,10 +471,12 @@ class SemanticsData extends Diagnosticable {
scrollExtentMax,
scrollExtentMin,
platformViewId,
maxValueLength,
currentValueLength,
transform,
elevation,
thickness,
),
elevation,
thickness,
ui.hashList(customSemanticsActionIds),
);
}
......@@ -575,6 +603,8 @@ class SemanticsProperties extends DiagnosticableTree {
this.namesRoute,
this.image,
this.liveRegion,
this.maxValueLength,
this.currentValueLength,
this.label,
this.value,
this.increasedValue,
......@@ -760,6 +790,26 @@ class SemanticsProperties extends DiagnosticableTree {
/// * [UpdateLiveRegionEvent], to trigger a polite announcement of a live region.
final bool liveRegion;
/// The maximum number of characters that can be entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [textField] is true. Defaults to null,
/// which means no limit is imposed on the text field.
final int maxValueLength;
/// The current number of characters that have been entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [textField] is true. Must be set when
/// [maxValueLength] is set.
final int currentValueLength;
/// Provides a textual description of the widget.
///
/// If a label is provided, there must either by an ambient [Directionality]
......@@ -1512,6 +1562,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
_actionsAsBits != config._actionsAsBits ||
indexInParent != config.indexInParent ||
platformViewId != config.platformViewId ||
_maxValueLength != config._maxValueLength ||
_currentValueLength != config._currentValueLength ||
_mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants;
}
......@@ -1729,6 +1781,28 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
int get platformViewId => _platformViewId;
int _platformViewId;
/// The maximum number of characters that can be entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [SemanticsFlag.isTextField] is set. Defaults
/// to null, which means no limit is imposed on the text field.
int get maxValueLength => _maxValueLength;
int _maxValueLength;
/// The current number of characters that have been entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [SemanticsFlag.isTextField] is set. Must be
/// set when [maxValueLength] is set.
int get currentValueLength => _currentValueLength;
int _currentValueLength;
bool _canPerformAction(SemanticsAction action) => _actions.containsKey(action);
static final SemanticsConfiguration _kEmptyConfig = SemanticsConfiguration();
......@@ -1779,6 +1853,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
_scrollIndex = config.scrollIndex;
indexInParent = config.indexInParent;
_platformViewId = config._platformViewId;
_maxValueLength = config._maxValueLength;
_currentValueLength = config._currentValueLength;
_replaceChildren(childrenInInversePaintOrder ?? const <SemanticsNode>[]);
assert(
......@@ -1814,6 +1890,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
double scrollExtentMax = _scrollExtentMax;
double scrollExtentMin = _scrollExtentMin;
int platformViewId = _platformViewId;
int maxValueLength = _maxValueLength;
int currentValueLength = _currentValueLength;
final double elevation = _elevation;
double thickness = _thickness;
final Set<int> customSemanticsActionIds = <int>{};
......@@ -1849,6 +1927,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
scrollExtentMax ??= node._scrollExtentMax;
scrollExtentMin ??= node._scrollExtentMin;
platformViewId ??= node._platformViewId;
maxValueLength ??= node._maxValueLength;
currentValueLength ??= node._currentValueLength;
if (value == '' || value == null)
value = node._value;
if (increasedValue == '' || increasedValue == null)
......@@ -1919,6 +1999,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
scrollExtentMax: scrollExtentMax,
scrollExtentMin: scrollExtentMin,
platformViewId: platformViewId,
maxValueLength: maxValueLength,
currentValueLength: currentValueLength,
customSemanticsActionIds: customSemanticsActionIds.toList()..sort(),
);
}
......@@ -1975,6 +2057,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
textSelectionBase: data.textSelection != null ? data.textSelection.baseOffset : -1,
textSelectionExtent: data.textSelection != null ? data.textSelection.extentOffset : -1,
platformViewId: data.platformViewId ?? -1,
maxValueLength: data.maxValueLength ?? -1,
currentValueLength: data.currentValueLength ?? -1,
scrollChildren: data.scrollChildCount ?? 0,
scrollIndex: data.scrollIndex ?? 0 ,
scrollPosition: data.scrollPosition ?? double.nan,
......@@ -2118,6 +2202,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
if (_textSelection?.isValid == true)
properties.add(MessageProperty('text selection', '[${_textSelection.start}, ${_textSelection.end}]'));
properties.add(IntProperty('platformViewId', platformViewId, defaultValue: null));
properties.add(IntProperty('maxValueLength', maxValueLength, defaultValue: null));
properties.add(IntProperty('currentValueLength', currentValueLength, defaultValue: null));
properties.add(IntProperty('scrollChildren', scrollChildCount, defaultValue: null));
properties.add(IntProperty('scrollIndex', scrollIndex, defaultValue: null));
properties.add(DoubleProperty('scrollExtentMin', scrollExtentMin, defaultValue: null));
......@@ -3188,6 +3274,40 @@ class SemanticsConfiguration {
_hasBeenAnnotated = true;
}
/// The maximum number of characters that can be entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [isTextField] is true. Defaults to null,
/// which means no limit is imposed on the text field.
int get maxValueLength => _maxValueLength;
int _maxValueLength;
set maxValueLength(int value) {
if (value == maxValueLength)
return;
_maxValueLength = value;
_hasBeenAnnotated = true;
}
/// The current number of characters that have been entered into an editable
/// text field.
///
/// For the purpose of this function a character is defined as one Unicode
/// scalar value.
///
/// This should only be set when [isTextField] is true. Must be set when
/// [maxValueLength] is set.
int get currentValueLength => _currentValueLength;
int _currentValueLength;
set currentValueLength(int value) {
if (value == currentValueLength)
return;
_currentValueLength = value;
_hasBeenAnnotated = true;
}
/// Whether the semantic information provided by the owning [RenderObject] and
/// all of its descendants should be treated as one logical entity.
///
......@@ -3690,6 +3810,12 @@ class SemanticsConfiguration {
if (_platformViewId != null && other._platformViewId != null) {
return false;
}
if (_maxValueLength != null && other._maxValueLength != null) {
return false;
}
if (_currentValueLength != null && other._currentValueLength != null) {
return false;
}
if (_value != null && _value.isNotEmpty && other._value != null && other._value.isNotEmpty)
return false;
return true;
......@@ -3725,6 +3851,8 @@ class SemanticsConfiguration {
_scrollIndex ??= child._scrollIndex;
_scrollChildCount ??= child._scrollChildCount;
_platformViewId ??= child._platformViewId;
_maxValueLength ??= child._maxValueLength;
_currentValueLength ??= child._currentValueLength;
textDirection ??= child.textDirection;
_sortKey ??= child._sortKey;
......@@ -3781,6 +3909,8 @@ class SemanticsConfiguration {
.._scrollIndex = _scrollIndex
.._scrollChildCount = _scrollChildCount
.._platformViewId = _platformViewId
.._maxValueLength = _maxValueLength
.._currentValueLength = _currentValueLength
.._actions.addAll(_actions)
.._customSemanticsActions.addAll(_customSemanticsActions);
}
......
......@@ -6196,6 +6196,8 @@ class Semantics extends SingleChildRenderObjectWidget {
bool hidden,
bool image,
bool liveRegion,
int maxValueLength,
int currentValueLength,
String label,
String value,
String increasedValue,
......@@ -6247,6 +6249,8 @@ class Semantics extends SingleChildRenderObjectWidget {
hidden: hidden,
image: image,
liveRegion: liveRegion,
maxValueLength: maxValueLength,
currentValueLength: currentValueLength,
label: label,
value: value,
increasedValue: increasedValue,
......@@ -6350,6 +6354,8 @@ class Semantics extends SingleChildRenderObjectWidget {
readOnly: properties.readOnly,
focused: properties.focused,
liveRegion: properties.liveRegion,
maxValueLength: properties.maxValueLength,
currentValueLength: properties.currentValueLength,
inMutuallyExclusiveGroup: properties.inMutuallyExclusiveGroup,
obscured: properties.obscured,
multiline: properties.multiline,
......@@ -6422,6 +6428,8 @@ class Semantics extends SingleChildRenderObjectWidget {
..hidden = properties.hidden
..image = properties.image
..liveRegion = properties.liveRegion
..maxValueLength = properties.maxValueLength
..currentValueLength = properties.currentValueLength
..label = properties.label
..value = properties.value
..increasedValue = properties.increasedValue
......
......@@ -3367,6 +3367,68 @@ void main() {
semantics.dispose();
});
testWidgets('Disabled text field does not have tap action', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: Center(
child: TextField(
maxLength: 10,
enabled: false,
),
),
),
),
);
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap])));
semantics.dispose();
});
testWidgets('currentValueLength/maxValueLength are in the tree', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final TextEditingController controller = TextEditingController();
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
controller: controller,
maxLength: 10,
),
),
),
),
);
expect(semantics, includesNodeWith(
flags: <SemanticsFlag>[SemanticsFlag.isTextField],
maxValueLength: 10,
currentValueLength: 0,
));
await tester.showKeyboard(find.byType(TextField));
const String testValue = '123';
tester.testTextInput.updateEditingValue(const TextEditingValue(
text: testValue,
selection: TextSelection.collapsed(offset: 3),
composing: TextRange(start: 0, end: testValue.length),
));
await tester.pump();
expect(semantics, includesNodeWith(
flags: <SemanticsFlag>[SemanticsFlag.isTextField, SemanticsFlag.isFocused],
maxValueLength: 10,
currentValueLength: 3,
));
semantics.dispose();
});
testWidgets('Read only TextField identifies as read only text field in semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
......
......@@ -447,6 +447,8 @@ void main() {
' textDirection: null\n'
' sortKey: null\n'
' platformViewId: null\n'
' maxValueLength: null\n'
' currentValueLength: null\n'
' scrollChildren: null\n'
' scrollIndex: null\n'
' scrollExtentMin: null\n'
......@@ -543,6 +545,8 @@ void main() {
' textDirection: null\n'
' sortKey: null\n'
' platformViewId: null\n'
' maxValueLength: null\n'
' currentValueLength: null\n'
' scrollChildren: null\n'
' scrollIndex: null\n'
' scrollExtentMin: null\n'
......
......@@ -452,8 +452,11 @@ void main() {
),
);
final dynamic semanticsDebuggerPainter = _getSemanticsDebuggerPainter(debuggerKey: debugger, tester: tester);
final RenderObject renderTextfield = tester.renderObject(find.descendant(of: find.byKey(textField), matching: find.byType(Semantics)).first);
expect(
_getMessageShownInSemanticsDebugger(widgetKey: textField, debuggerKey: debugger, tester: tester),
semanticsDebuggerPainter.getMessage(renderTextfield.debugSemantics),
'textfield',
);
});
......@@ -463,6 +466,14 @@ String _getMessageShownInSemanticsDebugger({
@required Key widgetKey,
@required Key debuggerKey,
@required WidgetTester tester,
}) {
final dynamic semanticsDebuggerPainter = _getSemanticsDebuggerPainter(debuggerKey: debuggerKey, tester: tester);
return semanticsDebuggerPainter.getMessage(tester.renderObject(find.byKey(widgetKey)).debugSemantics);
}
dynamic _getSemanticsDebuggerPainter({
@required Key debuggerKey,
@required WidgetTester tester,
}) {
final CustomPaint customPaint = tester.widgetList(find.descendant(
of: find.byKey(debuggerKey),
......@@ -470,5 +481,5 @@ String _getMessageShownInSemanticsDebugger({
)).first;
final dynamic semanticsDebuggerPainter = customPaint.foregroundPainter;
expect(semanticsDebuggerPainter.runtimeType.toString(), '_SemanticsDebuggerPainter');
return semanticsDebuggerPainter.getMessage(tester.renderObject(find.byKey(widgetKey)).debugSemantics);
return semanticsDebuggerPainter;
}
......@@ -442,6 +442,8 @@ class SemanticsTester {
double scrollPosition,
double scrollExtentMax,
double scrollExtentMin,
int currentValueLength,
int maxValueLength,
SemanticsNode ancestor,
}) {
bool checkNode(SemanticsNode node) {
......@@ -471,6 +473,12 @@ class SemanticsTester {
return false;
if (scrollExtentMin != null && !nearEqual(node.scrollExtentMin, scrollExtentMin, 0.1))
return false;
if (currentValueLength != null && node.currentValueLength != currentValueLength) {
return false;
}
if (maxValueLength != null && node.maxValueLength != maxValueLength) {
return false;
}
return true;
}
......@@ -713,7 +721,19 @@ class _IncludesNodeWith extends Matcher {
this.scrollPosition,
this.scrollExtentMax,
this.scrollExtentMin,
}) : assert(label != null || value != null || actions != null || flags != null || scrollPosition != null || scrollExtentMax != null || scrollExtentMin != null);
this.maxValueLength,
this.currentValueLength,
}) : assert(
label != null ||
value != null ||
actions != null ||
flags != null ||
scrollPosition != null ||
scrollExtentMax != null ||
scrollExtentMin != null ||
maxValueLength != null ||
currentValueLength != null
);
final String label;
final String value;
......@@ -724,6 +744,8 @@ class _IncludesNodeWith extends Matcher {
final double scrollPosition;
final double scrollExtentMax;
final double scrollExtentMin;
final int currentValueLength;
final int maxValueLength;
@override
bool matches(covariant SemanticsTester item, Map<dynamic, dynamic> matchState) {
......@@ -737,6 +759,8 @@ class _IncludesNodeWith extends Matcher {
scrollPosition: scrollPosition,
scrollExtentMax: scrollExtentMax,
scrollExtentMin: scrollExtentMin,
currentValueLength: currentValueLength,
maxValueLength: maxValueLength,
).isNotEmpty;
}
......@@ -761,6 +785,8 @@ class _IncludesNodeWith extends Matcher {
if (scrollPosition != null) 'scrollPosition "$scrollPosition"',
if (scrollExtentMax != null) 'scrollExtentMax "$scrollExtentMax"',
if (scrollExtentMin != null) 'scrollExtentMin "$scrollExtentMin"',
if (currentValueLength != null) 'currentValueLength "$currentValueLength"',
if (maxValueLength != null) 'maxValueLength "$maxValueLength"',
];
return strings.join(', ');
}
......@@ -780,6 +806,8 @@ Matcher includesNodeWith({
double scrollPosition,
double scrollExtentMax,
double scrollExtentMin,
int maxValueLength,
int currentValueLength,
}) {
return _IncludesNodeWith(
label: label,
......@@ -791,5 +819,7 @@ Matcher includesNodeWith({
scrollPosition: scrollPosition,
scrollExtentMax: scrollExtentMax,
scrollExtentMin: scrollExtentMin,
maxValueLength: maxValueLength,
currentValueLength: currentValueLength,
);
}
......@@ -433,6 +433,8 @@ Matcher matchesSemantics({
double elevation,
double thickness,
int platformViewId,
int maxValueLength,
int currentValueLength,
// Flags //
bool hasCheckedState = false,
bool isChecked = false,
......@@ -552,6 +554,8 @@ Matcher matchesSemantics({
platformViewId: platformViewId,
customActions: customActions,
hintOverrides: hintOverrides,
currentValueLength: currentValueLength,
maxValueLength: maxValueLength,
children: children,
);
}
......@@ -1745,6 +1749,8 @@ class _MatchesSemanticsData extends Matcher {
this.elevation,
this.thickness,
this.platformViewId,
this.maxValueLength,
this.currentValueLength,
this.customActions,
this.hintOverrides,
this.children,
......@@ -1765,6 +1771,8 @@ class _MatchesSemanticsData extends Matcher {
final double elevation;
final double thickness;
final int platformViewId;
final int maxValueLength;
final int currentValueLength;
final List<Matcher> children;
@override
......@@ -1796,6 +1804,10 @@ class _MatchesSemanticsData extends Matcher {
description.add(' with thickness: $thickness');
if (platformViewId != null)
description.add(' with platformViewId: $platformViewId');
if (maxValueLength != null)
description.add(' with maxValueLength: $maxValueLength');
if (currentValueLength != null)
description.add(' with currentValueLength: $currentValueLength');
if (customActions != null)
description.add(' with custom actions: $customActions');
if (hintOverrides != null)
......@@ -1838,6 +1850,10 @@ class _MatchesSemanticsData extends Matcher {
return failWithDescription(matchState, 'thickness was: ${data.thickness}');
if (platformViewId != null && platformViewId != data.platformViewId)
return failWithDescription(matchState, 'platformViewId was: ${data.platformViewId}');
if (currentValueLength != null && currentValueLength != data.currentValueLength)
return failWithDescription(matchState, 'currentValueLength was: ${data.currentValueLength}');
if (maxValueLength != null && maxValueLength != data.maxValueLength)
return failWithDescription(matchState, 'maxValueLength was: ${data.maxValueLength}');
if (actions != null) {
int actionBits = 0;
for (SemanticsAction action in actions)
......
......@@ -525,6 +525,8 @@ void main() {
scrollExtentMin: null,
platformViewId: 105,
customSemanticsActionIds: <int>[CustomSemanticsAction.getIdentifier(action)],
currentValueLength: 10,
maxValueLength: 15,
);
final _FakeSemanticsNode node = _FakeSemanticsNode();
node.data = data;
......@@ -535,6 +537,8 @@ void main() {
elevation: 3.0,
thickness: 4.0,
platformViewId: 105,
currentValueLength: 10,
maxValueLength: 15,
/* Flags */
hasCheckedState: true,
isChecked: true,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment