MotorSignal-App/test/cloud_ride_identity_migrati...

123 lines
4.6 KiB
Dart

import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:motorcycle_dash/database/database.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('new rides receive a persisted cloudRideId independent of local id', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
addTearDown(db.close);
final localId = await db.startRide();
final cloudId = await db.getCloudRideId(localId);
expect(cloudId, isNotNull);
expect(cloudId, startsWith('ride_'));
expect(cloudId, isNot(localId.toString()));
final secondLocalId = await db.startRide();
final secondCloudId = await db.getCloudRideId(secondLocalId);
expect(secondCloudId, isNot(cloudId));
// Re-reading the same local row returns the exact persisted identity.
expect(await db.getCloudRideId(localId), cloudId);
});
test('ensureCloudRideId is idempotent', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
addTearDown(db.close);
final localId = await db.startRide();
final first = await db.ensureCloudRideId(localId);
final second = await db.ensureCloudRideId(localId);
expect(second, first);
});
test('real v5 rides migrate to their legacy MotorCloud identity', () async {
final connection = NativeDatabase.memory(setup: (rawDb) {
rawDb.execute('''
CREATE TABLE rides (
id INTEGER PRIMARY KEY AUTOINCREMENT,
start_time INTEGER NOT NULL,
end_time INTEGER,
distance_miles REAL NOT NULL DEFAULT 0.0,
top_speed_mph REAL NOT NULL DEFAULT 0.0,
max_lean_left REAL NOT NULL DEFAULT 0.0,
max_lean_right REAL NOT NULL DEFAULT 0.0,
max_accel_g REAL NOT NULL DEFAULT 0.0,
max_braking_g REAL NOT NULL DEFAULT 0.0,
best0to60_ms REAL,
best0to100_ms REAL,
distance REAL NOT NULL DEFAULT 0.0,
moving_time INTEGER NOT NULL DEFAULT 0,
stopped_time INTEGER NOT NULL DEFAULT 0,
average_speed REAL NOT NULL DEFAULT 0.0,
top_speed REAL NOT NULL DEFAULT 0.0,
elevation_gain REAL NOT NULL DEFAULT 0.0,
elevation_loss REAL NOT NULL DEFAULT 0.0,
motorcycle_id INTEGER,
motorcycle_year INTEGER,
motorcycle_make TEXT,
motorcycle_model TEXT,
motorcycle_variant TEXT
)
''');
final start = DateTime.utc(2026, 8, 31, 21, 7, 5);
rawDb.execute('INSERT INTO rides (id, start_time) VALUES (?, ?)', [42, start.millisecondsSinceEpoch]);
rawDb.execute('PRAGMA user_version = 5');
});
final db = AppDatabase.forTesting(connection);
addTearDown(db.close);
final migrated = await db.getCloudRideId(42);
expect(migrated, 'ride_42_20260831_210705');
final rows = await db.customSelect('PRAGMA table_info(rides)').get();
expect(rows.any((row) => row.data['name'] == 'cloud_ride_id'), isTrue);
final indexes = await db.customSelect('PRAGMA index_list(rides)').get();
expect(indexes.any((row) => row.data['name'] == 'rides_cloud_ride_id_idx'), isTrue);
});
test('fresh database creation creates cloud identity column and unique index', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
addTearDown(db.close);
final columns = await db.customSelect('PRAGMA table_info(rides)').get();
expect(columns.any((row) => row.data['name'] == 'cloud_ride_id'), isTrue);
final indexes = await db.customSelect('PRAGMA index_list(rides)').get();
expect(indexes.any((row) => row.data['name'] == 'rides_cloud_ride_id_idx'), isTrue);
final rideId = await db.startRide();
expect(await db.getCloudRideId(rideId), startsWith('ride_'));
});
test('a restored ride keeps its cloud identity even when its local ID changes', () async {
const cloudId = 'ride_9f4d8a3e2b1c7d6e5f4a3b2c1d0e9f8a';
final original = AppDatabase.forTesting(NativeDatabase.memory());
final restored = AppDatabase.forTesting(NativeDatabase.memory());
addTearDown(original.close);
addTearDown(restored.close);
final originalId = await original.startRide();
await original.customStatement(
'UPDATE rides SET cloud_ride_id = ? WHERE id = ?',
[cloudId, originalId],
);
expect(await original.getCloudRideId(originalId), cloudId);
final restoredId = await restored.startRide();
await restored.customStatement(
'UPDATE rides SET cloud_ride_id = ? WHERE id = ?',
[cloudId, restoredId],
);
expect(restoredId, isNot(originalId));
expect(await restored.getCloudRideId(restoredId), cloudId);
});
}