import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:miler/data/accepted_store.dart'; /// Deleting a mock generator does not reach the rows it already wrote. /// /// Every store in `accepted_store.dart` is SharedPreferences, so a phone that /// once ran a build with the demo layer still carries those bookings — and /// Bookings merges the accepted store into its list while Activity reads the /// completed and skipped ones. That is why demo stops kept appearing on exactly /// those two tabs with nothing left in the repo to explain them. /// /// The risk in fixing it is the obvious one: a blanket wipe would take the /// rider's real accepted work with it. So these tests are mostly about what /// must *survive*. void main() { TestWidgetsFlutterBinding.ensureInitialized(); Map booking(String id, {String? pickupId}) => { 'orderid': id, if (pickupId != null) 'pickupid': pickupId, 'pickupcustomer': 'Customer $id', 'orderstatus': 'accepted', }; test('drops the demo bookings and keeps the real ones', () async { SharedPreferences.setMockInitialValues({}); await debugSeedStore( 'mock_accepted_bookings', jsonEncode([ booking('MOCK-Q-1001', pickupId: 'del-mock-q-1001'), booking('884213'), booking('MOCK-B-3004'), ]), ); expect(await purgeDemoRecords(), 2); final left = await getAcceptedBookings(); expect(left.map((b) => b['orderid']), ['884213']); }); test('matches on the pickup id too', () async { // `getMockQueues` wrote ids like `del-mock-q-1001` on the pickup field // while the order id looked ordinary in some rows. SharedPreferences.setMockInitialValues({}); await debugSeedStore( 'completed_bookings', jsonEncode([ booking('7001', pickupId: 'del-mock-d-2003'), booking('7002', pickupId: 'del-77aa'), ]), ); expect(await purgeDemoRecords(), 1); // Read the raw store, not [getCompletedBookings]: that reader also drops // anything not stamped today, which would empty this list for a reason // that has nothing to do with the purge. final prefs = await SharedPreferences.getInstance(); final left = (jsonDecode(prefs.getString(await debugStoreKey('completed_bookings'))!) as List) .map((e) => (e as Map)['orderid']) .toList(); expect(left, ['7002']); }); test('clears the id-only stores as well', () async { SharedPreferences.setMockInitialValues({}); await debugSeedStore('mock_rejected_order_ids', ['MOCK-Q-1005', '99120']); await debugSeedStore('collected_order_ids', ['MOCK-B-3001', '77451']); await debugSeedStore('not_loaded_orders', ['DEMO-2', '31009']); expect(await purgeDemoRecords(), 3); expect(await getRejectedOrderIds(), {'99120'}); expect(await getCollectedOrderIds(), {'77451'}); expect(await getNotLoadedOrderIds(), {'31009'}); }); test('a real order id is never mistaken for a demo one', () async { // The ids a backend actually issues. None of these may be touched — losing // a genuine accepted booking is a rider driving to a door with no record of // why, which is far worse than a leftover demo row. final real = [ booking('884213'), booking('ORD-2026-000412'), booking('DM-99120', pickupId: 'del-77aa'), booking('mockingbird-77'), // contains "mock", does not start with it ]; SharedPreferences.setMockInitialValues({}); await debugSeedStore('mock_accepted_bookings', jsonEncode(real)); expect(await purgeDemoRecords(), 0); expect((await getAcceptedBookings()).length, real.length); }); test('an untouched install is a no-op', () async { SharedPreferences.setMockInitialValues({}); expect(await purgeDemoRecords(), 0); }); }