Unverified Commit c71f1dd7 authored by Simon Binder's avatar Simon Binder Committed by GitHub

Treat hidden `IndexedStack` children as offstage for test finder (#123129)

Treat hidden `IndexedStack` children as offstage for test finder
parent 42f61b32
...@@ -16,13 +16,15 @@ void main() { ...@@ -16,13 +16,15 @@ void main() {
), ),
); );
expect(find.text('One'), findsNWidgets(4)); expect(find.text('One'), findsOneWidget);
expect(find.text('One', skipOffstage: false), findsNWidgets(4));
await tester.tap(find.text('One').first); await tester.tap(find.text('One').first);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('Two'), findsOneWidget); expect(find.text('Two'), findsOneWidget);
await tester.tap(find.text('Two')); await tester.tap(find.text('Two'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('Two'), findsNWidgets(4)); expect(find.text('Two'), findsOneWidget);
expect(find.text('Two', skipOffstage: false), findsNWidgets(4));
}); });
} }
...@@ -11,11 +11,11 @@ void main() { ...@@ -11,11 +11,11 @@ void main() {
await tester.pumpWidget(const example.IndexedStackApp()); await tester.pumpWidget(const example.IndexedStackApp());
final Finder gesture2 = find.byKey(const Key('gesture2')); final Finder gesture2 = find.byKey(const Key('gesture2'));
final Element containerFinder = find.byKey(const Key('Dash')).evaluate().first; final Element containerFinder = find.byKey(const Key('Dash'), skipOffstage: false).evaluate().first;
expect(containerFinder.renderObject!.debugNeedsPaint, false); expect(containerFinder.renderObject!.debugNeedsPaint, false);
final Element containerFinder1 = find.byKey(const Key('John')).evaluate().first; final Element containerFinder1 = find.byKey(const Key('John'), skipOffstage: false).evaluate().first;
expect(containerFinder1.renderObject!.debugNeedsPaint, true); expect(containerFinder1.renderObject!.debugNeedsPaint, true);
final Element containerFinder2 = find.byKey(const Key('Mary')).evaluate().first; final Element containerFinder2 = find.byKey(const Key('Mary'), skipOffstage: false).evaluate().first;
expect(containerFinder2.renderObject!.debugNeedsPaint, true); expect(containerFinder2.renderObject!.debugNeedsPaint, true);
await tester.tap(gesture2); await tester.tap(gesture2);
...@@ -34,9 +34,9 @@ void main() { ...@@ -34,9 +34,9 @@ void main() {
await tester.pumpWidget(const example.IndexedStackApp()); await tester.pumpWidget(const example.IndexedStackApp());
final Finder gesture1 = find.byKey(const Key('gesture1')); final Finder gesture1 = find.byKey(const Key('gesture1'));
final Element containerFinder = find.byKey(const Key('Dash')).evaluate().first; final Element containerFinder = find.byKey(const Key('Dash'), skipOffstage: false).evaluate().first;
final Element containerFinder1 = find.byKey(const Key('John')).evaluate().first; final Element containerFinder1 = find.byKey(const Key('John'), skipOffstage: false).evaluate().first;
final Element containerFinder2 = find.byKey(const Key('Mary')).evaluate().first; final Element containerFinder2 = find.byKey(const Key('Mary'), skipOffstage: false).evaluate().first;
await tester.tap(gesture1); await tester.tap(gesture1);
await tester.pump(); await tester.pump();
...@@ -53,17 +53,18 @@ void main() { ...@@ -53,17 +53,18 @@ void main() {
testWidgets('has correct element addition handling', (WidgetTester tester) async { testWidgets('has correct element addition handling', (WidgetTester tester) async {
await tester.pumpWidget(const example.IndexedStackApp()); await tester.pumpWidget(const example.IndexedStackApp());
expect(find.byType(example.PersonTracker), findsNWidgets(3)); expect(find.byType(example.PersonTracker), findsOneWidget);
expect(find.byType(example.PersonTracker, skipOffstage: false), findsNWidgets(3));
final Finder textField = find.byType(TextField); final Finder textField = find.byType(TextField);
await tester.enterText(textField, 'hello'); await tester.enterText(textField, 'hello');
await tester.testTextInput.receiveAction(TextInputAction.done); await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pump(); await tester.pump();
expect(find.byType(example.PersonTracker), findsNWidgets(4)); expect(find.byType(example.PersonTracker, skipOffstage: false), findsNWidgets(4));
await tester.enterText(textField, 'hello1'); await tester.enterText(textField, 'hello1');
await tester.testTextInput.receiveAction(TextInputAction.done); await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pump(); await tester.pump();
expect(find.byType(example.PersonTracker), findsNWidgets(5)); expect(find.byType(example.PersonTracker, skipOffstage: false), findsNWidgets(5));
}); });
testWidgets('has state preservation', (WidgetTester tester) async { testWidgets('has state preservation', (WidgetTester tester) async {
await tester.pumpWidget(const example.IndexedStackApp()); await tester.pumpWidget(const example.IndexedStackApp());
......
...@@ -4075,6 +4075,28 @@ class _RawIndexedStack extends Stack { ...@@ -4075,6 +4075,28 @@ class _RawIndexedStack extends Stack {
..alignment = alignment ..alignment = alignment
..textDirection = textDirection ?? Directionality.maybeOf(context); ..textDirection = textDirection ?? Directionality.maybeOf(context);
} }
@override
MultiChildRenderObjectElement createElement() {
return _IndexedStackElement(this);
}
}
class _IndexedStackElement extends MultiChildRenderObjectElement {
_IndexedStackElement(_RawIndexedStack super.widget);
@override
_RawIndexedStack get widget => super.widget as _RawIndexedStack;
@override
void debugVisitOnstageChildren(ElementVisitor visitor) {
final int? index = widget.index;
// If the index is null, no child is onstage. Otherwise, only the child at
// the selected index is.
if (index != null && children.isNotEmpty) {
visitor(children.elementAt(index));
}
}
} }
/// A widget that controls where a child of a [Stack] is positioned. /// A widget that controls where a child of a [Stack] is positioned.
......
...@@ -264,16 +264,28 @@ void main() { ...@@ -264,16 +264,28 @@ void main() {
); );
} }
void expectFindsChild(int n) {
for (int i = 0; i < 3; i++) {
expect(find.text('$i', skipOffstage: false), findsOneWidget);
if (i == n) {
expect(find.text('$i'), findsOneWidget);
} else {
expect(find.text('$i'), findsNothing);
}
}
}
await tester.pumpWidget(buildFrame(0)); await tester.pumpWidget(buildFrame(0));
expect(find.text('0'), findsOneWidget); expectFindsChild(0);
expect(find.text('1'), findsOneWidget);
expect(find.text('2'), findsOneWidget);
expect(itemsPainted, equals(<int>[0])); expect(itemsPainted, equals(<int>[0]));
await tester.pumpWidget(buildFrame(1)); await tester.pumpWidget(buildFrame(1));
expectFindsChild(1);
expect(itemsPainted, equals(<int>[1])); expect(itemsPainted, equals(<int>[1]));
await tester.pumpWidget(buildFrame(2)); await tester.pumpWidget(buildFrame(2));
expectFindsChild(2);
expect(itemsPainted, equals(<int>[2])); expect(itemsPainted, equals(<int>[2]));
}); });
...@@ -473,6 +485,40 @@ void main() { ...@@ -473,6 +485,40 @@ void main() {
expect(tapped, isNull); expect(tapped, isNull);
}); });
testWidgets('IndexedStack reports hidden children as offstage', (WidgetTester tester) async {
final List<Widget> children = <Widget>[
for (int i = 0; i < 5; i++) Text('child $i'),
];
Future<void> pumpIndexedStack(int? activeIndex) async{
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: IndexedStack(
index: activeIndex,
children: children,
),
)
);
}
final Finder finder = find.byType(Text);
final Finder finderIncludingOffstage = find.byType(Text, skipOffstage: false);
await pumpIndexedStack(null);
expect(finder, findsNothing); // IndexedStack with null index shows nothing
expect(finderIncludingOffstage, findsNWidgets(5));
for (int i = 0; i < 5; i++) {
await pumpIndexedStack(i);
expect(finder, findsOneWidget);
expect(finderIncludingOffstage, findsNWidgets(5));
expect(find.text('child $i'), findsOneWidget);
}
});
testWidgets('Stack clip test', (WidgetTester tester) async { testWidgets('Stack clip test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
......
...@@ -318,8 +318,9 @@ void main() { ...@@ -318,8 +318,9 @@ void main() {
], ],
)), )),
); );
expect(find.byType(GestureDetector), findsNWidgets(2)); expect(find.byType(GestureDetector), findsOneWidget);
final Finder hitTestable = find.byType(GestureDetector).hitTestable(); expect(find.byType(GestureDetector, skipOffstage: false), findsNWidgets(2));
final Finder hitTestable = find.byType(GestureDetector, skipOffstage: false).hitTestable();
expect(hitTestable, findsOneWidget); expect(hitTestable, findsOneWidget);
expect(tester.widget(hitTestable).key, const ValueKey<int>(0)); expect(tester.widget(hitTestable).key, const ValueKey<int>(0));
}); });
......
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