import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sxchnge_app/main.dart'; import 'package:sxchnge_app/providers/locale.dart'; Finder field(String key) => find.byKey(ValueKey(key)); EditableTextState editor(WidgetTester tester, String key) => tester.state( find.descendant(of: field(key), matching: find.byType(EditableText)), ); void main() { for (final language in ['en', 'ru']) { testWidgets( 'platform autofill fills the signup credential group ($language)', (tester) async { tester.view.physicalSize = const Size(1440, 1200); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); await tester.pumpWidget( SxchngeApp( localeProvider: LocaleProvider(initialLocale: Locale(language)), ), ); await tester.pumpAndSettle(); await tester.tap( find.text(language == 'ru' ? 'Регистрация' : 'Sign up'), ); await tester.pumpAndSettle(); await tester.showKeyboard(field('email')); final configuration = tester.testTextInput.setClientArgs!; expect( configuration['inputType']['name'], 'TextInputType.emailAddress', ); final fields = (configuration['fields'] as List).cast(); expect(fields, hasLength(4)); expect( fields.map((field) => field['autofill']['hints'].first), containsAll(['name', 'username', 'newPassword', 'newPassword']), ); const values = { 'name': 'Alex Example', 'email': 'alex@example.com', 'password': 'generated-example-password', 'confirmation': 'generated-example-password', }; await tester.binding.defaultBinaryMessenger.handlePlatformMessage( SystemChannels.textInput.name, SystemChannels.textInput.codec.encodeMethodCall( MethodCall('TextInputClient.updateEditingStateWithTag', [ 0, { for (final entry in values.entries) editor(tester, entry.key).autofillId: TextEditingValue( text: entry.value, ).toJSON(), }, ]), ), (_) {}, ); await tester.pumpAndSettle(); for (final entry in values.entries) { expect( editor(tester, entry.key).currentTextEditingValue.text, entry.value, ); } // A visibility change must retain both the supplied value and its role. await tester.tap( find.byTooltip( language == 'ru' ? 'Показать пароль' : 'Show password', ), ); await tester.pump(); expect(editor(tester, 'password').widget.obscureText, isFalse); expect(editor(tester, 'password').widget.autofillHints, [ 'newPassword', ]); expect( editor(tester, 'password').currentTextEditingValue.text, values['password'], ); await tester.tap(find.text(language == 'ru' ? 'Войти' : 'Log in')); await tester.pumpAndSettle(); await tester.showKeyboard(field('email')); final loginFields = (tester.testTextInput.setClientArgs!['fields'] as List).cast(); expect(loginFields, hasLength(2)); expect(loginFields.map((field) => field['autofill']['hints'].first), [ 'username', 'password', ]); expect( editor(tester, 'password').currentTextEditingValue.text, isEmpty, ); expect( tester.testTextInput.log, contains( isMethodCall('TextInput.finishAutofillContext', arguments: false), ), ); expect( tester.testTextInput.log, isNot( contains( isMethodCall('TextInput.finishAutofillContext', arguments: true), ), ), ); }, ); } testWidgets('leaving an unfinished auth form cancels saving', (tester) async { await tester.pumpWidget(const SxchngeApp()); await tester.pumpAndSettle(); await tester.enterText(field('email'), 'alex@example.com'); await tester.enterText(field('password'), 'unfinished-password'); tester.testTextInput.log.clear(); await tester.pumpWidget(const SizedBox.shrink()); await tester.pumpAndSettle(); expect( tester.testTextInput.log, contains( isMethodCall('TextInput.finishAutofillContext', arguments: false), ), ); expect( tester.testTextInput.log, isNot( contains( isMethodCall('TextInput.finishAutofillContext', arguments: true), ), ), ); }); }