import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/misc.dart' show Override; import 'package:flutter_test/flutter_test.dart'; import 'package:go_router/go_router.dart'; import 'package:sharedinbox/core/models/account.dart'; import 'package:sharedinbox/di.dart'; import 'package:sharedinbox/ui/screens/compose_screen.dart'; import 'helpers.dart'; void main() { group('ComposeScreen', () { testWidgets('renders To, Cc, Subject and Body fields', (tester) async { await tester.pumpWidget( buildApp( initialLocation: '/compose', overrides: [ accountRepositoryProvider.overrideWithValue( FakeAccountRepository([kTestAccount]), ), mailboxRepositoryProvider.overrideWithValue( FakeMailboxRepository(), ), emailRepositoryProvider.overrideWithValue(FakeEmailRepository()), draftRepositoryProvider.overrideWithValue(FakeDraftRepository()), ], ), ); await tester.pumpAndSettle(); expect(find.text('To'), findsOneWidget); expect(find.text('Cc'), findsOneWidget); expect(find.text('Subject'), findsOneWidget); expect(find.text('Body'), findsOneWidget); }); testWidgets('prefills To and Subject when provided as constructor params', ( tester, ) async { await tester.pumpWidget( _buildDirect( screen: const ComposeScreen( prefillTo: 'bob@example.com', prefillSubject: 'Re: Hello', ), overrides: [ accountRepositoryProvider.overrideWithValue( FakeAccountRepository([kTestAccount]), ), mailboxRepositoryProvider.overrideWithValue( FakeMailboxRepository(), ), emailRepositoryProvider.overrideWithValue(FakeEmailRepository()), draftRepositoryProvider.overrideWithValue(FakeDraftRepository()), ], ), ); await tester.pumpAndSettle(); expect( find.widgetWithText(TextFormField, 'bob@example.com'), findsOneWidget, ); expect(find.widgetWithText(TextFormField, 'Re: Hello'), findsOneWidget); }); testWidgets('shows static From field when one account is loaded', ( tester, ) async { await tester.pumpWidget( buildApp( initialLocation: '/compose', overrides: [ accountRepositoryProvider.overrideWithValue( FakeAccountRepository([kTestAccount]), ), mailboxRepositoryProvider.overrideWithValue( FakeMailboxRepository(), ), emailRepositoryProvider.overrideWithValue(FakeEmailRepository()), draftRepositoryProvider.overrideWithValue(FakeDraftRepository()), ], ), ); await tester.pumpAndSettle(); expect(find.text('Alice '), findsOneWidget); }); testWidgets('shows From dropdown when multiple accounts are loaded', ( tester, ) async { const second = Account( id: 'acc-2', displayName: 'Bob', email: 'bob@example.com', imapHost: 'imap.example.com', smtpHost: 'smtp.example.com', ); await tester.pumpWidget( buildApp( initialLocation: '/compose', overrides: [ accountRepositoryProvider.overrideWithValue( FakeAccountRepository([kTestAccount, second]), ), mailboxRepositoryProvider.overrideWithValue( FakeMailboxRepository(), ), emailRepositoryProvider.overrideWithValue(FakeEmailRepository()), draftRepositoryProvider.overrideWithValue(FakeDraftRepository()), ], ), ); await tester.pumpAndSettle(); expect(find.byType(DropdownButtonFormField), findsOneWidget); }); testWidgets('restores saved draft when no prefill is provided', ( tester, ) async { final fakeDrafts = FakeDraftRepository(); await fakeDrafts.saveDraft( toText: 'carol@example.com', ccText: '', subjectText: 'Restored subject', bodyText: 'Draft body', ); await tester.pumpWidget( _buildDirect( screen: const ComposeScreen(), overrides: [ accountRepositoryProvider.overrideWithValue( FakeAccountRepository([kTestAccount]), ), mailboxRepositoryProvider.overrideWithValue( FakeMailboxRepository(), ), emailRepositoryProvider.overrideWithValue(FakeEmailRepository()), draftRepositoryProvider.overrideWithValue(fakeDrafts), ], ), ); await tester.pumpAndSettle(); expect( find.widgetWithText(TextFormField, 'carol@example.com'), findsOneWidget, ); expect( find.widgetWithText(TextFormField, 'Restored subject'), findsOneWidget, ); }); }); } /// Builds [screen] inside a minimal GoRouter so [context.pop()] works, without /// going through [buildApp]'s full route tree. Widget _buildDirect({ required Widget screen, required List overrides, }) { final router = GoRouter( initialLocation: '/', routes: [GoRoute(path: '/', builder: (ctx, state) => screen)], ); return ProviderScope( overrides: overrides, child: MaterialApp.router( routerConfig: router, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo), useMaterial3: true, ), ), ); }