import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:country_picker/country_picker.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sxchnge_theme/sxchnge_theme.dart'; import 'package:sxchnge_app/kyc/country.dart'; import 'package:sxchnge_app/generated/i18n/app_localizations.dart'; void main() { final search = find.byKey(const ValueKey('country-search')); final button = find.byType(OutlinedButton); Future mount( WidgetTester tester, ValueNotifier value, { Locale locale = const Locale('en'), bool enabled = true, }) async { await tester.pumpWidget( MaterialApp( theme: SxchngeTheme.light(), locale: locale, localizationsDelegates: const [ ...AppLocalizations.localizationsDelegates, CountryLocalizations.delegate, ], supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( body: Padding( padding: const EdgeInsets.all(24), child: ValueListenableBuilder( valueListenable: value, builder: (_, code, _) => CountryField( value: code, enabled: enabled, onChanged: (code) => value.value = code, ), ), ), ), ), ); await tester.pumpAndSettle(); } Future open(WidgetTester tester) async { await tester.tap(button); await tester.pumpAndSettle(); } testWidgets( 'name search stores code, reselection and cancel preserve value', (tester) async { final value = ValueNotifier(''); addTearDown(value.dispose); await mount(tester, value); expect(find.text('Select a country'), findsOneWidget); await open(tester); await tester.enterText(search, 'polAND'); await tester.pumpAndSettle(); await tester.tap(find.text('Poland')); await tester.pumpAndSettle(); expect(value.value, 'PL'); expect(find.text('Poland'), findsOneWidget); expect(find.text('0/2'), findsNothing); await open(tester); await tester.enterText(search, ' de '); await tester.pumpAndSettle(); await tester.tap(find.text('Germany')); await tester.pumpAndSettle(); expect(value.value, 'DE'); expect(find.text('Germany'), findsOneWidget); await open(tester); await tester.enterText(search, 'poland'); await tester.pumpAndSettle(); await tester.tap(find.byType(BackButton)); await tester.pumpAndSettle(); expect(value.value, 'DE'); expect(find.text('Germany'), findsOneWidget); }, ); testWidgets('no-results state recovers through clear and Escape cancels', ( tester, ) async { final value = ValueNotifier('PL'); addTearDown(value.dispose); await mount(tester, value); await open(tester); await tester.enterText(search, 'no-such-country'); await tester.pumpAndSettle(); expect(find.textContaining('No countries found'), findsOneWidget); expect(find.byType(ListTile), findsNothing); expect(value.value, 'PL'); await tester.tap(find.byTooltip('Clear search')); await tester.pumpAndSettle(); expect(find.textContaining('No countries found'), findsNothing); expect(find.byType(ListTile), findsWidgets); await tester.sendKeyEvent(LogicalKeyboardKey.escape); await tester.pumpAndSettle(); expect(search, findsNothing); expect(value.value, 'PL'); }); testWidgets('saved code follows locale and Russian names are searchable', ( tester, ) async { final value = ValueNotifier('PL'); addTearDown(value.dispose); await mount(tester, value); expect(find.text('Poland'), findsOneWidget); await mount(tester, value, locale: const Locale('ru')); expect(find.text('Польша'), findsOneWidget); expect(value.value, 'PL'); await open(tester); await tester.enterText(search, 'Германия'); await tester.pumpAndSettle(); await tester.tap(find.byType(ListTile)); await tester.pumpAndSettle(); expect(value.value, 'DE'); expect(find.text('Германия'), findsOneWidget); }); testWidgets('busy field cannot open or change selection', (tester) async { final value = ValueNotifier('PL'); addTearDown(value.dispose); await mount(tester, value, enabled: false); expect(tester.widget(button).onPressed, isNull); await tester.tap(button); await tester.pumpAndSettle(); expect(search, findsNothing); expect(value.value, 'PL'); }); testWidgets( 'keyboard and labeled touch targets work at 320px with large text', (tester) async { tester.view.physicalSize = const Size(320, 900); tester.view.devicePixelRatio = 1; tester.platformDispatcher.textScaleFactorTestValue = 1.6; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); addTearDown(tester.platformDispatcher.clearTextScaleFactorTestValue); final semantics = tester.ensureSemantics(); final value = ValueNotifier('GS'); addTearDown(value.dispose); await mount(tester, value); expect(tester, meetsGuideline(labeledTapTargetGuideline)); expect(tester, meetsGuideline(androidTapTargetGuideline)); await tester.sendKeyEvent(LogicalKeyboardKey.tab); await tester.sendKeyEvent(LogicalKeyboardKey.enter); await tester.pumpAndSettle(); expect(search, findsOneWidget); await tester.enterText(search, 'GS'); await tester.pumpAndSettle(); expect(tester.widget(find.byType(ListTile)).selected, isTrue); expect(tester, meetsGuideline(labeledTapTargetGuideline)); expect(tester, meetsGuideline(androidTapTargetGuideline)); await tester.sendKeyEvent(LogicalKeyboardKey.tab); await tester.sendKeyEvent(LogicalKeyboardKey.tab); await tester.sendKeyEvent(LogicalKeyboardKey.enter); await tester.pumpAndSettle(); expect(search, findsNothing); expect(value.value, 'GS'); expect(tester.takeException(), isNull); semantics.dispose(); }, ); }