// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/widgets.dart'; import 'test_widgets.dart'; void main() { testWidgets('ListView.builder mount/dismount smoke test', (WidgetTester tester) async { final List<int> callbackTracker = <int>[]; // the root view is 800x600 in the test environment // so if our widget is 100 pixels tall, it should fit exactly 6 times. Widget builder() { return new Directionality( textDirection: TextDirection.ltr, child: new FlipWidget( left: new ListView.builder( itemExtent: 100.0, itemBuilder: (BuildContext context, int index) { callbackTracker.add(index); return new Container( key: new ValueKey<int>(index), height: 100.0, child: new Text('$index'), ); }, ), right: const Text('Not Today'), ), ); } await tester.pumpWidget(builder()); final FlipWidgetState testWidget = tester.state(find.byType(FlipWidget)); expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4, 5])); callbackTracker.clear(); testWidget.flip(); await tester.pump(); expect(callbackTracker, equals(<int>[])); callbackTracker.clear(); testWidget.flip(); await tester.pump(); expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4, 5])); }); testWidgets('ListView.builder vertical', (WidgetTester tester) async { final List<int> callbackTracker = <int>[]; // the root view is 800x600 in the test environment // so if our widget is 200 pixels tall, it should fit exactly 3 times. // but if we are offset by 300 pixels, there will be 4, numbered 1-4. final IndexedWidgetBuilder itemBuilder = (BuildContext context, int index) { callbackTracker.add(index); return new Container( key: new ValueKey<int>(index), width: 500.0, // this should be ignored height: 400.0, // should be overridden by itemExtent child: new Text('$index', textDirection: TextDirection.ltr) ); }; Widget buildWidget() { return new Directionality( textDirection: TextDirection.ltr, child: new FlipWidget( left: new ListView.builder( controller: new ScrollController(initialScrollOffset: 300.0), itemExtent: 200.0, itemBuilder: itemBuilder, ), right: const Text('Not Today'), ), ); } void jumpTo(double newScrollOffset) { final ScrollableState scrollable = tester.state(find.byType(Scrollable)); scrollable.position.jumpTo(newScrollOffset); } await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[1, 2, 3, 4])); callbackTracker.clear(); jumpTo(400.0); // now only 3 should fit, numbered 2-4. await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[1, 2, 3, 4])); callbackTracker.clear(); await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[2, 3, 4])); callbackTracker.clear(); jumpTo(500.0); // now 4 should fit, numbered 2-5. await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[2, 3, 4, 5])); callbackTracker.clear(); }); testWidgets('ListView.builder horizontal', (WidgetTester tester) async { final List<int> callbackTracker = <int>[]; // the root view is 800x600 in the test environment // so if our widget is 200 pixels wide, it should fit exactly 4 times. // but if we are offset by 300 pixels, there will be 5, numbered 1-5. final IndexedWidgetBuilder itemBuilder = (BuildContext context, int index) { callbackTracker.add(index); return new Container( key: new ValueKey<int>(index), width: 400.0, // this should be overridden by itemExtent height: 500.0, // this should be ignored child: new Text('$index'), ); }; Widget buildWidget() { return new Directionality( textDirection: TextDirection.ltr, child: new FlipWidget( left: new ListView.builder( controller: new ScrollController(initialScrollOffset: 300.0), itemBuilder: itemBuilder, itemExtent: 200.0, scrollDirection: Axis.horizontal, ), right: const Text('Not Today'), ), ); } void jumpTo(double newScrollOffset) { final ScrollableState scrollable = tester.state(find.byType(Scrollable)); scrollable.position.jumpTo(newScrollOffset); } await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[1, 2, 3, 4, 5])); callbackTracker.clear(); jumpTo(400.0); // now only 4 should fit, numbered 2-5. await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[1, 2, 3, 4, 5])); callbackTracker.clear(); await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[2, 3, 4, 5])); callbackTracker.clear(); jumpTo(500.0); // now only 5 should fit, numbered 2-6. await tester.pumpWidget(buildWidget()); expect(callbackTracker, equals(<int>[2, 3, 4, 5, 6])); callbackTracker.clear(); }); testWidgets('ListView.builder 10 items, 2-3 items visible', (WidgetTester tester) async { final List<int> callbackTracker = <int>[]; // The root view is 800x600 in the test environment and our list // items are 300 tall. Scrolling should cause two or three items // to be built. final IndexedWidgetBuilder itemBuilder = (BuildContext context, int index) { callbackTracker.add(index); return new Text('$index', key: new ValueKey<int>(index), textDirection: TextDirection.ltr); }; final Widget testWidget = new Directionality( textDirection: TextDirection.ltr, child: new ListView.builder( itemBuilder: itemBuilder, itemExtent: 300.0, itemCount: 10, ), ); void jumpTo(double newScrollOffset) { final ScrollableState scrollable = tester.state(find.byType(Scrollable)); scrollable.position.jumpTo(newScrollOffset); } await tester.pumpWidget(testWidget); expect(callbackTracker, equals(<int>[0, 1])); callbackTracker.clear(); jumpTo(150.0); await tester.pump(); expect(callbackTracker, equals(<int>[2])); callbackTracker.clear(); jumpTo(600.0); await tester.pump(); expect(callbackTracker, equals(<int>[3])); callbackTracker.clear(); jumpTo(750.0); await tester.pump(); expect(callbackTracker, equals(<int>[4])); callbackTracker.clear(); }); }