futures_test.dart 7.38 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6
// 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/animation.dart';
7
import 'package:flutter/scheduler.dart';
8 9 10 11
import 'package:flutter/widgets.dart';

void main() {
  testWidgets('awaiting animation controllers - using direct future', (WidgetTester tester) async {
12
    final AnimationController controller1 = AnimationController(
13 14 15
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
16
    final AnimationController controller2 = AnimationController(
17 18 19
      duration: const Duration(milliseconds: 600),
      vsync: const TestVSync(),
    );
20
    final AnimationController controller3 = AnimationController(
21 22 23 24
      duration: const Duration(milliseconds: 300),
      vsync: const TestVSync(),
    );
    final List<String> log = <String>[];
25
    Future<void> runTest() async {
26 27 28
      log.add('a'); // t=0
      await controller1.forward(); // starts at t=0 again
      log.add('b'); // wants to end at t=100 but missed frames until t=150
29 30 31 32
      await controller2.forward(); // starts at t=150
      log.add('c'); // wants to end at t=750 but missed frames until t=799
      await controller3.forward(); // starts at t=799
      log.add('d'); // wants to end at t=1099 but missed frames until t=1200
33 34
    }
    log.add('start');
35
    runTest().then((void value) {
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
      log.add('end');
    });
    await tester.pump(); // t=0
    expect(log, <String>['start', 'a']);
    await tester.pump(); // t=0 again
    expect(log, <String>['start', 'a']);
    await tester.pump(const Duration(milliseconds: 50)); // t=50
    expect(log, <String>['start', 'a']);
    await tester.pump(const Duration(milliseconds: 100)); // t=150
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 50)); // t=200
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 400)); // t=600
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 199)); // t=799
51
    expect(log, <String>['start', 'a', 'b', 'c']);
52 53 54
    await tester.pump(const Duration(milliseconds: 51)); // t=850
    expect(log, <String>['start', 'a', 'b', 'c']);
    await tester.pump(const Duration(milliseconds: 400)); // t=1200
55
    expect(log, <String>['start', 'a', 'b', 'c', 'd', 'end']);
56 57 58 59 60
    await tester.pump(const Duration(milliseconds: 400)); // t=1600
    expect(log, <String>['start', 'a', 'b', 'c', 'd', 'end']);
  });

  testWidgets('awaiting animation controllers - using orCancel', (WidgetTester tester) async {
61
    final AnimationController controller1 = AnimationController(
62 63 64
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
65
    final AnimationController controller2 = AnimationController(
66 67 68
      duration: const Duration(milliseconds: 600),
      vsync: const TestVSync(),
    );
69
    final AnimationController controller3 = AnimationController(
70 71 72 73
      duration: const Duration(milliseconds: 300),
      vsync: const TestVSync(),
    );
    final List<String> log = <String>[];
74
    Future<void> runTest() async {
75 76 77
      log.add('a'); // t=0
      await controller1.forward().orCancel; // starts at t=0 again
      log.add('b'); // wants to end at t=100 but missed frames until t=150
78 79 80 81
      await controller2.forward().orCancel; // starts at t=150
      log.add('c'); // wants to end at t=750 but missed frames until t=799
      await controller3.forward().orCancel; // starts at t=799
      log.add('d'); // wants to end at t=1099 but missed frames until t=1200
82 83
    }
    log.add('start');
84
    runTest().then((void value) {
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
      log.add('end');
    });
    await tester.pump(); // t=0
    expect(log, <String>['start', 'a']);
    await tester.pump(); // t=0 again
    expect(log, <String>['start', 'a']);
    await tester.pump(const Duration(milliseconds: 50)); // t=50
    expect(log, <String>['start', 'a']);
    await tester.pump(const Duration(milliseconds: 100)); // t=150
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 50)); // t=200
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 400)); // t=600
    expect(log, <String>['start', 'a', 'b']);
    await tester.pump(const Duration(milliseconds: 199)); // t=799
100
    expect(log, <String>['start', 'a', 'b', 'c']);
101 102 103
    await tester.pump(const Duration(milliseconds: 51)); // t=850
    expect(log, <String>['start', 'a', 'b', 'c']);
    await tester.pump(const Duration(milliseconds: 400)); // t=1200
104
    expect(log, <String>['start', 'a', 'b', 'c', 'd', 'end']);
105 106 107 108 109
    await tester.pump(const Duration(milliseconds: 400)); // t=1600
    expect(log, <String>['start', 'a', 'b', 'c', 'd', 'end']);
  });

  testWidgets('awaiting animation controllers and failing', (WidgetTester tester) async {
110
    final AnimationController controller1 = AnimationController(
111 112 113 114
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
    final List<String> log = <String>[];
115
    Future<void> runTest() async {
116 117 118 119 120 121 122 123
      try {
        log.add('start');
        await controller1.forward().orCancel;
        log.add('fail');
      } on TickerCanceled {
        log.add('caught');
      }
    }
124
    runTest().then((void value) {
125 126 127 128 129 130 131 132 133 134 135 136 137
      log.add('end');
    });
    await tester.pump(); // start ticker
    expect(log, <String>['start']);
    await tester.pump(const Duration(milliseconds: 50));
    expect(log, <String>['start']);
    controller1.dispose();
    expect(log, <String>['start']);
    await tester.idle();
    expect(log, <String>['start', 'caught', 'end']);
  });

  testWidgets('creating orCancel future later', (WidgetTester tester) async {
138
    final AnimationController controller1 = AnimationController(
139 140 141 142 143 144 145 146 147 148 149 150
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
    final TickerFuture f = controller1.forward();
    await tester.pump(); // start ticker
    await tester.pump(const Duration(milliseconds: 200)); // end ticker
    await f; // should be a no-op
    await f.orCancel; // should create a resolved future
    expect(true, isTrue); // should reach here
  });

  testWidgets('creating orCancel future later', (WidgetTester tester) async {
151
    final AnimationController controller1 = AnimationController(
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
    final TickerFuture f = controller1.forward();
    await tester.pump(); // start ticker
    controller1.stop(); // cancel ticker
    bool ok = false;
    try {
      await f.orCancel; // should create a resolved future
    } on TickerCanceled {
      ok = true;
    }
    expect(ok, isTrue); // should reach here
  });

  testWidgets('TickerFuture is a Future', (WidgetTester tester) async {
168
    final AnimationController controller1 = AnimationController(
169 170 171 172 173 174
      duration: const Duration(milliseconds: 100),
      vsync: const TestVSync(),
    );
    final TickerFuture f = controller1.forward();
    await tester.pump(); // start ticker
    await tester.pump(const Duration(milliseconds: 200)); // end ticker
Dan Field's avatar
Dan Field committed
175
    expect(f.asStream().single, isA<Future<void>>());
176
    await f.catchError((dynamic e) { throw 'do not reach'; });
177
    expect(await f.then<bool>((_) => true), isTrue);
Dan Field's avatar
Dan Field committed
178 179
    expect(f.whenComplete(() => false), isA<Future<void>>());
    expect(f.timeout(const Duration(seconds: 5)), isA<Future<void>>());
180 181
  });
}