Integrate themed login/signup, EN/RU localization, shared dummy providers, verification recovery screens and named URL routes. Store frontend guidelines, workflow skills, validation and delivery documentation. Related to #2, #3, #5 and #6.
105 lines
3.4 KiB
Dart
105 lines
3.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_test/flutter_test.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 = <Completer<AuthResult>>[];
|
|
LoginRequest? request;
|
|
@override
|
|
Future<AuthResult> login(LoginRequest input) {
|
|
request = input;
|
|
final completer = Completer<AuthResult>();
|
|
calls.add(completer);
|
|
return completer.future;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
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<FilledButton>(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);
|
|
});
|
|
}
|