113 lines
4.4 KiB
Dart
113 lines
4.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:drift/native.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:motorcycle_dash/database/database.dart' hide TelemetrySample;
|
|
import 'package:motorcycle_dash/features/performance/performance_timer_service.dart';
|
|
import 'package:motorcycle_dash/models/telemetry_sample.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
late AppDatabase db;
|
|
late StreamController<TelemetrySample> controller;
|
|
PerformanceTimerService? timer;
|
|
|
|
setUp(() {
|
|
db = AppDatabase.forTesting(NativeDatabase.memory());
|
|
controller = StreamController<TelemetrySample>.broadcast();
|
|
});
|
|
|
|
tearDown(() async {
|
|
timer?.dispose();
|
|
await controller.close();
|
|
await db.close();
|
|
});
|
|
|
|
Future<void> completeZeroToSixty(DateTime base) async {
|
|
controller.add(TelemetrySample(timestamp: base, speed: 0.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 200)), speed: 5.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 1800)), speed: 45.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 2800)), speed: 62.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
|
}
|
|
|
|
test('performance run completed during active ride stores that ride ID', () async {
|
|
final rideId = await db.startRide(startTime: DateTime.utc(2026, 9, 3, 12));
|
|
timer = PerformanceTimerService(
|
|
db,
|
|
controller.stream,
|
|
activeRideIdReader: () => rideId,
|
|
);
|
|
|
|
timer!.setTarget(PerformanceTarget.sixty);
|
|
await completeZeroToSixty(DateTime.utc(2026, 9, 3, 12, 1));
|
|
|
|
final runs = await db.select(db.performanceRuns).get();
|
|
expect(runs, hasLength(1));
|
|
expect(runs.single.rideId, rideId);
|
|
});
|
|
|
|
test('ride-specific performance query returns associated run after ride completion', () async {
|
|
final rideId = await db.startRide(startTime: DateTime.utc(2026, 9, 3, 13));
|
|
timer = PerformanceTimerService(
|
|
db,
|
|
controller.stream,
|
|
activeRideIdReader: () => rideId,
|
|
);
|
|
|
|
timer!.setTarget(PerformanceTarget.sixty);
|
|
await completeZeroToSixty(DateTime.utc(2026, 9, 3, 13, 1));
|
|
await db.endRide(rideId, const RidesCompanion());
|
|
|
|
final rideRuns = await (db.select(db.performanceRuns)..where((p) => p.rideId.equals(rideId))).get();
|
|
expect(rideRuns, hasLength(1));
|
|
expect(rideRuns.single.type, '0-60');
|
|
expect(rideRuns.single.rideId, rideId);
|
|
});
|
|
|
|
test('standalone performance run remains valid without ride ID', () async {
|
|
timer = PerformanceTimerService(db, controller.stream);
|
|
|
|
timer!.setTarget(PerformanceTarget.sixty);
|
|
await completeZeroToSixty(DateTime.utc(2026, 9, 3, 14));
|
|
|
|
final runs = await db.select(db.performanceRuns).get();
|
|
expect(runs, hasLength(1));
|
|
expect(runs.single.rideId, isNull);
|
|
});
|
|
|
|
test('attempt that starts on ride A is not reassigned to ride B before save', () async {
|
|
final rideA = await db.startRide(startTime: DateTime.utc(2026, 9, 3, 15));
|
|
final rideB = await db.startRide(startTime: DateTime.utc(2026, 9, 3, 16));
|
|
var activeRideId = rideA;
|
|
timer = PerformanceTimerService(
|
|
db,
|
|
controller.stream,
|
|
activeRideIdReader: () => activeRideId,
|
|
);
|
|
|
|
final base = DateTime.utc(2026, 9, 3, 15, 1);
|
|
timer!.setTarget(PerformanceTarget.sixty);
|
|
controller.add(TelemetrySample(timestamp: base, speed: 0.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 200)), speed: 5.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
|
|
activeRideId = rideB;
|
|
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 1800)), speed: 45.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
controller.add(TelemetrySample(timestamp: base.add(const Duration(milliseconds: 2800)), speed: 62.0));
|
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
|
|
|
final rideARuns = await (db.select(db.performanceRuns)..where((p) => p.rideId.equals(rideA))).get();
|
|
final rideBRuns = await (db.select(db.performanceRuns)..where((p) => p.rideId.equals(rideB))).get();
|
|
expect(rideARuns, hasLength(1));
|
|
expect(rideBRuns, isEmpty);
|
|
});
|
|
}
|