testsAndMisc-archive/pomodoro_app/test/screens/pomodoro_screen_test.dart

208 lines
5.5 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pomodoro_app/models/pomodoro_state.dart';
import 'package:pomodoro_app/screens/pomodoro_screen.dart';
import 'package:pomodoro_app/services/pomodoro_timer.dart';
/// Controllable fake timer for widget tests.
class FakeTimerController {
void Function(Timer)? _callback;
bool _isActive = true;
void tick() {
if (_isActive) {
_callback?.call(_FakeTimer(this));
}
}
void cancel() {
_isActive = false;
}
bool get isActive => _isActive;
}
class _FakeTimer implements Timer {
_FakeTimer(this._controller);
final FakeTimerController _controller;
@override
void cancel() => _controller.cancel();
@override
bool get isActive => _controller.isActive;
@override
int get tick => 0;
}
void main() {
late PomodoroTimer timer;
late FakeTimerController fakeController;
Timer fakeTimerFactory(Duration duration, void Function(Timer) callback) {
fakeController = FakeTimerController();
fakeController._callback = callback;
return _FakeTimer(fakeController);
}
setUp(() {
timer = PomodoroTimer(
workMinutes: 1,
shortBreakMinutes: 1,
longBreakMinutes: 2,
pomodorosPerCycle: 4,
timerFactory: fakeTimerFactory,
);
});
tearDown(() {
timer.dispose();
});
Widget createApp() {
return MaterialApp(
home: PomodoroScreen(timer: timer),
);
}
group('PomodoroScreen', () {
testWidgets('shows initial time', (tester) async {
await tester.pumpWidget(createApp());
expect(find.text('01:00'), findsOneWidget);
});
testWidgets('shows Work label initially', (tester) async {
await tester.pumpWidget(createApp());
expect(find.text('Work'), findsOneWidget);
});
testWidgets('shows 0 pomodoros completed', (tester) async {
await tester.pumpWidget(createApp());
expect(find.text('0 pomodoros completed'), findsOneWidget);
});
testWidgets('play button starts timer', (tester) async {
await tester.pumpWidget(createApp());
// Find and tap the play button.
final playButton = find.byIcon(Icons.play_arrow);
expect(playButton, findsOneWidget);
await tester.tap(playButton);
await tester.pump();
// After ticking, time should decrease.
fakeController.tick();
await tester.pump();
expect(find.text('00:59'), findsOneWidget);
});
testWidgets('pause button appears when running', (tester) async {
await tester.pumpWidget(createApp());
await tester.tap(find.byIcon(Icons.play_arrow));
await tester.pump();
expect(find.byIcon(Icons.pause), findsOneWidget);
});
testWidgets('pause button pauses timer', (tester) async {
await tester.pumpWidget(createApp());
// Start.
await tester.tap(find.byIcon(Icons.play_arrow));
await tester.pump();
fakeController.tick();
await tester.pump();
// Pause.
await tester.tap(find.byIcon(Icons.pause));
await tester.pump();
expect(find.text('00:59'), findsOneWidget);
expect(find.byIcon(Icons.play_arrow), findsOneWidget);
});
testWidgets('reset button resets time', (tester) async {
await tester.pumpWidget(createApp());
// Start and tick.
await tester.tap(find.byIcon(Icons.play_arrow));
await tester.pump();
fakeController.tick();
fakeController.tick();
await tester.pump();
// Reset.
await tester.tap(find.byIcon(Icons.refresh));
await tester.pump();
expect(find.text('01:00'), findsOneWidget);
});
testWidgets('skip button moves to next mode', (tester) async {
await tester.pumpWidget(createApp());
await tester.tap(find.byIcon(Icons.skip_next));
await tester.pump();
expect(find.text('Short Break'), findsOneWidget);
});
testWidgets('shows correct completed count after session', (tester) async {
await tester.pumpWidget(createApp());
// Start and complete a work session.
await tester.tap(find.byIcon(Icons.play_arrow));
await tester.pump();
for (var i = 0; i < 60; i++) {
fakeController.tick();
}
await tester.pump();
expect(find.text('1 pomodoro completed'), findsOneWidget);
});
testWidgets('has 4 indicator dots', (tester) async {
await tester.pumpWidget(createApp());
// There should be 4 AnimatedContainers for indicators.
// We can check that the PomodoroIndicators widget is present.
expect(find.text('0 pomodoros completed'), findsOneWidget);
});
testWidgets('shows style picker with Pomodoro selected', (tester) async {
await tester.pumpWidget(createApp());
expect(find.text('Pomodoro'), findsOneWidget);
expect(find.text('Ultraradian'), findsOneWidget);
});
testWidgets('switching to ultraradian updates timer', (tester) async {
await tester.pumpWidget(createApp());
await tester.tap(find.text('Ultraradian'));
await tester.pump();
// Ultraradian work session is 90 minutes.
expect(find.text('90:00'), findsOneWidget);
expect(timer.timerStyle, TimerStyle.ultraradian);
});
testWidgets('switching back to pomodoro resets timer', (tester) async {
await tester.pumpWidget(createApp());
await tester.tap(find.text('Ultraradian'));
await tester.pump();
expect(find.text('90:00'), findsOneWidget);
await tester.tap(find.text('Pomodoro'));
await tester.pump();
expect(find.text('25:00'), findsOneWidget);
});
});
}