| // Copyright 2014 The Flutter 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/foundation.dart'; |
| import 'package:flutter/scheduler.dart'; |
| import 'package:flutter/services.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| Future<void> setAppLifeCycleState(AppLifecycleState state) async { |
| final ByteData? message = |
| const StringCodec().encodeMessage(state.toString()); |
| await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger |
| .handlePlatformMessage('flutter/lifecycle', message, (_) {}); |
| } |
| |
| testWidgets('Ticker mute control test', (WidgetTester tester) async { |
| int tickCount = 0; |
| void handleTick(Duration duration) { |
| tickCount += 1; |
| } |
| |
| final Ticker ticker = Ticker(handleTick); |
| |
| expect(ticker.isTicking, isFalse); |
| expect(ticker.isActive, isFalse); |
| |
| ticker.start(); |
| |
| expect(ticker.isTicking, isTrue); |
| expect(ticker.isActive, isTrue); |
| expect(tickCount, equals(0)); |
| |
| FlutterError? error; |
| try { |
| ticker.start(); |
| } on FlutterError catch (e) { |
| error = e; |
| } |
| expect(error, isNotNull); |
| expect(error!.diagnostics.length, 3); |
| expect(error.diagnostics.last, isA<DiagnosticsProperty<Ticker>>()); |
| 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', |
| ), |
| ); |
| |
| 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); |
| }); |
| |
| testWidgets('Ticker control test', (WidgetTester tester) async { |
| late Ticker ticker; |
| |
| void testFunction() { |
| ticker = Ticker((Duration _) { }); |
| } |
| |
| testFunction(); |
| |
| expect(ticker, hasOneLineDescription); |
| expect(ticker.toString(debugIncludeStack: true), contains('testFunction')); |
| }); |
| |
| testWidgets('Ticker can be sped up with time dilation', (WidgetTester tester) async { |
| timeDilation = 0.5; // Move twice as fast. |
| late Duration lastDuration; |
| void handleTick(Duration duration) { |
| lastDuration = duration; |
| } |
| |
| final Ticker ticker = Ticker(handleTick); |
| ticker.start(); |
| await tester.pump(const Duration(milliseconds: 10)); |
| await tester.pump(const Duration(milliseconds: 10)); |
| expect(lastDuration, const Duration(milliseconds: 20)); |
| |
| ticker.dispose(); |
| |
| timeDilation = 1.0; // restore time dilation, or it will affect other tests |
| }); |
| |
| testWidgets('Ticker can be slowed down with time dilation', (WidgetTester tester) async { |
| timeDilation = 2.0; // Move half as fast. |
| late Duration lastDuration; |
| void handleTick(Duration duration) { |
| lastDuration = duration; |
| } |
| |
| final Ticker ticker = Ticker(handleTick); |
| ticker.start(); |
| await tester.pump(const Duration(milliseconds: 10)); |
| await tester.pump(const Duration(milliseconds: 10)); |
| expect(lastDuration, const Duration(milliseconds: 5)); |
| |
| ticker.dispose(); |
| |
| timeDilation = 1.0; // restore time dilation, or it will affect other tests |
| }); |
| |
| testWidgets('Ticker stops ticking when application is paused', (WidgetTester tester) async { |
| int tickCount = 0; |
| void handleTick(Duration duration) { |
| tickCount += 1; |
| } |
| |
| final Ticker ticker = Ticker(handleTick); |
| ticker.start(); |
| |
| expect(ticker.isTicking, isTrue); |
| expect(ticker.isActive, isTrue); |
| expect(tickCount, equals(0)); |
| |
| setAppLifeCycleState(AppLifecycleState.paused); |
| |
| expect(ticker.isTicking, isFalse); |
| expect(ticker.isActive, isTrue); |
| |
| ticker.stop(); |
| |
| setAppLifeCycleState(AppLifecycleState.resumed); |
| }); |
| |
| testWidgets('Ticker can be created before application unpauses', (WidgetTester tester) async { |
| setAppLifeCycleState(AppLifecycleState.paused); |
| |
| int tickCount = 0; |
| void handleTick(Duration duration) { |
| tickCount += 1; |
| } |
| |
| final Ticker ticker = Ticker(handleTick); |
| 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); |
| |
| setAppLifeCycleState(AppLifecycleState.resumed); |
| |
| await tester.pump(const Duration(milliseconds: 10)); |
| |
| expect(tickCount, equals(1)); |
| expect(ticker.isTicking, isTrue); |
| |
| ticker.stop(); |
| }); |
| } |