import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:relationship_saver/core/auth/in_memory_token_store.dart'; import 'package:relationship_saver/features/local/storage/local_data_store_in_memory.dart'; import 'package:relationship_saver/features/local/storage/local_data_store_provider.dart'; import 'package:relationship_saver/features/sync/storage/sync_state_store_in_memory.dart'; import 'package:relationship_saver/features/sync/storage/sync_state_store_provider.dart'; import 'package:relationship_saver/features/sync/sync_queue_repository.dart'; import 'package:relationship_saver/integrations/backend/backend_gateway_fake.dart'; import 'package:relationship_saver/integrations/backend/backend_gateway_provider.dart'; import 'package:relationship_saver/integrations/backend/models/backend_models.dart'; import 'package:relationship_saver/main.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { setUp(() { SharedPreferences.setMockInitialValues({}); }); testWidgets('mobile flow adds person and queues a sync change', ( WidgetTester tester, ) async { await tester.binding.setSurfaceSize(const Size(390, 844)); addTearDown(() => tester.binding.setSurfaceSize(null)); final ProviderContainer container = ProviderContainer( overrides: [ tokenStoreProvider.overrideWithValue(InMemoryTokenStore()), backendGatewayProvider.overrideWithValue(BackendGatewayFake()), localDataStoreProvider.overrideWithValue(InMemoryLocalDataStore()), syncStateStoreProvider.overrideWithValue(InMemorySyncStateStore()), ], ); addTearDown(container.dispose); await tester.pumpWidget( UncontrolledProviderScope( container: container, child: const RelationshipSaverApp(), ), ); await tester.pumpAndSettle(); expect(find.text('Sign in to continue'), findsOneWidget); await tester.tap(find.widgetWithText(FilledButton, 'Sign In')); await tester.pumpAndSettle(const Duration(milliseconds: 500)); expect(find.text('Dashboard'), findsWidgets); await tester.tap(find.text('People').last); await tester.pumpAndSettle(const Duration(milliseconds: 500)); expect(find.text('People'), findsWidgets); await tester.tap(find.widgetWithText(FilledButton, 'Add person')); await tester.pumpAndSettle(const Duration(milliseconds: 300)); expect(find.text('Add Person'), findsOneWidget); await tester.enterText( find.widgetWithText(TextField, 'Name'), 'Taylor Quinn', ); await tester.enterText( find.widgetWithText(TextField, 'Relationship'), 'Partner', ); await tester.enterText( find.widgetWithText(TextField, 'Tags (comma separated)'), 'tea, books', ); await tester.enterText( find.widgetWithText(TextField, 'Notes'), 'Prefers calm evenings and handmade gifts.', ); await tester.tap(find.widgetWithText(FilledButton, 'Save')); await tester.pumpAndSettle(const Duration(milliseconds: 500)); expect(find.text('Taylor Quinn'), findsWidgets); final syncState = await container.read(syncQueueRepositoryProvider.future); expect(syncState.pendingChanges.isNotEmpty, isTrue); expect( syncState.pendingChanges.any((ChangeEnvelope change) { return change.entityType == 'person' && change.op == ChangeOperation.upsert && change.payload?['name'] == 'Taylor Quinn'; }), isTrue, ); await tester.tap(find.byTooltip('More')); await tester.pumpAndSettle(const Duration(milliseconds: 250)); await tester.tap(find.text('Sync').last); await tester.pumpAndSettle(const Duration(milliseconds: 500)); expect(find.text('Queue Status'), findsOneWidget); expect(find.text('Pending changes'), findsOneWidget); }); }