page_forward_transitions_test.dart 6.74 KB
Newer Older
Hixie's avatar
Hixie committed
1 2 3 4
// 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.

5
import 'package:flutter_test/flutter_test.dart' hide TypeMatcher;
Hixie's avatar
Hixie committed
6
import 'package:flutter/material.dart';
7
import 'package:flutter/rendering.dart';
Hixie's avatar
Hixie committed
8

9
class TestTransition extends AnimatedWidget {
Hixie's avatar
Hixie committed
10 11 12 13
  TestTransition({
    Key key,
    this.childFirstHalf,
    this.childSecondHalf,
14
    Animation<double> animation
15
  }) : super(key: key, animation: animation);
Hixie's avatar
Hixie committed
16 17 18 19

  final Widget childFirstHalf;
  final Widget childSecondHalf;

20
  @override
Hixie's avatar
Hixie committed
21
  Widget build(BuildContext context) {
22
    final Animation<double> animation = this.animation;
23
    if (animation.value >= 0.5)
Hixie's avatar
Hixie committed
24 25 26 27 28
      return childSecondHalf;
    return childFirstHalf;
  }
}

29
class TestRoute<T> extends PageRoute<T> {
30
  TestRoute({ this.child, RouteSettings settings }) : super(settings: settings);
31

32
  final Widget child;
33 34

  @override
35
  Duration get transitionDuration => const Duration(milliseconds: 150);
36 37

  @override
38
  Color get barrierColor => null;
39

40 41 42
  @override
  bool get maintainState => false;

43
  @override
44
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
45 46
    return child;
  }
47 48
}

