I have ListView widgets within a TabBarView to allow users to scroll through the contents of each tab. I would like to test some of the widgets which are off screen. I followed this to scroll the ListView to bring the relevant widget on screen:
How to find off-screen ListView child in widget tests?
This works fine until I place the ListView in a TabBarView, then it fails.
I've rebuilt the code without the ListView in a TabBarView and the test passes. Placing the ListView in a TabBarView causes the test to fail with:
'zero widgets with text "bbb" (ignoring offstage widgets)'
debugDumpApp()
output shows that this is because there has been no scrolling.
My stateful widget:
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Scroll test'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
expandedHeight: 100.0,
bottom: TabBar(
controller: _tabController,
tabs: <Widget>[
Tab(
child: Text('Tab one'),
),
Tab(
child: Text('Tab two'),
)
],
),
)
];
},
body: TabBarView(
controller: _tabController,
children: <Widget>[
ListView(
children: <Widget>[
Container(
height: 800.0,
child: Text('aaa'),
),
Text('bbb')
],
),
ListView(
children: <Widget>[
Container(
height: 800.0,
child: Text('ccc'),
),
Text('ddd')
],
),
],
)
)
);
}
}
My test:
void main() {
Widget buildTestableWidget(Widget widget) {
return new MediaQuery(
data: new MediaQueryData(), child: new MaterialApp(home: widget));
}
Home home = Home();
testWidgets('scroll test', (WidgetTester tester) async {
await tester.pumpWidget(buildTestableWidget(home));
expect(find.text('aaa'), findsOneWidget);
expect(find.text('bbb'), findsNothing);
final Offset point = tester.getCenter(find.text("aaa"));
final gesture = await tester.startGesture(point);
await gesture.moveBy(const Offset(0.0, -400.0));
await tester.pump();
expect(find.text('bbb'), findsOneWidget);
});
}
Is this a bug or do I need to do something different to get TestGesture.moveBy to work in a TabBarView? Many thanks for your help.