import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:go_router/go_router.dart'; import 'package:sxchnge_auth/sxchnge_auth.dart'; import 'package:sxchnge_app/main.dart'; import 'package:sxchnge_app/providers/locale.dart'; class ControlledLogin implements LoginService { final calls = >[]; LoginRequest? request; @override Future login(LoginRequest input) { request = input; final completer = Completer(); calls.add(completer); return completer.future; } } class UnverifiedBackend extends BackendAuthServices { UnverifiedBackend() : super(baseUri: Uri.parse('https://api.example/api/v1'), clientId: 'web'); int sends = 0; @override Future login(LoginRequest request) async => throw const AuthException(AuthError.accountNotVerified); @override Future send({ required String email, required String locale, }) async { sends++; return const VerificationResult(isSimulated: false); } } void main() { testWidgets('backend mode gates workspace and recovers unverified login', ( tester, ) async { tester.view.physicalSize = const Size(1440, 1200); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); final backend = UnverifiedBackend(); await tester.pumpWidget(SxchngeApp(backend: backend)); await tester.pumpAndSettle(); final router = GoRouter.of( tester.element(find.byKey(const ValueKey('email'))), ); router.go('/accounts'); await tester.pumpAndSettle(); expect(router.routeInformationProvider.value.uri.path, '/'); await tester.enterText( find.byKey(const ValueKey('email')), 'user@example.com', ); await tester.enterText( find.byKey(const ValueKey('password')), 'password-value', ); await tester.ensureVisible(find.byKey(const ValueKey('submit'))); await tester.tap(find.byKey(const ValueKey('submit'))); await tester.pumpAndSettle(); expect( router.routeInformationProvider.value.uri.path, '/verification-sent', ); expect(backend.sends, 1); expect( find.textContaining('a verification email is on its way'), findsOneWidget, ); expect(tester.takeException(), isNull); }); testWidgets( 'app shows loading, localized failure, and retries through injected service', (tester) async { tester.view.physicalSize = const Size(1440, 1200); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); final service = ControlledLogin(); await tester.pumpWidget( SxchngeApp( loginService: service, localeProvider: LocaleProvider(initialLocale: const Locale('ru')), ), ); await tester.pumpAndSettle(); await tester.enterText( find.byKey(const ValueKey('email')), 'a@example.com', ); await tester.enterText( find.byKey(const ValueKey('password')), 'example-password', ); final button = find.byKey(const ValueKey('submit')); await tester.ensureVisible(button); await tester.tap(button); await tester.pump(); expect(tester.widget(button).onPressed, isNull); expect(find.text('Подождите…'), findsOneWidget); expect(service.request!.locale, 'ru'); service.calls.single.completeError( const AuthException(AuthError.unavailable), ); await tester.pumpAndSettle(); expect( find.text('Сервис недоступен. Попробуйте ещё раз.'), findsOneWidget, ); await tester.tap(button); await tester.pump(); expect(service.calls, hasLength(2)); service.calls.last.complete( const AuthResult(userId: 'demo', isSimulated: true), ); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('preview-result')), findsOneWidget); expect(find.byKey(const ValueKey('auth-error')), findsNothing); expect(tester.takeException(), isNull); }, ); testWidgets('changing mode while loading ignores the old login result', ( tester, ) async { final service = ControlledLogin(); await tester.pumpWidget(SxchngeApp(loginService: service)); await tester.pumpAndSettle(); await tester.enterText( find.byKey(const ValueKey('email')), 'a@example.com', ); await tester.enterText( find.byKey(const ValueKey('password')), 'example-password', ); await tester.ensureVisible(find.byKey(const ValueKey('submit'))); await tester.tap(find.byKey(const ValueKey('submit'))); await tester.pump(); await tester.ensureVisible(find.text('Sign up')); await tester.tap(find.text('Sign up')); await tester.pumpAndSettle(); service.calls.single.complete( const AuthResult(userId: 'demo', isSimulated: true), ); await tester.pumpAndSettle(); expect(find.byKey(const ValueKey('confirmation')), findsOneWidget); expect(find.byKey(const ValueKey('preview-result')), findsNothing); expect(tester.takeException(), isNull); }); }