Connect sign-up to Sendico Facts intake (#46)
This commit is contained in:
1 parent
30f0455122
commit
a584c8189a
40 files changed
+1616
-35
No files matched your search
@@ -22,6 +22,7 @@ class AuthFeedback extends StatelessWidget {
|
||||
AuthError.accountNotVerified => l.authVerifyEmail,
|
||||
AuthError.invalidCredentials => l.authInvalidCredentials,
|
||||
AuthError.emailInUse => l.authEmailInUse,
|
||||
AuthError.signupNeedsAssistance => l.authSignupNeedsAssistance,
|
||||
AuthError.unavailable => l.authUnavailable,
|
||||
AuthError.unexpected => l.authUnexpected,
|
||||
AuthError.factorLocked => l.factorLocked,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
"authSignupNeedsAssistance": "We could not finish setting up your account. Please contact support.",
|
||||
"appTitle": "SXCHNGE · Your next move",
|
||||
"nextChapter": "YOUR NEXT CHAPTER",
|
||||
"loginHeading": "Hey, welcome\nback.",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"@@locale": "ru",
|
||||
"authSignupNeedsAssistance": "Не удалось завершить создание аккаунта. Обратитесь в службу поддержки.",
|
||||
"appTitle": "SXCHNGE · Ваш следующий шаг",
|
||||
"nextChapter": "НОВАЯ ГЛАВА",
|
||||
"loginHeading": "Рады видеть\nвас снова.",
|
||||
|
||||
@@ -122,8 +122,10 @@ class _VerificationPageState extends State<VerificationPage> {
|
||||
(_provider.service as SimulationInfo).isSimulated) ||
|
||||
state.isSimulated;
|
||||
final sent = status == VerificationStatus.sent;
|
||||
final needsAssistance = state.error == VerificationError.needsAssistance;
|
||||
final retryConfirmation =
|
||||
status == VerificationStatus.error &&
|
||||
!needsAssistance &&
|
||||
!_lastWasSend &&
|
||||
widget.token != null;
|
||||
final title = switch (status) {
|
||||
@@ -139,14 +141,16 @@ class _VerificationPageState extends State<VerificationPage> {
|
||||
? l.verificationChecking
|
||||
: l.verificationRequest,
|
||||
};
|
||||
final body = switch (status) {
|
||||
VerificationStatus.sent => l.verificationSent,
|
||||
VerificationStatus.verified => l.verificationVerifiedBody,
|
||||
VerificationStatus.expired => l.verificationExpiredBody,
|
||||
VerificationStatus.invalid => l.verificationInvalidBody,
|
||||
VerificationStatus.error => l.verificationInternalBody,
|
||||
_ => null,
|
||||
};
|
||||
final body = needsAssistance
|
||||
? l.authSignupNeedsAssistance
|
||||
: switch (status) {
|
||||
VerificationStatus.sent => l.verificationSent,
|
||||
VerificationStatus.verified => l.verificationVerifiedBody,
|
||||
VerificationStatus.expired => l.verificationExpiredBody,
|
||||
VerificationStatus.invalid => l.verificationInvalidBody,
|
||||
VerificationStatus.error => l.verificationInternalBody,
|
||||
_ => null,
|
||||
};
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:sxchnge_analytics/sxchnge_analytics.dart';
|
||||
|
||||
import 'package:sxchnge_auth/sxchnge_auth.dart';
|
||||
|
||||
import 'package:sxchnge_app/main.dart';
|
||||
@@ -41,6 +43,84 @@ class UnverifiedBackend extends BackendAuthServices {
|
||||
}
|
||||
|
||||
void main() {
|
||||
for (final language in ['en', 'ru']) {
|
||||
testWidgets(
|
||||
'signup requiring assistance preserves input and records failure ($language)',
|
||||
(tester) async {
|
||||
tester.view.physicalSize = const Size(390, 844);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
tester.platformDispatcher.textScaleFactorTestValue = 1.5;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
addTearDown(tester.platformDispatcher.clearTextScaleFactorTestValue);
|
||||
final analytics = DummyAnalyticsService();
|
||||
final locale = LocaleProvider(initialLocale: Locale(language));
|
||||
await tester.pumpWidget(
|
||||
SxchngeApp(
|
||||
localeProvider: locale,
|
||||
analyticsService: analytics,
|
||||
signupService: const DummySignupService(
|
||||
delay: Duration.zero,
|
||||
failure: AuthError.signupNeedsAssistance,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
final signupLabel = language == 'ru' ? 'Регистрация' : 'Sign up';
|
||||
await tester.ensureVisible(find.text(signupLabel));
|
||||
await tester.tap(find.text(signupLabel));
|
||||
await tester.pumpAndSettle();
|
||||
for (final entry in {
|
||||
'name': 'Ada Lovelace',
|
||||
'email': 'ada@example.com',
|
||||
'password': 'password preserved',
|
||||
'confirmation': 'password preserved',
|
||||
}.entries) {
|
||||
await tester.enterText(find.byKey(ValueKey(entry.key)), entry.value);
|
||||
}
|
||||
await tester.ensureVisible(find.byKey(const ValueKey('submit')));
|
||||
await tester.tap(find.byKey(const ValueKey('submit')));
|
||||
await tester.pumpAndSettle();
|
||||
final feedback = find.byKey(const ValueKey('auth-error'));
|
||||
await tester.ensureVisible(feedback);
|
||||
expect(
|
||||
find.text(
|
||||
language == 'ru'
|
||||
? 'Не удалось завершить создание аккаунта. Обратитесь в службу поддержки.'
|
||||
: 'We could not finish setting up your account. Please contact support.',
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byKey(const ValueKey('verification-sent')), findsNothing);
|
||||
expect(
|
||||
tester
|
||||
.widget<TextFormField>(find.byKey(const ValueKey('email')))
|
||||
.controller!
|
||||
.text,
|
||||
'ada@example.com',
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<TextFormField>(find.byKey(const ValueKey('password')))
|
||||
.controller!
|
||||
.text,
|
||||
'password preserved',
|
||||
);
|
||||
expect(
|
||||
analytics.events.where((event) => event.name == 'auth_signup_failed'),
|
||||
hasLength(1),
|
||||
);
|
||||
expect(
|
||||
analytics.events.where(
|
||||
(event) => event.name == 'auth_signup_succeeded',
|
||||
),
|
||||
isEmpty,
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('backend mode gates workspace and recovers unverified login', (
|
||||
tester,
|
||||
) async {
|
||||
|
||||
@@ -42,6 +42,37 @@ Future<void> openVerification(
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('resend assistance retains email and does not claim delivery', (
|
||||
tester,
|
||||
) async {
|
||||
await openVerification(
|
||||
tester,
|
||||
'/verification-sent',
|
||||
service: const DummyVerificationService(
|
||||
delay: Duration.zero,
|
||||
sendFailure: VerificationError.needsAssistance,
|
||||
),
|
||||
);
|
||||
final email = find.byKey(const ValueKey('verification-email'));
|
||||
await tester.enterText(email, 'ada@example.com');
|
||||
await tester.ensureVisible(
|
||||
find.byKey(const ValueKey('verification-resend')),
|
||||
);
|
||||
await tester.tap(find.byKey(const ValueKey('verification-resend')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.text(
|
||||
'We could not finish setting up your account. Please contact support.',
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byKey(const ValueKey('verification-sent')), findsNothing);
|
||||
expect(
|
||||
tester.widget<TextFormField>(email).controller!.text,
|
||||
'ada@example.com',
|
||||
);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
for (final scenario in {
|
||||
'demo-valid': 'verified',
|
||||
'demo-expired': 'expired',
|
||||
|
||||
Reference in new issue
Block a user