Unverified Commit cdf1cec9 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

add ability to match child semantics data (#22001)

parent 21a32fdd
...@@ -14,7 +14,7 @@ void main() { ...@@ -14,7 +14,7 @@ void main() {
home: ChipDemo(), home: ChipDemo(),
)); ));
expect(tester.getSemanticsData(find.byIcon(Icons.vignette)), matchesSemanticsData( expect(tester.getSemantics(find.byIcon(Icons.vignette)), matchesSemantics(
isButton: true, isButton: true,
hasEnabledState: true, hasEnabledState: true,
isEnabled: true, isEnabled: true,
...@@ -22,7 +22,7 @@ void main() { ...@@ -22,7 +22,7 @@ void main() {
label: 'Update border shape', label: 'Update border shape',
)); ));
expect(tester.getSemanticsData(find.byIcon(Icons.refresh)), matchesSemanticsData( expect(tester.getSemantics(find.byIcon(Icons.refresh)), matchesSemantics(
isButton: true, isButton: true,
hasEnabledState: true, hasEnabledState: true,
isEnabled: true, isEnabled: true,
......
...@@ -330,7 +330,7 @@ void main() { ...@@ -330,7 +330,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(CupertinoSlider)), matchesSemanticsData( expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
hasIncreaseAction: true, hasIncreaseAction: true,
hasDecreaseAction: true, hasDecreaseAction: true,
value: '50%', value: '50%',
...@@ -348,7 +348,7 @@ void main() { ...@@ -348,7 +348,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(CupertinoSlider)), matchesSemanticsData( expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
hasIncreaseAction: true, hasIncreaseAction: true,
hasDecreaseAction: true, hasDecreaseAction: true,
value: '60%', value: '60%',
......
...@@ -82,7 +82,7 @@ void main() { ...@@ -82,7 +82,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(tester.getSemanticsData(find.byType(BackButton)), matchesSemanticsData( expect(tester.getSemantics(find.byType(BackButton)), matchesSemantics(
label: 'Back', label: 'Back',
isButton: true, isButton: true,
hasEnabledState: true, hasEnabledState: true,
......
...@@ -66,7 +66,7 @@ void main() { ...@@ -66,7 +66,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true, hasCheckedState: true,
hasEnabledState: true, hasEnabledState: true,
isEnabled: true, isEnabled: true,
...@@ -80,7 +80,7 @@ void main() { ...@@ -80,7 +80,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true, hasCheckedState: true,
hasEnabledState: true, hasEnabledState: true,
isChecked: true, isChecked: true,
...@@ -95,7 +95,7 @@ void main() { ...@@ -95,7 +95,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true, hasCheckedState: true,
hasEnabledState: true, hasEnabledState: true,
)); ));
...@@ -107,7 +107,7 @@ void main() { ...@@ -107,7 +107,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true, hasCheckedState: true,
hasEnabledState: true, hasEnabledState: true,
isChecked: true, isChecked: true,
...@@ -129,7 +129,7 @@ void main() { ...@@ -129,7 +129,7 @@ void main() {
), ),
)); ));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
label: 'foo', label: 'foo',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
hasCheckedState: true, hasCheckedState: true,
......
...@@ -692,7 +692,7 @@ void main() { ...@@ -692,7 +692,7 @@ void main() {
)); ));
// By default the hint contributes the label. // By default the hint contributes the label.
expect(tester.getSemanticsData(find.byKey(key)), matchesSemanticsData( expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
isButton: true, isButton: true,
label: 'test', label: 'test',
hasTapAction: true, hasTapAction: true,
...@@ -707,7 +707,7 @@ void main() { ...@@ -707,7 +707,7 @@ void main() {
)); ));
// Displays label of select item and is no longer tappable. // Displays label of select item and is no longer tappable.
expect(tester.getSemanticsData(find.byKey(key)), matchesSemanticsData( expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
isButton: true, isButton: true,
label: 'three', label: 'three',
hasTapAction: true, hasTapAction: true,
......
...@@ -95,7 +95,7 @@ void main() { ...@@ -95,7 +95,7 @@ void main() {
) )
)); ));
expect(tester.getSemanticsData(find.byType(ExpandIcon)), matchesSemanticsData( expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics(
hasTapAction: true, hasTapAction: true,
hasEnabledState: true, hasEnabledState: true,
isEnabled: true, isEnabled: true,
...@@ -110,7 +110,7 @@ void main() { ...@@ -110,7 +110,7 @@ void main() {
) )
)); ));
expect(tester.getSemanticsData(find.byType(ExpandIcon)), matchesSemanticsData( expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics(
hasTapAction: true, hasTapAction: true,
hasEnabledState: true, hasEnabledState: true,
isEnabled: true, isEnabled: true,
......
...@@ -382,7 +382,7 @@ void main() { ...@@ -382,7 +382,7 @@ void main() {
), ),
); );
expect(tester.getSemanticsData(find.byKey(expandedKey)), matchesSemanticsData( expect(tester.getSemantics(find.byKey(expandedKey)), matchesSemantics(
label: 'Expanded', label: 'Expanded',
isButton: true, isButton: true,
hasEnabledState: true, hasEnabledState: true,
...@@ -391,7 +391,7 @@ void main() { ...@@ -391,7 +391,7 @@ void main() {
onTapHint: localizations.expandedIconTapHint, onTapHint: localizations.expandedIconTapHint,
)); ));
expect(tester.getSemanticsData(find.byKey(collapsedKey)), matchesSemanticsData( expect(tester.getSemantics(find.byKey(collapsedKey)), matchesSemantics(
label: 'Collapsed', label: 'Collapsed',
isButton: true, isButton: true,
hasEnabledState: true, hasEnabledState: true,
......
...@@ -462,10 +462,10 @@ void main() { ...@@ -462,10 +462,10 @@ void main() {
)); ));
// Get the switch tile's semantics: // Get the switch tile's semantics:
final SemanticsData semanticsData = tester.getSemanticsData(find.byKey(const Key('Switch tile'))); final SemanticsNode semanticsNode = tester.getSemantics(find.byKey(const Key('Switch tile')));
// Check for properties of both SwitchTile semantics and the ReorderableListView custom semantics actions. // Check for properties of both SwitchTile semantics and the ReorderableListView custom semantics actions.
expect(semanticsData, matchesSemanticsData( expect(semanticsNode, matchesSemantics(
hasToggledState: true, hasToggledState: true,
isToggled: true, isToggled: true,
isEnabled: true, isEnabled: true,
......
...@@ -555,7 +555,7 @@ void main() { ...@@ -555,7 +555,7 @@ void main() {
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(tester.getSemanticsData(find.text('snack')), matchesSemanticsData( expect(tester.getSemantics(find.text('snack')), matchesSemantics(
isLiveRegion: true, isLiveRegion: true,
hasDismissAction: true, hasDismissAction: true,
hasScrollDownAction: true, hasScrollDownAction: true,
......
...@@ -378,17 +378,17 @@ void main() { ...@@ -378,17 +378,17 @@ void main() {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
await pumpTestWidget(tester); await pumpTestWidget(tester);
expect(tester.getSemanticsData(find.text('B')), matchesSemanticsData( expect(tester.getSemantics(find.text('B')), matchesSemantics(
label: 'B', label: 'B',
size: const Size(48.0, 48.0), size: const Size(48.0, 48.0),
)); ));
expect(tester.getSemanticsData(find.text('C')), matchesSemanticsData( expect(tester.getSemantics(find.text('C')), matchesSemantics(
label: 'C', label: 'C',
size: const Size(48.0, 48.0), size: const Size(48.0, 48.0),
)); ));
expect(tester.getSemanticsData(find.text('D')), matchesSemanticsData( expect(tester.getSemantics(find.text('D')), matchesSemantics(
label: 'D', label: 'D',
size: const Size(48.0, 48.0), size: const Size(48.0, 48.0),
)); ));
......
...@@ -111,7 +111,7 @@ void main() { ...@@ -111,7 +111,7 @@ void main() {
), ),
); );
expect(tester.getSemanticsData(find.byType(ImageIcon)), matchesSemanticsData( expect(tester.getSemantics(find.byType(ImageIcon)), matchesSemantics(
label: 'test', label: 'test',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
)); ));
......
...@@ -643,7 +643,7 @@ void main() { ...@@ -643,7 +643,7 @@ void main() {
onTapHint: 'test', onTapHint: 'test',
)); ));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
hasTapAction: true, hasTapAction: true,
onTapHint: 'test' onTapHint: 'test'
)); ));
...@@ -654,7 +654,7 @@ void main() { ...@@ -654,7 +654,7 @@ void main() {
onLongPressHint: 'foo', onLongPressHint: 'foo',
)); ));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
hasLongPressAction: true, hasLongPressAction: true,
onLongPressHint: 'foo' onLongPressHint: 'foo'
)); ));
...@@ -671,7 +671,7 @@ void main() { ...@@ -671,7 +671,7 @@ void main() {
}, },
)); ));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData( expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
customActions: <CustomSemanticsAction>[ customActions: <CustomSemanticsAction>[
const CustomSemanticsAction(label: 'bar'), const CustomSemanticsAction(label: 'bar'),
const CustomSemanticsAction(label: 'foo'), const CustomSemanticsAction(label: 'foo'),
......
This diff is collapsed.
...@@ -617,15 +617,39 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -617,15 +617,39 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
}); });
} }
/// Attempts to find the [SemanticsData] of first result from `finder`. /// Attempts to find the [SemanticsNode] of first result from `finder`.
/// ///
/// If the object identified by the finder doesn't own it's semantic node, /// 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 /// 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 /// The ancestor's semantic data will include the child's as well as
/// other nodes that have been merged together. /// other nodes that have been merged together.
/// ///
/// Will throw a [StateError] if the finder returns more than one element or /// Will throw a [StateError] if the finder returns more than one element or
/// if no semantics are found or are not enabled. /// if no semantics are found or are not enabled.
SemanticsNode getSemantics(Finder finder) {
if (binding.pipelineOwner.semanticsOwner == null)
throw StateError('Semantics are not enabled.');
final Iterable<Element> candidates = finder.evaluate();
if (candidates.isEmpty) {
throw StateError('Finder returned no matching elements.');
}
if (candidates.length > 1) {
throw 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 StateError('No Semantics data found.');
return result;
}
/// DEPRECATED: use [getSemantics] instead.
@Deprecated('use getSemantics instead')
SemanticsData getSemanticsData(Finder finder) { SemanticsData getSemanticsData(Finder finder) {
if (binding.pipelineOwner.semanticsOwner == null) if (binding.pipelineOwner.semanticsOwner == null)
throw StateError('Semantics are not enabled.'); throw StateError('Semantics are not enabled.');
......
...@@ -409,8 +409,8 @@ void main() { ...@@ -409,8 +409,8 @@ void main() {
}, },
)); ));
expect(tester.getSemanticsData(find.byKey(key)), expect(tester.getSemantics(find.byKey(key)),
matchesSemanticsData( matchesSemantics(
label: 'foo', label: 'foo',
hint: 'bar', hint: 'bar',
value: 'baz', value: 'baz',
...@@ -432,8 +432,8 @@ void main() { ...@@ -432,8 +432,8 @@ void main() {
); );
// Doesn't match custom actions // Doesn't match custom actions
expect(tester.getSemanticsData(find.byKey(key)), expect(tester.getSemantics(find.byKey(key)),
isNot(matchesSemanticsData( isNot(matchesSemantics(
label: 'foo', label: 'foo',
hint: 'bar', hint: 'bar',
value: 'baz', value: 'baz',
...@@ -453,8 +453,8 @@ void main() { ...@@ -453,8 +453,8 @@ void main() {
); );
// Doesn't match wrong hints // Doesn't match wrong hints
expect(tester.getSemanticsData(find.byKey(key)), expect(tester.getSemantics(find.byKey(key)),
isNot(matchesSemanticsData( isNot(matchesSemantics(
label: 'foo', label: 'foo',
hint: 'bar', hint: 'bar',
value: 'baz', value: 'baz',
...@@ -500,8 +500,10 @@ void main() { ...@@ -500,8 +500,10 @@ void main() {
scrollExtentMin: null, scrollExtentMin: null,
customSemanticsActionIds: <int>[CustomSemanticsAction.getIdentifier(action)], customSemanticsActionIds: <int>[CustomSemanticsAction.getIdentifier(action)],
); );
final _FakeSemanticsNode node = _FakeSemanticsNode();
node.data = data;
expect(data, matchesSemanticsData( expect(node, matchesSemantics(
rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0), rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
size: const Size(10.0, 10.0), size: const Size(10.0, 10.0),
/* Flags */ /* Flags */
...@@ -548,6 +550,35 @@ void main() { ...@@ -548,6 +550,35 @@ void main() {
customActions: <CustomSemanticsAction>[action], customActions: <CustomSemanticsAction>[action],
)); ));
}); });
testWidgets('Can match child semantics', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
const Key key = Key('a');
await tester.pumpWidget(Semantics(
key: key,
label: 'Foo',
container: true,
explicitChildNodes: true,
textDirection: TextDirection.ltr,
child: Semantics(
label: 'Bar',
textDirection: TextDirection.ltr,
),
));
final SemanticsNode node = tester.getSemantics(find.byKey(key));
expect(node, matchesSemantics(
label: 'Foo',
textDirection: TextDirection.ltr,
children: <Matcher>[
matchesSemantics(
label: 'Bar',
textDirection: TextDirection.ltr,
),
],
));
handle.dispose();
});
}); });
} }
...@@ -592,3 +623,9 @@ class _FakeComparator implements GoldenFileComparator { ...@@ -592,3 +623,9 @@ class _FakeComparator implements GoldenFileComparator {
return Future<void>.value(); return Future<void>.value();
} }
} }
class _FakeSemanticsNode extends SemanticsNode {
SemanticsData data;
@override
SemanticsData getSemanticsData() => data;
}
\ No newline at end of file
...@@ -540,7 +540,7 @@ void main() { ...@@ -540,7 +540,7 @@ void main() {
), ),
); );
expect(() => tester.getSemanticsData(find.text('hello')), expect(() => tester.getSemantics(find.text('hello')),
throwsA(isInstanceOf<StateError>())); throwsA(isInstanceOf<StateError>()));
}); });
...@@ -560,7 +560,7 @@ void main() { ...@@ -560,7 +560,7 @@ void main() {
), ),
); );
expect(() => tester.getSemanticsData(find.text('hello')), expect(() => tester.getSemantics(find.text('hello')),
throwsA(isInstanceOf<StateError>())); throwsA(isInstanceOf<StateError>()));
semanticsHandle.dispose(); semanticsHandle.dispose();
}); });
...@@ -581,7 +581,8 @@ void main() { ...@@ -581,7 +581,8 @@ void main() {
), ),
); );
final SemanticsData semantics = tester.getSemanticsData(find.text('hello')); final SemanticsNode node = tester.getSemantics(find.text('hello'));
final SemanticsData semantics = node.getSemanticsData();
expect(semantics.label, 'hello'); expect(semantics.label, 'hello');
expect(semantics.hasAction(SemanticsAction.tap), true); expect(semantics.hasAction(SemanticsAction.tap), true);
expect(semantics.hasFlag(SemanticsFlag.isButton), true); expect(semantics.hasFlag(SemanticsFlag.isButton), true);
...@@ -609,7 +610,8 @@ void main() { ...@@ -609,7 +610,8 @@ void main() {
), ),
); );
final SemanticsData semantics = tester.getSemanticsData(find.byKey(key)); final SemanticsNode node = tester.getSemantics(find.byKey(key));
final SemanticsData semantics = node.getSemanticsData();
expect(semantics.label, 'A\nB\nC'); expect(semantics.label, 'A\nB\nC');
semanticsHandle.dispose(); semanticsHandle.dispose();
}); });
......
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