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() {
home: ChipDemo(),
));
expect(tester.getSemanticsData(find.byIcon(Icons.vignette)), matchesSemanticsData(
expect(tester.getSemantics(find.byIcon(Icons.vignette)), matchesSemantics(
isButton: true,
hasEnabledState: true,
isEnabled: true,
......@@ -22,7 +22,7 @@ void main() {
label: 'Update border shape',
));
expect(tester.getSemanticsData(find.byIcon(Icons.refresh)), matchesSemanticsData(
expect(tester.getSemantics(find.byIcon(Icons.refresh)), matchesSemantics(
isButton: true,
hasEnabledState: true,
isEnabled: true,
......
......@@ -330,7 +330,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(CupertinoSlider)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
hasIncreaseAction: true,
hasDecreaseAction: true,
value: '50%',
......@@ -348,7 +348,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(CupertinoSlider)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
hasIncreaseAction: true,
hasDecreaseAction: true,
value: '60%',
......
......@@ -82,7 +82,7 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSemanticsData(find.byType(BackButton)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(BackButton)), matchesSemantics(
label: 'Back',
isButton: true,
hasEnabledState: true,
......
......@@ -66,7 +66,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
isEnabled: true,
......@@ -80,7 +80,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
isChecked: true,
......@@ -95,7 +95,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
));
......@@ -107,7 +107,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
hasCheckedState: true,
hasEnabledState: true,
isChecked: true,
......@@ -129,7 +129,7 @@ void main() {
),
));
expect(tester.getSemanticsData(find.byType(Checkbox)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Checkbox)), matchesSemantics(
label: 'foo',
textDirection: TextDirection.ltr,
hasCheckedState: true,
......
......@@ -692,7 +692,7 @@ void main() {
));
// By default the hint contributes the label.
expect(tester.getSemanticsData(find.byKey(key)), matchesSemanticsData(
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
isButton: true,
label: 'test',
hasTapAction: true,
......@@ -707,7 +707,7 @@ void main() {
));
// 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,
label: 'three',
hasTapAction: true,
......
......@@ -95,7 +95,7 @@ void main() {
)
));
expect(tester.getSemanticsData(find.byType(ExpandIcon)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics(
hasTapAction: true,
hasEnabledState: true,
isEnabled: true,
......@@ -110,7 +110,7 @@ void main() {
)
));
expect(tester.getSemanticsData(find.byType(ExpandIcon)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics(
hasTapAction: true,
hasEnabledState: true,
isEnabled: true,
......
......@@ -382,7 +382,7 @@ void main() {
),
);
expect(tester.getSemanticsData(find.byKey(expandedKey)), matchesSemanticsData(
expect(tester.getSemantics(find.byKey(expandedKey)), matchesSemantics(
label: 'Expanded',
isButton: true,
hasEnabledState: true,
......@@ -391,7 +391,7 @@ void main() {
onTapHint: localizations.expandedIconTapHint,
));
expect(tester.getSemanticsData(find.byKey(collapsedKey)), matchesSemanticsData(
expect(tester.getSemantics(find.byKey(collapsedKey)), matchesSemantics(
label: 'Collapsed',
isButton: true,
hasEnabledState: true,
......
......@@ -462,10 +462,10 @@ void main() {
));
// 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.
expect(semanticsData, matchesSemanticsData(
expect(semanticsNode, matchesSemantics(
hasToggledState: true,
isToggled: true,
isEnabled: true,
......
......@@ -555,7 +555,7 @@ void main() {
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(tester.getSemanticsData(find.text('snack')), matchesSemanticsData(
expect(tester.getSemantics(find.text('snack')), matchesSemantics(
isLiveRegion: true,
hasDismissAction: true,
hasScrollDownAction: true,
......
......@@ -378,17 +378,17 @@ void main() {
final SemanticsHandle handle = tester.ensureSemantics();
await pumpTestWidget(tester);
expect(tester.getSemanticsData(find.text('B')), matchesSemanticsData(
expect(tester.getSemantics(find.text('B')), matchesSemantics(
label: 'B',
size: const Size(48.0, 48.0),
));
expect(tester.getSemanticsData(find.text('C')), matchesSemanticsData(
expect(tester.getSemantics(find.text('C')), matchesSemantics(
label: 'C',
size: const Size(48.0, 48.0),
));
expect(tester.getSemanticsData(find.text('D')), matchesSemanticsData(
expect(tester.getSemantics(find.text('D')), matchesSemantics(
label: 'D',
size: const Size(48.0, 48.0),
));
......
......@@ -111,7 +111,7 @@ void main() {
),
);
expect(tester.getSemanticsData(find.byType(ImageIcon)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(ImageIcon)), matchesSemantics(
label: 'test',
textDirection: TextDirection.ltr,
));
......
......@@ -643,7 +643,7 @@ void main() {
onTapHint: 'test',
));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
hasTapAction: true,
onTapHint: 'test'
));
......@@ -654,7 +654,7 @@ void main() {
onLongPressHint: 'foo',
));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
hasLongPressAction: true,
onLongPressHint: 'foo'
));
......@@ -671,7 +671,7 @@ void main() {
},
));
expect(tester.getSemanticsData(find.byType(Semantics)), matchesSemanticsData(
expect(tester.getSemantics(find.byType(Semantics)), matchesSemantics(
customActions: <CustomSemanticsAction>[
const CustomSemanticsAction(label: 'bar'),
const CustomSemanticsAction(label: 'foo'),
......
This diff is collapsed.
......@@ -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,
/// 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
/// this will return the semantics data of the first ancestor with semantics.
/// 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.
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) {
if (binding.pipelineOwner.semanticsOwner == null)
throw StateError('Semantics are not enabled.');
......
......@@ -409,8 +409,8 @@ void main() {
},
));
expect(tester.getSemanticsData(find.byKey(key)),
matchesSemanticsData(
expect(tester.getSemantics(find.byKey(key)),
matchesSemantics(
label: 'foo',
hint: 'bar',
value: 'baz',
......@@ -432,8 +432,8 @@ void main() {
);
// Doesn't match custom actions
expect(tester.getSemanticsData(find.byKey(key)),
isNot(matchesSemanticsData(
expect(tester.getSemantics(find.byKey(key)),
isNot(matchesSemantics(
label: 'foo',
hint: 'bar',
value: 'baz',
......@@ -453,8 +453,8 @@ void main() {
);
// Doesn't match wrong hints
expect(tester.getSemanticsData(find.byKey(key)),
isNot(matchesSemanticsData(
expect(tester.getSemantics(find.byKey(key)),
isNot(matchesSemantics(
label: 'foo',
hint: 'bar',
value: 'baz',
......@@ -500,8 +500,10 @@ void main() {
scrollExtentMin: null,
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),
size: const Size(10.0, 10.0),
/* Flags */
......@@ -548,6 +550,35 @@ void main() {
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 {
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() {
),
);
expect(() => tester.getSemanticsData(find.text('hello')),
expect(() => tester.getSemantics(find.text('hello')),
throwsA(isInstanceOf<StateError>()));
});
......@@ -560,7 +560,7 @@ void main() {
),
);
expect(() => tester.getSemanticsData(find.text('hello')),
expect(() => tester.getSemantics(find.text('hello')),
throwsA(isInstanceOf<StateError>()));
semanticsHandle.dispose();
});
......@@ -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.hasAction(SemanticsAction.tap), true);
expect(semantics.hasFlag(SemanticsFlag.isButton), true);
......@@ -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');
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