// 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/material.dart'; import 'package:flutter/rendering.dart'; import 'test_widgets.dart'; void main() { testWidgets('LazyBlockViewport mount/dismount smoke test', (WidgetTester tester) async { 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 FlipWidget( left: new LazyBlockViewport( delegate: new LazyBlockBuilder(builder: (BuildContext context, int i) { callbackTracker.add(i); return new Container( key: new ValueKey<int>(i), height: 100.0, child: new Text("$i") ); }), startOffset: 0.0 ), right: new Text('Not Today') ); } await tester.pumpWidget(builder()); 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('LazyBlockViewport vertical', (WidgetTester tester) async { 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. double offset = 300.0; IndexedWidgetBuilder itemBuilder = (BuildContext context, int i) { callbackTracker.add(i); return new Container( key: new ValueKey<int>(i), width: 500.0, // this should be ignored height: 200.0, child: new Text("$i") ); }; Widget builder() { return new FlipWidget( left: new LazyBlockViewport( delegate: new LazyBlockBuilder(builder: itemBuilder), startOffset: offset ), right: new Text('Not Today') ); } await tester.pumpWidget(builder()); // 0 is built to find its height expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4])); callbackTracker.clear(); offset = 400.0; // now only 3 should fit, numbered 2-4. await tester.pumpWidget(builder()); // We build all the children to find their new size. expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4])); callbackTracker.clear(); await tester.pumpWidget(builder()); // 0 isn't built because they're not visible. expect(callbackTracker, equals(<int>[1, 2, 3, 4])); callbackTracker.clear(); }); testWidgets('LazyBlockViewport horizontal', (WidgetTester tester) async { 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. double offset = 300.0; IndexedWidgetBuilder itemBuilder = (BuildContext context, int i) { callbackTracker.add(i); return new Container( key: new ValueKey<int>(i), height: 500.0, // this should be ignored width: 200.0, child: new Text("$i") ); }; Widget builder() { return new FlipWidget( left: new LazyBlockViewport( delegate: new LazyBlockBuilder(builder: itemBuilder), startOffset: offset, mainAxis: Axis.horizontal ), right: new Text('Not Today') ); } await tester.pumpWidget(builder()); // 0 is built to find its width expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4, 5])); callbackTracker.clear(); offset = 400.0; // now only 4 should fit, numbered 2-5. await tester.pumpWidget(builder()); // We build all the children to find their new size. expect(callbackTracker, equals(<int>[0, 1, 2, 3, 4, 5])); callbackTracker.clear(); await tester.pumpWidget(builder()); // 0 isn't built because they're not visible. expect(callbackTracker, equals(<int>[1, 2, 3, 4, 5])); callbackTracker.clear(); }); testWidgets('LazyBlockViewport reinvoke builders', (WidgetTester tester) async { List<int> callbackTracker = <int>[]; List<String> text = <String>[]; IndexedWidgetBuilder itemBuilder = (BuildContext context, int i) { callbackTracker.add(i); return new Container( key: new ValueKey<int>(i), width: 500.0, // this should be ignored height: 220.0, child: new Text("$i") ); }; void collectText(Widget widget) { if (widget is Text) text.add(widget.data); } Widget builder() { return new LazyBlockViewport( delegate: new LazyBlockBuilder(builder: itemBuilder), startOffset: 0.0 ); } await tester.pumpWidget(builder()); expect(callbackTracker, equals(<int>[0, 1, 2])); callbackTracker.clear(); tester.allWidgets.forEach(collectText); expect(text, equals(<String>['0', '1', '2'])); text.clear(); await tester.pumpWidget(builder()); expect(callbackTracker, equals(<int>[0, 1, 2])); callbackTracker.clear(); tester.allWidgets.forEach(collectText); expect(text, equals(<String>['0', '1', '2'])); text.clear(); }); testWidgets('LazyBlockViewport reinvoke builders', (WidgetTester tester) async { StateSetter setState; ThemeData themeData = new ThemeData.light(); IndexedWidgetBuilder itemBuilder = (BuildContext context, int i) { return new Container( key: new ValueKey<int>(i), width: 500.0, // this should be ignored height: 220.0, decoration: new BoxDecoration( backgroundColor: Theme.of(context).primaryColor ), child: new Text("$i") ); }; Widget viewport = new LazyBlockViewport( delegate: new LazyBlockBuilder(builder: itemBuilder) ); await tester.pumpWidget( new StatefulBuilder( builder: (BuildContext context, StateSetter setter) { setState = setter; return new Theme(data: themeData, child: viewport); } ) ); DecoratedBox widget = tester.firstWidget(find.byType(DecoratedBox)); BoxDecoration decoraton = widget.decoration; expect(decoraton.backgroundColor, equals(Colors.blue[500])); setState(() { themeData = new ThemeData(primarySwatch: Colors.green); }); await tester.pump(); widget = tester.firstWidget(find.byType(DecoratedBox)); decoraton = widget.decoration; expect(decoraton.backgroundColor, equals(Colors.green[500])); }); testWidgets('LazyBlockViewport padding', (WidgetTester tester) async { IndexedWidgetBuilder itemBuilder = (BuildContext context, int i) { return new Container( key: new ValueKey<int>(i), width: 500.0, // this should be ignored height: 220.0, decoration: new BoxDecoration( backgroundColor: Colors.green[500] ), child: new Text("$i") ); }; await tester.pumpWidget( new LazyBlockViewport( padding: new EdgeInsets.fromLTRB(7.0, 3.0, 5.0, 11.0), delegate: new LazyBlockBuilder(builder: itemBuilder) ) ); RenderBox firstBox = tester.renderObject(find.text('0')); Point upperLeft = firstBox.localToGlobal(Point.origin); expect(upperLeft, equals(new Point(7.0, 3.0))); expect(firstBox.size.width, equals(800.0 - 12.0)); }); testWidgets('Underflow extents', (WidgetTester tester) async { int lastFirstIndex; int lastLastIndex; double lastFirstStartOffset; double lastLastEndOffset; double lastMinScrollOffset; double lastContainerExtent; void handleExtendsChanged(int firstIndex, int lastIndex, double firstStartOffset, double lastEndOffset, double minScrollOffset, double containerExtent) { lastFirstIndex = firstIndex; lastLastIndex = lastIndex; lastFirstStartOffset = firstStartOffset; lastLastEndOffset = lastEndOffset; lastMinScrollOffset = minScrollOffset; lastContainerExtent = containerExtent; } await tester.pumpWidget(new LazyBlockViewport( onExtentsChanged: handleExtendsChanged, delegate: new LazyBlockChildren( children: <Widget>[ new Container(height: 100.0), new Container(height: 100.0), new Container(height: 100.0), ] ) )); expect(lastFirstIndex, 0); expect(lastLastIndex, 2); expect(lastFirstStartOffset, 0.0); expect(lastLastEndOffset, 300.0); expect(lastContainerExtent, 600.0); expect(lastMinScrollOffset, 0.0); }); }