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_')); }); }