| // Copyright 2013 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. |
| |
| // @dart = 2.6 |
| import 'package:test/test.dart'; |
| import 'package:quiver/testing/async.dart'; |
| import 'package:quiver/time.dart'; |
| |
| import 'package:ui/src/engine.dart'; |
| |
| void main() { |
| group(AlarmClock, () { |
| _alarmClockTests(); |
| }); |
| } |
| |
| void _alarmClockTests() { |
| int callCount = 0; |
| |
| void testCallback() { |
| callCount += 1; |
| } |
| |
| setUp(() { |
| callCount = 0; |
| }); |
| |
| testAsync('AlarmClock calls the callback in the future', |
| (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| // There should be no timers scheduled until we set a non-null datetime. |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| |
| // There should be exactly 1 timer scheduled. |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| |
| // No time has passed; the callback should not be called. |
| expect(callCount, 0); |
| |
| // Not enough time has passed; the callback should not be called. |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 0); |
| |
| // Exactly 1 minute has passed; fire the callback. |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 1); |
| |
| // Timers should be cleaned up. |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| |
| // Rescheduling. |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| fakeAsync.elapse(const Duration(minutes: 1)); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| expect(callCount, 2); |
| }); |
| |
| testAsync('AlarmClock does nothing when new datetime is the same', |
| (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| expect(callCount, 0); |
| |
| alarm.datetime = alarm.datetime.add(Duration.zero); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| expect(callCount, 0); |
| |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| |
| alarm.datetime = alarm.datetime.add(Duration.zero); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| expect(callCount, 0); |
| |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| expect(callCount, 1); |
| }); |
| |
| testAsync('AlarmClock does not call the callback in the past', |
| (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| alarm.datetime = clock.ago(minutes: 1); |
| |
| // No timers scheduled for past dates. |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| expect(callCount, 0); |
| }); |
| |
| testAsync('AlarmClock reschedules to a future time', (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| |
| expect(callCount, 0); |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 0); |
| |
| // Reschedule. |
| alarm.datetime = alarm.datetime.add(const Duration(minutes: 1)); |
| |
| fakeAsync.elapse(const Duration(minutes: 1)); |
| |
| // Still no calls because we rescheduled. |
| expect(callCount, 0); |
| |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| }); |
| |
| testAsync('AlarmClock reschedules to an earlier time', (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| |
| expect(callCount, 0); |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 0); |
| |
| // Reschedule to an earlier time that's still in the future. |
| alarm.datetime = alarm.datetime.subtract(const Duration(seconds: 15)); |
| |
| fakeAsync.elapse(const Duration(seconds: 45)); |
| expect(callCount, 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| }); |
| |
| testAsync('AlarmClock cancels the timer when datetime is null', |
| (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| |
| // Cancel. |
| alarm.datetime = null; |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| expect(callCount, 0); |
| |
| // Make sure nothing fires even if we wait long enough. |
| fakeAsync.elapse(const Duration(minutes: 2)); |
| expect(callCount, 0); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| }); |
| |
| testAsync('AlarmClock cancels the timer when datetime is in the past', |
| (FakeAsync fakeAsync) { |
| final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24)); |
| final AlarmClock alarm = AlarmClock(clock.now); |
| alarm.callback = testCallback; |
| |
| alarm.datetime = clock.fromNow(minutes: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| fakeAsync.elapse(const Duration(seconds: 30)); |
| expect(callCount, 0); |
| expect(fakeAsync.nonPeriodicTimerCount, 1); |
| |
| // Cancel. |
| alarm.datetime = clock.ago(seconds: 1); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| expect(callCount, 0); |
| |
| // Make sure nothing fires even if we wait long enough. |
| fakeAsync.elapse(const Duration(minutes: 2)); |
| expect(callCount, 0); |
| expect(fakeAsync.nonPeriodicTimerCount, 0); |
| }); |
| } |
| |
| typedef FakeAsyncTest = void Function(FakeAsync); |
| |
| void testAsync(String description, FakeAsyncTest fn) { |
| test(description, () { |
| FakeAsync().run(fn); |
| }); |
| } |