Hixie's avatar
Hixie committed
49
void main() {
50 51
  final Duration kTwoTenthsOfTheTransitionDuration = const Duration(milliseconds: 30);
  final Duration kFourTenthsOfTheTransitionDuration = const Duration(milliseconds: 60);
Hixie's avatar
Hixie committed
52

53
  testWidgets('Check onstage/offstage handling around transitions', (WidgetTester tester) async {
54 55 56

    GlobalKey insideKey = new GlobalKey();

57
    String state({ bool skipOffstage: true }) {
58
      String result = '';
59
      if (tester.any(find.text('A', skipOffstage: skipOffstage)))
60
        result += 'A';
61
      if (tester.any(find.text('B', skipOffstage: skipOffstage)))
62
        result += 'B';
63
      if (tester.any(find.text('C', skipOffstage: skipOffstage)))
64
        result += 'C';
65
      if (tester.any(find.text('D', skipOffstage: skipOffstage)))
66
        result += 'D';
67
      if (tester.any(find.text('E', skipOffstage: skipOffstage)))
68
        result += 'E';
69
      if (tester.any(find.text('F', skipOffstage: skipOffstage)))
70
        result += 'F';
71
      if (tester.any(find.text('G', skipOffstage: skipOffstage)))
72 73 74 75
        result += 'G';
      return result;
    }

76
    await tester.pumpWidget(
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
      new MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          switch (settings.name) {
            case '/':
              return new TestRoute<Null>(
                settings: settings,
                child: new Builder(
                  key: insideKey,
                  builder: (BuildContext context) {
                    PageRoute<Null> 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<Null>(settings: settings, child: new Text('E'));
105 106
            case '/3': return new TestRoute<Null>(settings: settings, child: new Text('F'));
            case '/4': return new TestRoute<Null>(settings: settings, child: new Text('G'));
Hixie's avatar
Hixie committed
107
          }
108 109 110
        }
      )
    );
Hixie's avatar
Hixie committed
111

112
    NavigatorState navigator = insideKey.currentContext.ancestorStateOfType(const TypeMatcher<NavigatorState>());
Hixie's avatar
Hixie committed
113

114
    expect(state(), equals('BC')); // transition ->1 is at 1.0
Hixie's avatar
Hixie committed
115

116
    navigator.pushNamed('/2');
117
    expect(state(), equals('BC')); // transition 1->2 is not yet built
118
    await tester.pump();
119 120
    expect(state(), equals('BC')); // transition 1->2 is at 0.0
    expect(state(skipOffstage: false), equals('BCE')); // E is offstage
Hixie's avatar
Hixie committed
121

122
    await tester.pump(kFourTenthsOfTheTransitionDuration);
123
    expect(state(), equals('BCE')); // transition 1->2 is at 0.4
Hixie's avatar
Hixie committed
124

125
    await tester.pump(kFourTenthsOfTheTransitionDuration);
126
    expect(state(), equals('BDE')); // transition 1->2 is at 0.8
Hixie's avatar
Hixie committed
127

128
    await tester.pump(kFourTenthsOfTheTransitionDuration);
129
    expect(state(), equals('E')); // transition 1->2 is at 1.0
130
    expect(state(skipOffstage: false), equals('E')); // B and C are gone, the route is inactive with maintainState=false
Hixie's avatar
Hixie committed
131

132
    navigator.pop();
133
    expect(state(), equals('E')); // transition 1<-2 is at 1.0, just reversed
134
    await tester.pump();
135
    expect(state(), equals('BDE')); // transition 1<-2 is at 1.0
Hixie's avatar
Hixie committed
136

137
    await tester.pump(kFourTenthsOfTheTransitionDuration);
138
    expect(state(), equals('BDE')); // transition 1<-2 is at 0.6
Hixie's avatar
Hixie committed
139

140
    navigator.pushNamed('/3');
141
    expect(state(), equals('BDE')); // transition 1<-2 is at 0.6
142
    await tester.pump();
143 144
    expect(state(), equals('BDE')); // transition 1<-2 is at 0.6, 1->3 is at 0.0
    expect(state(skipOffstage: false), equals('BDEF')); // F is offstage since we're at 0.0
Hixie's avatar
Hixie committed
145

146
    await tester.pump(kFourTenthsOfTheTransitionDuration);
147
    expect(state(), equals('BCEF')); // transition 1<-2 is at 0.2, 1->3 is at 0.4
148
    expect(state(skipOffstage: false), equals('BCEF')); // nothing secret going on here
Hixie's avatar
Hixie committed
149

150
    await tester.pump(kFourTenthsOfTheTransitionDuration);
151
    expect(state(), equals('BDF')); // transition 1<-2 is done, 1->3 is at 0.8
Hixie's avatar
Hixie committed
152

153
    navigator.pop();
154
    expect(state(), equals('BDF')); // transition 1<-3 is at 0.8, just reversed
155
    await tester.pump();
156
    expect(state(), equals('BDF')); // transition 1<-3 is at 0.8
Hixie's avatar
Hixie committed
157

158
    await tester.pump(kTwoTenthsOfTheTransitionDuration); // notice that dT=0.2 here, not 0.4
159
    expect(state(), equals('BDF')); // transition 1<-3 is at 0.6
Hixie's avatar
Hixie committed
160

161
    await tester.pump(kFourTenthsOfTheTransitionDuration);
162
    expect(state(), equals('BCF')); // transition 1<-3 is at 0.2
Hixie's avatar
Hixie committed
163

164
    navigator.pushNamed('/4');
165
    expect(state(), equals('BCF')); // transition 1<-3 is at 0.2, 1->4 is not yet built
166
    await tester.pump();
167 168
    expect(state(), equals('BCF')); // transition 1<-3 is at 0.2, 1->4 is at 0.0
    expect(state(skipOffstage: false), equals('BCFG')); // G is offstage
Hixie's avatar
Hixie committed
169

170
    await tester.pump(kFourTenthsOfTheTransitionDuration);
171
    expect(state(), equals('BCG')); // transition 1<-3 is done, 1->4 is at 0.4
Hixie's avatar
Hixie committed
172

173
    await tester.pump(kFourTenthsOfTheTransitionDuration);
174
    expect(state(), equals('BDG')); // transition 1->4 is at 0.8
Hixie's avatar
Hixie committed
175

176
    await tester.pump(kFourTenthsOfTheTransitionDuration);
177
    expect(state(), equals('G')); // transition 1->4 is done
178
    expect(state(skipOffstage: false), equals('G')); // route 1 is not around any more
Hixie's avatar
Hixie committed
179 180 181

  });
}