Unverified Commit fe337dca authored by Swiftaxe's avatar Swiftaxe Committed by GitHub

Animation controller test (#88251)

Co-authored-by: 's avatarAlexander Dahlberg <alexander.dahlberg@sigma.se>

Fixes test/animation/animation_controller_test.dart in #85160

Problem:
The test 'animateTo can deal with duration == Duration.Zero' was failing with the following error:

Expected: <0>
Actual: <5>
Expected no animation.
package:test_api expect
package:flutter_test/src/widget_tester.dart 484:3 expect
test/animation/animation_controller_test.dart 511:5 main.

Following line finds 5 transientCallbacks scheduled, while expecting zero, if shuffled with seed 123:

expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.');

This is caused by some other test leaving transientCallbacks scheduled.

Fix:
By disposing the AnimationController after each test, the transientCallbacks get cleaned up.
I chose to dispose all controllers in every test, to make sure there is no risk of leaks.
parent 06be7e53
...@@ -2,12 +2,6 @@ ...@@ -2,12 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// TODO(gspencergoog): Remove this tag once this test's state leaks/test
// dependencies have been fixed.
// https://github.com/flutter/flutter/issues/85160
// Fails with "flutter test --test-randomize-ordering-seed=123"
@Tags(<String>['no-shuffle'])
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -57,6 +51,7 @@ void main() { ...@@ -57,6 +51,7 @@ void main() {
expect(didDismiss, isTrue); expect(didDismiss, isTrue);
controller.stop(); controller.stop();
controller.dispose();
}); });
test('Receives status callbacks for forward and reverse', () { test('Receives status callbacks for forward and reverse', () {
...@@ -118,6 +113,7 @@ void main() { ...@@ -118,6 +113,7 @@ void main() {
expect(valueLog, equals(<AnimationStatus>[])); expect(valueLog, equals(<AnimationStatus>[]));
controller.stop(); controller.stop();
controller.dispose();
}); });
test('Forward and reverse from values', () { test('Forward and reverse from values', () {
...@@ -144,6 +140,7 @@ void main() { ...@@ -144,6 +140,7 @@ void main() {
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.dismissed, AnimationStatus.forward ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.dismissed, AnimationStatus.forward ]));
expect(valueLog, equals(<double>[ 0.0 ])); expect(valueLog, equals(<double>[ 0.0 ]));
expect(controller.value, equals(0.0)); expect(controller.value, equals(0.0));
controller.dispose();
}); });
test('Forward and reverse with different durations', () { test('Forward and reverse with different durations', () {
...@@ -207,6 +204,7 @@ void main() { ...@@ -207,6 +204,7 @@ void main() {
tick(const Duration(milliseconds: 310)); tick(const Duration(milliseconds: 310));
expect(controller.value, moreOrLessEquals(0.0)); expect(controller.value, moreOrLessEquals(0.0));
controller.stop(); controller.stop();
controller.dispose();
}); });
test('Forward only from value', () { test('Forward only from value', () {
...@@ -226,6 +224,7 @@ void main() { ...@@ -226,6 +224,7 @@ void main() {
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward ]));
expect(valueLog, equals(<double>[ 0.2 ])); expect(valueLog, equals(<double>[ 0.2 ]));
expect(controller.value, equals(0.2)); expect(controller.value, equals(0.2));
controller.dispose();
}); });
test('Can fling to upper and lower bounds', () { test('Can fling to upper and lower bounds', () {
...@@ -256,6 +255,8 @@ void main() { ...@@ -256,6 +255,8 @@ void main() {
tick(const Duration(seconds: 6)); tick(const Duration(seconds: 6));
expect(largeRangeController.value, -30.0); expect(largeRangeController.value, -30.0);
largeRangeController.stop(); largeRangeController.stop();
controller.dispose();
largeRangeController.dispose();
}); });
test('Custom springDescription can be applied', () { test('Custom springDescription can be applied', () {
...@@ -279,6 +280,8 @@ void main() { ...@@ -279,6 +280,8 @@ void main() {
tick(const Duration(milliseconds: 50)); tick(const Duration(milliseconds: 50));
expect(customSpringController.value < controller.value, true); expect(customSpringController.value < controller.value, true);
controller.dispose();
customSpringController.dispose();
}); });
test('lastElapsedDuration control test', () { test('lastElapsedDuration control test', () {
...@@ -292,6 +295,7 @@ void main() { ...@@ -292,6 +295,7 @@ void main() {
tick(const Duration(milliseconds: 40)); tick(const Duration(milliseconds: 40));
expect(controller.lastElapsedDuration, equals(const Duration(milliseconds: 20))); expect(controller.lastElapsedDuration, equals(const Duration(milliseconds: 20)));
controller.stop(); controller.stop();
controller.dispose();
}); });
test('toString control test', () { test('toString control test', () {
...@@ -311,6 +315,7 @@ void main() { ...@@ -311,6 +315,7 @@ void main() {
tick(const Duration(milliseconds: 50)); tick(const Duration(milliseconds: 50));
expect(controller, hasOneLineDescription); expect(controller, hasOneLineDescription);
controller.stop(); controller.stop();
controller.dispose();
}); });
test('velocity test - linear', () { test('velocity test - linear', () {
...@@ -354,6 +359,7 @@ void main() { ...@@ -354,6 +359,7 @@ void main() {
expect(controller.velocity, 0.0); expect(controller.velocity, 0.0);
controller.stop(); controller.stop();
controller.dispose();
}); });
test('Disposed AnimationController toString works', () { test('Disposed AnimationController toString works', () {
...@@ -407,6 +413,7 @@ void main() { ...@@ -407,6 +413,7 @@ void main() {
); );
expect(() { controller.repeat(); }, throwsFlutterError); expect(() { controller.repeat(); }, throwsFlutterError);
expect(() { controller.repeat(period: null); }, throwsFlutterError); expect(() { controller.repeat(period: null); }, throwsFlutterError);
controller.dispose();
}); });
test('Do not animate if already at target', () { test('Do not animate if already at target', () {
...@@ -421,6 +428,7 @@ void main() { ...@@ -421,6 +428,7 @@ void main() {
controller.animateTo(0.5, duration: const Duration(milliseconds: 100)); controller.animateTo(0.5, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(0.5)); expect(controller.value, equals(0.5));
controller.dispose();
}); });
test('Do not animate to upperBound if already at upperBound', () { test('Do not animate to upperBound if already at upperBound', () {
...@@ -437,6 +445,7 @@ void main() { ...@@ -437,6 +445,7 @@ void main() {
controller.animateTo(1.0, duration: const Duration(milliseconds: 100)); controller.animateTo(1.0, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(1.0)); expect(controller.value, equals(1.0));
controller.dispose();
}); });
test('Do not animate to lowerBound if already at lowerBound', () { test('Do not animate to lowerBound if already at lowerBound', () {
...@@ -453,6 +462,7 @@ void main() { ...@@ -453,6 +462,7 @@ void main() {
controller.animateTo(0.0, duration: const Duration(milliseconds: 100)); controller.animateTo(0.0, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(0.0)); expect(controller.value, equals(0.0));
controller.dispose();
}); });
test('Do not animate if already at target mid-flight (forward)', () { test('Do not animate if already at target mid-flight (forward)', () {
...@@ -475,6 +485,7 @@ void main() { ...@@ -475,6 +485,7 @@ void main() {
controller.animateTo(currentValue, duration: const Duration(milliseconds: 100)); controller.animateTo(currentValue, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
expect(controller.value, currentValue); expect(controller.value, currentValue);
controller.dispose();
}); });
test('Do not animate if already at target mid-flight (reverse)', () { test('Do not animate if already at target mid-flight (reverse)', () {
...@@ -497,6 +508,7 @@ void main() { ...@@ -497,6 +508,7 @@ void main() {
controller.animateTo(currentValue, duration: const Duration(milliseconds: 100)); controller.animateTo(currentValue, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.reverse, AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.reverse, AnimationStatus.completed ]));
expect(controller.value, currentValue); expect(controller.value, currentValue);
controller.dispose();
}); });
test('animateTo can deal with duration == Duration.zero', () { test('animateTo can deal with duration == Duration.zero', () {
...@@ -510,6 +522,7 @@ void main() { ...@@ -510,6 +522,7 @@ void main() {
controller.animateTo(1.0, duration: Duration.zero); controller.animateTo(1.0, duration: Duration.zero);
expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.'); expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.');
expect(controller.value, 1.0); expect(controller.value, 1.0);
controller.dispose();
}); });
test('resetting animation works at all phases', () { test('resetting animation works at all phases', () {
...@@ -563,6 +576,7 @@ void main() { ...@@ -563,6 +576,7 @@ void main() {
expect(controller.value, 0.0); expect(controller.value, 0.0);
expect(controller.status, AnimationStatus.dismissed); expect(controller.status, AnimationStatus.dismissed);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed, AnimationStatus.dismissed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed, AnimationStatus.dismissed ]));
controller.dispose();
}); });
test('setting value directly sets correct status', () { test('setting value directly sets correct status', () {
...@@ -591,6 +605,7 @@ void main() { ...@@ -591,6 +605,7 @@ void main() {
controller.value = 0.0; controller.value = 0.0;
expect(controller.value, 0.0); expect(controller.value, 0.0);
expect(controller.status, AnimationStatus.dismissed); expect(controller.status, AnimationStatus.dismissed);
controller.dispose();
}); });
test('animateTo sets correct status', () { test('animateTo sets correct status', () {
...@@ -637,6 +652,7 @@ void main() { ...@@ -637,6 +652,7 @@ void main() {
expect(controller.value, 0.0); expect(controller.value, 0.0);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear(); statusLog.clear();
controller.dispose();
}); });
test('after a reverse call animateTo sets correct status', () { test('after a reverse call animateTo sets correct status', () {
...@@ -665,6 +681,7 @@ void main() { ...@@ -665,6 +681,7 @@ void main() {
expect(controller.value, 0.5); expect(controller.value, 0.5);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear(); statusLog.clear();
controller.dispose();
}); });
test('after a forward call animateTo sets correct status', () { test('after a forward call animateTo sets correct status', () {
...@@ -693,6 +710,7 @@ void main() { ...@@ -693,6 +710,7 @@ void main() {
expect(controller.value, 0.5); expect(controller.value, 0.5);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ])); expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear(); statusLog.clear();
controller.dispose();
}); });
test( test(
...@@ -743,6 +761,7 @@ void main() { ...@@ -743,6 +761,7 @@ void main() {
tick(Duration.zero); tick(Duration.zero);
tick(const Duration(milliseconds: 150)); tick(const Duration(milliseconds: 150));
expect(controller.value, 0.0); expect(controller.value, 0.0);
controller.dispose();
}, },
); );
...@@ -785,6 +804,7 @@ void main() { ...@@ -785,6 +804,7 @@ void main() {
tick(Duration.zero); tick(Duration.zero);
tick(const Duration(milliseconds: 125)); tick(const Duration(milliseconds: 125));
expect(controller.value, 1.0); expect(controller.value, 1.0);
controller.dispose();
}, },
); );
...@@ -795,6 +815,8 @@ void main() { ...@@ -795,6 +815,8 @@ void main() {
final AnimationController repeating = AnimationController.unbounded(vsync: const TestVSync()); final AnimationController repeating = AnimationController.unbounded(vsync: const TestVSync());
expect(repeating.animationBehavior, AnimationBehavior.preserve); expect(repeating.animationBehavior, AnimationBehavior.preserve);
controller.dispose();
repeating.dispose();
}); });
test('AnimationBehavior.preserve runs at normal speed when animatingTo', () { test('AnimationBehavior.preserve runs at normal speed when animatingTo', () {
...@@ -820,6 +842,7 @@ void main() { ...@@ -820,6 +842,7 @@ void main() {
expect(controller.value, 1.0); expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed); expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = false; debugSemanticsDisableAnimations = false;
controller.dispose();
}); });
test('AnimationBehavior.normal runs at 20x speed when animatingTo', () { test('AnimationBehavior.normal runs at 20x speed when animatingTo', () {
...@@ -845,6 +868,7 @@ void main() { ...@@ -845,6 +868,7 @@ void main() {
expect(controller.value, 1.0); expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed); expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = null; debugSemanticsDisableAnimations = null;
controller.dispose();
}); });
test('AnimationBehavior.normal runs "faster" than AnimationBehavior.preserve', () { test('AnimationBehavior.normal runs "faster" than AnimationBehavior.preserve', () {
...@@ -864,6 +888,8 @@ void main() { ...@@ -864,6 +888,8 @@ void main() {
// We don't assert a specific faction that normal animation. // We don't assert a specific faction that normal animation.
expect(controller.value < fastController.value, true); expect(controller.value < fastController.value, true);
debugSemanticsDisableAnimations = null; debugSemanticsDisableAnimations = null;
controller.dispose();
fastController.dispose();
}); });
}); });
...@@ -895,6 +921,7 @@ void main() { ...@@ -895,6 +921,7 @@ void main() {
tick(Duration.zero); tick(Duration.zero);
tick(const Duration(seconds: 2)); tick(const Duration(seconds: 2));
expect(statuses, <AnimationStatus>[AnimationStatus.forward]); expect(statuses, <AnimationStatus>[AnimationStatus.forward]);
controller.dispose();
}); });
test('Simulations run forward even after a reverse run', () { test('Simulations run forward even after a reverse run', () {
...@@ -915,6 +942,7 @@ void main() { ...@@ -915,6 +942,7 @@ void main() {
tick(Duration.zero); tick(Duration.zero);
tick(const Duration(seconds: 2)); tick(const Duration(seconds: 2));
expect(statuses, <AnimationStatus>[AnimationStatus.forward]); expect(statuses, <AnimationStatus>[AnimationStatus.forward]);
controller.dispose();
}); });
test('Repeating animation with reverse: true report as forward and reverse', () { test('Repeating animation with reverse: true report as forward and reverse', () {
...@@ -933,6 +961,7 @@ void main() { ...@@ -933,6 +961,7 @@ void main() {
statuses.clear(); statuses.clear();
tick(const Duration(seconds: 1)); tick(const Duration(seconds: 1));
expect(statuses, <AnimationStatus>[AnimationStatus.reverse]); expect(statuses, <AnimationStatus>[AnimationStatus.reverse]);
controller.dispose();
}); });
test('AnimateBack can runs successfully with just "reverseDuration" property set', () { test('AnimateBack can runs successfully with just "reverseDuration" property set', () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment