Created
February 21, 2019 12:14
-
-
Save brianegan/1717304f836f837014e89f0658b9501c to your computer and use it in GitHub Desktop.
Now uses `tester.binding.clock`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_test/flutter_test.dart'; | |
import 'package:quiver/async.dart'; | |
import 'package:quiver/testing/time.dart'; | |
void main() { | |
group('CounterTimer', () { | |
testWidgets('counts down from 10 to 0', (WidgetTester tester) async { | |
// Create a Timer | |
final timer = CountdownTimer( | |
Duration(seconds: 10), | |
Duration(milliseconds: 100), | |
stopwatch: FakeStopwatch( | |
// The function will simply return our fake "Now" time. | |
() => tester.binding.clock.now().microsecondsSinceEpoch, | |
Duration(seconds: 1).inMicroseconds, | |
), | |
); | |
// Create the Widget we'll rebuild over time | |
final widget = Directionality( | |
textDirection: TextDirection.ltr, | |
child: CountdownTimerRunner(countdownTimer: timer), | |
); | |
// Build the Widget the first time and make sure it shows the right thing | |
await tester.pumpWidget(widget); | |
expect(find.text('10'), findsOneWidget); | |
// Wait 10 seconds to make sure the Widget is at 0 | |
await tester.pumpWidget(widget, Duration(seconds: 10)); | |
expect(find.text('0'), findsOneWidget); | |
// Important: Cancel the Timer, or this test will throw an error that | |
// there are active async calls in progress! | |
timer.cancel(); | |
}); | |
}); | |
} | |
class CountdownTimerWidget extends StatefulWidget { | |
@override | |
_CountdownTimerWidgetState createState() => _CountdownTimerWidgetState(); | |
} | |
class _CountdownTimerWidgetState extends State<CountdownTimerWidget> { | |
CountdownTimer _countdownTimer; | |
@override | |
void dispose() { | |
_countdownTimer?.cancel(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
if (_countdownTimer == null) { | |
return CountdownTimerInitializer( | |
Duration.zero, | |
onDurationSelected: (Duration duration) { | |
setState(() { | |
_countdownTimer = | |
CountdownTimer(duration, Duration(milliseconds: 250)); | |
}); | |
}, | |
); | |
} | |
return CountdownTimerRunner( | |
countdownTimer: _countdownTimer, | |
); | |
} | |
} | |
typedef void OnDurationSelected(Duration duration); | |
class CountdownTimerInitializer extends StatefulWidget { | |
final Duration initialDuration; | |
final OnDurationSelected onDurationSelected; | |
CountdownTimerInitializer(this.initialDuration, | |
{@required this.onDurationSelected, Key key}) | |
: super(key: key); | |
@override | |
CountdownTimerInitializerState createState() { | |
return new CountdownTimerInitializerState(initialDuration); | |
} | |
} | |
class CountdownTimerInitializerState extends State<CountdownTimerInitializer> { | |
Duration _duration; | |
CountdownTimerInitializerState([Duration initialDuration = Duration.zero]) | |
: _duration = initialDuration; | |
void _increment() { | |
setState(() { | |
_duration = _duration + Duration(seconds: 1); | |
}); | |
} | |
void _decrement() { | |
setState(() { | |
var updatedDuration = _duration - Duration(seconds: 1); | |
if (updatedDuration <= Duration.zero) { | |
updatedDuration = Duration.zero; | |
} | |
_duration = updatedDuration; | |
}); | |
} | |
bool get _isValid { | |
return _duration > Duration.zero; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: <Widget>[ | |
Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Text( | |
_duration.inSeconds.toString(), | |
style: Theme.of(context).textTheme.display1, | |
key: ValueKey("configure-duration-text"), | |
), | |
), | |
Row( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
RaisedButton( | |
key: ValueKey("configure-decrement"), | |
onPressed: _isValid ? _decrement : null, | |
child: Text("-"), | |
), | |
RaisedButton( | |
key: ValueKey("configure-increment"), | |
onPressed: _increment, | |
child: Text("+"), | |
), | |
], | |
), | |
RaisedButton( | |
key: ValueKey("configure-start"), | |
onPressed: | |
_isValid ? () => widget.onDurationSelected(_duration) : null, | |
child: Text("Start"), | |
) | |
], | |
); | |
} | |
} | |
class CountdownTimerRunner extends StatelessWidget { | |
final CountdownTimer countdownTimer; | |
const CountdownTimerRunner({Key key, @required this.countdownTimer}) | |
: super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: <Widget>[ | |
StreamBuilder<CountdownTimer>( | |
initialData: countdownTimer, | |
stream: countdownTimer, | |
builder: (context, snapshot) { | |
if (snapshot.hasData) { | |
return Text( | |
countdownTimer.remaining.inSeconds.toString(), | |
key: ValueKey("runner-duration-text"), | |
); | |
} else { | |
return Container(); | |
} | |
}, | |
), | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment