|  | // 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); | 
|  | }); | 
|  | } |