| // Copyright 2017 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'; |
| |
| void main() { |
| testWidgets('AnimatedList initialItemCount', (WidgetTester tester) async { |
| final Map<int, Animation<double>> animations = <int, Animation<double>>{}; |
| |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new AnimatedList( |
| initialItemCount: 2, |
| itemBuilder: (BuildContext context, int index, Animation<double> animation) { |
| animations[index] = animation; |
| return new SizedBox( |
| height: 100.0, |
| child: new Center( |
| child: new Text('item $index'), |
| ), |
| ); |
| }, |
| ), |
| ), |
| ); |
| |
| expect(find.text('item 0'), findsOneWidget); |
| expect(find.text('item 1'), findsOneWidget); |
| expect(animations.containsKey(0), true); |
| expect(animations.containsKey(1), true); |
| expect(animations[0].value, 1.0); |
| expect(animations[1].value, 1.0); |
| }); |
| |
| testWidgets('AnimatedList insert', (WidgetTester tester) async { |
| final GlobalKey<AnimatedListState> listKey = new GlobalKey<AnimatedListState>(); |
| |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new AnimatedList( |
| key: listKey, |
| itemBuilder: (BuildContext context, int index, Animation<double> animation) { |
| return new SizeTransition( |
| key: new ValueKey<int>(index), |
| axis: Axis.vertical, |
| sizeFactor: animation, |
| child: new SizedBox( |
| height: 100.0, |
| child: new Center( |
| child: new Text('item $index'), |
| ), |
| ), |
| ); |
| }, |
| ), |
| ), |
| ); |
| |
| double itemHeight(int index) => tester.getSize(find.byKey(new ValueKey<int>(index))).height; |
| double itemTop(int index) => tester.getTopLeft(find.byKey(new ValueKey<int>(index))).dy; |
| double itemBottom(int index) => tester.getBottomLeft(find.byKey(new ValueKey<int>(index))).dy; |
| |
| listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100)); |
| await tester.pump(); |
| |
| // Newly inserted item 0's height should animate from 0 to 100 |
| expect(itemHeight(0), 0.0); |
| await tester.pump(const Duration(milliseconds: 50)); |
| expect(itemHeight(0), 50.0); |
| await tester.pump(const Duration(milliseconds: 50)); |
| expect(itemHeight(0), 100.0); |
| |
| // The list now contains one fully expanded item at the top: |
| expect(find.text('item 0'), findsOneWidget); |
| expect(itemTop(0), 0.0); |
| expect(itemBottom(0), 100.0); |
| |
| listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100)); |
| listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100)); |
| await tester.pump(); |
| |
| // The height of the newly inserted items at index 0 and 1 should animate from 0 to 100. |
| // The height of the original item, now at index 2, should remain 100. |
| expect(itemHeight(0), 0.0); |
| expect(itemHeight(1), 0.0); |
| expect(itemHeight(2), 100.0); |
| await tester.pump(const Duration(milliseconds: 50)); |
| expect(itemHeight(0), 50.0); |
| expect(itemHeight(1), 50.0); |
| expect(itemHeight(2), 100.0); |
| await tester.pump(const Duration(milliseconds: 50)); |
| expect(itemHeight(0), 100.0); |
| expect(itemHeight(1), 100.0); |
| expect(itemHeight(2), 100.0); |
| |
| // The newly inserted "item 1" and "item 2" appear above "item 0" |
| expect(find.text('item 0'), findsOneWidget); |
| expect(find.text('item 1'), findsOneWidget); |
| expect(find.text('item 2'), findsOneWidget); |
| expect(itemTop(0), 0.0); |
| expect(itemBottom(0), 100.0); |
| expect(itemTop(1), 100.0); |
| expect(itemBottom(1), 200.0); |
| expect(itemTop(2), 200.0); |
| expect(itemBottom(2), 300.0); |
| }); |
| |
| testWidgets('AnimatedList remove', (WidgetTester tester) async { |
| final GlobalKey<AnimatedListState> listKey = new GlobalKey<AnimatedListState>(); |
| final List<int> items = <int>[0, 1, 2]; |
| |
| Widget buildItem(BuildContext context, int item, Animation<double> animation) { |
| return new SizeTransition( |
| key: new ValueKey<int>(item), |
| axis: Axis.vertical, |
| sizeFactor: animation, |
| child: new SizedBox( |
| height: 100.0, |
| child: new Center( |
| child: new Text('item $item', textDirection: TextDirection.ltr), |
| ), |
| ), |
| ); |
| } |
| |
| await tester.pumpWidget( |
| new Directionality( |
| textDirection: TextDirection.ltr, |
| child: new AnimatedList( |
| key: listKey, |
| initialItemCount: 3, |
| itemBuilder: (BuildContext context, int index, Animation<double> animation) { |
| return buildItem(context, items[index], animation); |
| }, |
| ), |
| ), |
| ); |
| |
| double itemTop(int index) => tester.getTopLeft(find.byKey(new ValueKey<int>(index))).dy; |
| double itemBottom(int index) => tester.getBottomLeft(find.byKey(new ValueKey<int>(index))).dy; |
| |
| expect(find.text('item 0'), findsOneWidget); |
| expect(find.text('item 1'), findsOneWidget); |
| expect(find.text('item 2'), findsOneWidget); |
| |
| items.removeAt(0); |
| listKey.currentState.removeItem(0, |
| (BuildContext context, Animation<double> animation) => buildItem(context, 0, animation), |
| duration: const Duration(milliseconds: 100), |
| ); |
| |
| // Items 0, 1, 2 at 0, 100, 200. All heights 100. |
| expect(itemTop(0), 0.0); |
| expect(itemBottom(0), 100.0); |
| expect(itemTop(1), 100.0); |
| expect(itemBottom(1), 200.0); |
| expect(itemTop(2), 200.0); |
| expect(itemBottom(2), 300.0); |
| |
| // Newly removed item 0's height should animate from 100 to 0 over 100ms |
| |
| // Items 0, 1, 2 at 0, 50, 150. Item 0's height is 50. |
| await tester.pump(); |
| await tester.pump(const Duration(milliseconds: 50)); |
| expect(itemTop(0), 0.0); |
| expect(itemBottom(0), 50.0); |
| expect(itemTop(1), 50.0); |
| expect(itemBottom(1), 150.0); |
| expect(itemTop(2), 150.0); |
| expect(itemBottom(2), 250.0); |
| |
| // Items 1, 2 at 0, 100. |
| await tester.pumpAndSettle(); |
| expect(itemTop(1), 0.0); |
| expect(itemBottom(1), 100.0); |
| expect(itemTop(2), 100.0); |
| expect(itemBottom(2), 200.0); |
| }); |
| } |