Shuffle/app/lib/features/auth/presentation/auth_failure_texts.dart
cschlaefke 57305dad4b fix(auth): address review findings for login
Fixed-wording tests for the generic credentials error, redacted toString for
login/register state, shared AuthFailure.isRetryable, autofill context
finished even when the router removes the screen, stricter from validation
(encoded and control-character variants), more widget tests.

Refs #1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 09:07:56 +01:00

43 lines
1.8 KiB
Dart

import 'package:shuffle/core/l10n/l10n.dart';
import 'package:shuffle/features/auth/domain/auth_failure.dart';
/// User-facing text of an [AuthFailure] (Spec #1 § 4.4, texts from
/// `docs/design/auth-screens.md`).
///
/// `emailSendLimited` has no text of its own: screens treat it as success
/// (F12) or convert it to `rateLimited` beforehand.
String authFailureMessage(AppLocalizations l10n, AuthFailure failure) =>
switch (failure) {
InvalidCredentials() => l10n.authErrorInvalidCredentials,
EmailNotConfirmed() => l10n.authErrorEmailNotConfirmed,
EmailSendLimited() || RateLimited() => l10n.authErrorRateLimited,
WeakPassword(:final reasons) => weakPasswordMessage(l10n, reasons),
SamePassword() => l10n.authErrorSamePassword,
LinkInvalidOrExpired() => l10n.authErrorLinkInvalidOrExpired,
InvalidEmail() => l10n.authErrorEmailInvalid,
RegistrationRejected() => l10n.authErrorRegistrationRejected,
NetworkFailure() => l10n.authErrorNetwork,
Unexpected() => l10n.authErrorUnexpected,
};
/// One sentence per distinct reason; an empty list gets the generic text.
String weakPasswordMessage(
AppLocalizations l10n,
List<WeakPasswordReason> reasons,
) {
final texts = <String>{
for (final reason in reasons)
switch (reason) {
WeakPasswordReason.length => l10n.authErrorWeakPasswordLength,
WeakPasswordReason.pwned => l10n.authErrorWeakPasswordPwned,
WeakPasswordReason.characters ||
WeakPasswordReason.unknown => l10n.authErrorWeakPasswordCharacters,
},
};
return texts.isEmpty ? l10n.authErrorWeakPasswordCharacters : texts.join(' ');
}
/// Failures the user can fix by simply trying again (offline, unexpected).
extension AuthFailureRetry on AuthFailure {
bool get isRetryable => this is NetworkFailure || this is Unexpected;
}