// 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:test/test.dart' hide TypeMatcher; class TestTransition extends AnimatedComponent { TestTransition({ Key key, this.childFirstHalf, this.childSecondHalf, Animation<double> animation }) : super(key: key, animation: animation) { assert(animation != null); } final Widget childFirstHalf; final Widget childSecondHalf; Widget build(BuildContext context) { final Animation<double> animation = this.animation; if (animation.value >= 0.5) return childSecondHalf; return childFirstHalf; } } class TestRoute<T> extends PageRoute<T> { TestRoute({ this.child, RouteSettings settings}) : super(settings: settings); final Widget child; Duration get transitionDuration => kMaterialPageRouteTransitionDuration; Color get barrierColor => null; Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { return child; } } void main() { final Duration kTwoTenthsOfTheTransitionDuration = kMaterialPageRouteTransitionDuration * 0.2; final Duration kFourTenthsOfTheTransitionDuration = kMaterialPageRouteTransitionDuration * 0.4; test('Check onstage/offstage handling around transitions', () { testWidgets((WidgetTester tester) { GlobalKey insideKey = new GlobalKey(); String state() { String result = ''; if (tester.findText('A') != null) result += 'A'; if (tester.findText('B') != null) result += 'B'; if (tester.findText('C') != null) result += 'C'; if (tester.findText('D') != null) result += 'D'; if (tester.findText('E') != null) result += 'E'; if (tester.findText('F') != null) result += 'F'; if (tester.findText('G') != null) result += 'G'; return result; } tester.pumpWidget( new MaterialApp( onGenerateRoute: (RouteSettings settings) { switch (settings.name) { case '/': return new TestRoute( settings: settings, child: new Builder( key: insideKey, builder: (BuildContext context) { PageRoute route = ModalRoute.of(context); return new Column( children: <Widget>[ new TestTransition( childFirstHalf: new Text('A'), childSecondHalf: new Text('B'), animation: route.animation ), new TestTransition( childFirstHalf: new Text('C'), childSecondHalf: new Text('D'), animation: route.forwardAnimation ), ] ); } ) ); case '/2': return new TestRoute(settings: settings, child: new Text('E')); case '/3': return new TestRoute(settings: settings, child: new Text('F')); case '/4': return new TestRoute(settings: settings, child: new Text('G')); } } ) ); NavigatorState navigator = insideKey.currentContext.ancestorStateOfType(const TypeMatcher<NavigatorState>()); expect(state(), equals('BC')); // transition ->1 is at 1.0 navigator.openTransaction((NavigatorTransaction transaction) => transaction.pushNamed('/2')); expect(state(), equals('BC')); // transition 1->2 is not yet built tester.pump(); expect(state(), equals('BCE')); // transition 1->2 is at 0.0 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BCE')); // transition 1->2 is at 0.4 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BDE')); // transition 1->2 is at 0.8 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('E')); // transition 1->2 is at 1.0 navigator.openTransaction((NavigatorTransaction transaction) => transaction.pop()); expect(state(), equals('E')); // transition 1<-2 is at 1.0, just reversed tester.pump(); expect(state(), equals('BDE')); // transition 1<-2 is at 1.0 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BDE')); // transition 1<-2 is at 0.6 navigator.openTransaction((NavigatorTransaction transaction) => transaction.pushNamed('/3')); expect(state(), equals('BDE')); // transition 1<-2 is at 0.6 tester.pump(); expect(state(), equals('BDEF')); // transition 1<-2 is at 0.6, 1->3 is at 0.0 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BCEF')); // transition 1<-2 is at 0.2, 1->3 is at 0.4 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BDF')); // transition 1<-2 is done, 1->3 is at 0.8 navigator.openTransaction((NavigatorTransaction transaction) => transaction.pop()); expect(state(), equals('BDF')); // transition 1<-3 is at 0.8, just reversed tester.pump(); expect(state(), equals('BDF')); // transition 1<-3 is at 0.8 tester.pump(kTwoTenthsOfTheTransitionDuration); // notice that dT=0.2 here, not 0.4 expect(state(), equals('BDF')); // transition 1<-3 is at 0.6 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BCF')); // transition 1<-3 is at 0.2 navigator.openTransaction((NavigatorTransaction transaction) => transaction.pushNamed('/4')); expect(state(), equals('BCF')); // transition 1<-3 is at 0.2, 1->4 is not yet built tester.pump(); expect(state(), equals('BCFG')); // transition 1<-3 is at 0.2, 1->4 is at 0.0 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BCG')); // transition 1<-3 is done, 1->4 is at 0.4 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('BDG')); // transition 1->4 is at 0.8 tester.pump(kFourTenthsOfTheTransitionDuration); expect(state(), equals('G')); // transition 1->4 is done }); }); }