ticker_test.dart 5.87 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/foundation.dart';
6
import 'package:flutter/scheduler.dart';
7
import 'package:flutter/services.dart';
8
import 'package:flutter_test/flutter_test.dart';
9
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
10 11

void main() {
12 13 14
  Future<void> setAppLifeCycleState(AppLifecycleState state) async {
    final ByteData? message =
        const StringCodec().encodeMessage(state.toString());
15
    await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
16 17 18
        .handlePlatformMessage('flutter/lifecycle', message, (_) {});
  }

19
  testWidgets('Ticker mute control test', (WidgetTester tester) async {
20 21
    int tickCount = 0;
    void handleTick(Duration duration) {
22
      tickCount += 1;
23 24
    }

25
    final Ticker ticker = Ticker(handleTick);
26
    addTearDown(ticker.dispose);
27 28 29 30 31 32 33 34 35 36

    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isFalse);

    ticker.start();

    expect(ticker.isTicking, isTrue);
    expect(ticker.isActive, isTrue);
    expect(tickCount, equals(0));

37
    FlutterError? error;
38 39 40 41 42 43
    try {
      ticker.start();
    } on FlutterError catch (e) {
      error = e;
    }
    expect(error, isNotNull);
44
    expect(error!.diagnostics.length, 3);
Dan Field's avatar
Dan Field committed
45
    expect(error.diagnostics.last, isA<DiagnosticsProperty<Ticker>>());
46 47 48 49 50 51 52 53 54 55 56
    expect(
      error.toStringDeep(),
      startsWith(
        'FlutterError\n'
        '   A ticker was started twice.\n'
        '   A ticker that is already active cannot be started again without\n'
        '   first stopping it.\n'
        '   The affected ticker was:\n'
        '     Ticker()\n',
      ),
    );
57

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(1));

    ticker.muted = true;
    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(1));
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isTrue);

    ticker.muted = false;
    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(2));
    expect(ticker.isTicking, isTrue);
    expect(ticker.isActive, isTrue);

    ticker.muted = true;
    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(2));
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isTrue);

    ticker.stop();

    expect(tickCount, equals(2));
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isFalse);

    ticker.muted = false;

    expect(tickCount, equals(2));
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isFalse);

    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(2));
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isFalse);
  });
101

102
  testWidgets('Ticker control test', (WidgetTester tester) async {
103
    late Ticker ticker;
104
    addTearDown(() => ticker.dispose());
105 106

    void testFunction() {
107
      ticker = Ticker((Duration _) { });
108 109 110 111 112 113 114
    }

    testFunction();

    expect(ticker, hasOneLineDescription);
    expect(ticker.toString(debugIncludeStack: true), contains('testFunction'));
  });
115

116
  testWidgets('Ticker can be sped up with time dilation', (WidgetTester tester) async {
117
    timeDilation = 0.5; // Move twice as fast.
118
    late Duration lastDuration;
119 120 121 122
    void handleTick(Duration duration) {
      lastDuration = duration;
    }

123
    final Ticker ticker = Ticker(handleTick);
124 125 126 127 128 129
    ticker.start();
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    expect(lastDuration, const Duration(milliseconds: 20));

    ticker.dispose();
130 131

    timeDilation = 1.0; // restore time dilation, or it will affect other tests
132 133
  });

134
  testWidgets('Ticker can be slowed down with time dilation', (WidgetTester tester) async {
135
    timeDilation = 2.0; // Move half as fast.
136
    late Duration lastDuration;
137 138 139 140
    void handleTick(Duration duration) {
      lastDuration = duration;
    }

141
    final Ticker ticker = Ticker(handleTick);
142 143 144 145 146 147
    ticker.start();
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    expect(lastDuration, const Duration(milliseconds: 5));

    ticker.dispose();
148 149

    timeDilation = 1.0; // restore time dilation, or it will affect other tests
150 151
  });

152
  testWidgets('Ticker stops ticking when application is paused', (WidgetTester tester) async {
153 154 155 156 157
    int tickCount = 0;
    void handleTick(Duration duration) {
      tickCount += 1;
    }

158
    final Ticker ticker = Ticker(handleTick);
159
    addTearDown(ticker.dispose);
160 161 162 163 164 165
    ticker.start();

    expect(ticker.isTicking, isTrue);
    expect(ticker.isActive, isTrue);
    expect(tickCount, equals(0));

166 167
    setAppLifeCycleState(AppLifecycleState.paused);

168 169 170 171
    expect(ticker.isTicking, isFalse);
    expect(ticker.isActive, isTrue);

    ticker.stop();
172 173

    setAppLifeCycleState(AppLifecycleState.resumed);
174
  });
175

176
  testWidgets('Ticker can be created before application unpauses', (WidgetTester tester) async {
177
    setAppLifeCycleState(AppLifecycleState.paused);
178

179 180 181 182 183
    int tickCount = 0;
    void handleTick(Duration duration) {
      tickCount += 1;
    }

184
    final Ticker ticker = Ticker(handleTick);
185
    addTearDown(ticker.dispose);
186 187 188 189 190 191 192 193 194 195
    ticker.start();

    expect(tickCount, equals(0));
    expect(ticker.isTicking, isFalse);

    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(0));
    expect(ticker.isTicking, isFalse);

196
    setAppLifeCycleState(AppLifecycleState.resumed);
197

198 199 200 201 202 203 204
    await tester.pump(const Duration(milliseconds: 10));

    expect(tickCount, equals(1));
    expect(ticker.isTicking, isTrue);

    ticker.stop();
  });
205 206 207 208 209 210 211

  test('Ticker dispatches memory events', () async {
    await expectLater(
      await memoryEvents(() => Ticker((_) {}).dispose(), Ticker,),
      areCreateAndDispose,
    );
  });
212
}