feat(flutter): 修复登录输入并升级登录页

This commit is contained in:
Zhou Weidong committed 2026-10-20 16:21:06 +08:00
1 parent f72cb41670
commit 81bb1543bb
5 files changed
+233 -141

No files matched your search

+94 -17
View File
@@ -13,6 +13,7 @@ import 'package:fruitshorts/core/data/services/auth_controller.dart';
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
import 'package:fruitshorts/core/platform/haptics.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/theme/app_theme.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/auth/auth_view.dart';
@@ -30,6 +31,7 @@ void main() {
AuthApi? api,
FakeHaptics? haptics,
bool openEmail = true,
bool asRoute = false,
}) async {
final auth = AuthController(
api ??
@@ -53,11 +55,15 @@ void main() {
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const AuthPage(),
home: asRoute ? const _AuthRouteHost() : const AuthPage(),
),
),
);
await tester.pump(const Duration(milliseconds: 220));
if (asRoute) {
await tester.tap(find.byKey(const Key('auth-open')));
await tester.pumpAndSettle();
}
if (openEmail) {
await tester.ensureVisible(find.byKey(const Key('auth-entry-email')));
await tester.tap(find.byKey(const Key('auth-entry-email')));
@@ -78,21 +84,46 @@ void main() {
);
expect(
tester.getSize(find.byKey(const Key('auth-brand-logo'))),
const Size(64, 64),
const Size(72, 72),
);
expect(find.byKey(const Key('auth-entry-google')), findsNothing);
expect(find.byKey(const Key('auth-entry-phone')), findsOneWidget);
expect(find.byKey(const Key('auth-entry-email')), findsOneWidget);
expect(find.byKey(const Key('auth-legal')), findsOneWidget);
expect(
tester.getSize(find.byKey(const Key('auth-entry-phone'))).height,
50,
);
expect(
tester.getSize(find.byKey(const Key('auth-entry-email'))).height,
50,
);
final phoneButton = tester.widget<Material>(
find.descendant(
of: find.byKey(const Key('auth-entry-phone')),
matching: find.byType(Material),
),
);
expect(phoneButton.color, AppColors.blue);
final emailButton = tester.widget<Material>(
find.descendant(
of: find.byKey(const Key('auth-entry-email')),
matching: find.byType(Material),
),
);
expect(emailButton.color, AppColors.card);
expect(
(emailButton.shape! as RoundedRectangleBorder).side.color,
AppColors.border,
);
final glow = tester.widget<Container>(
find.byKey(const Key('auth-background-glow')),
);
final glowDecoration = glow.decoration! as BoxDecoration;
final gradient = glowDecoration.gradient! as LinearGradient;
for (final color in gradient.colors) {
expect(color.a, lessThanOrEqualTo(0.18));
}
final gradient = glowDecoration.gradient! as RadialGradient;
expect(gradient.colors.first, AppColors.surfaceTop);
expect(gradient.colors.last.a, 0);
await tester.tap(find.byKey(const Key('auth-entry-email')));
await tester.pumpAndSettle();
@@ -101,19 +132,28 @@ void main() {
final cardDecoration = card.decoration! as BoxDecoration;
expect(cardDecoration.color, AppColors.card);
expect(cardDecoration.borderRadius, BorderRadius.circular(20));
expect(
(cardDecoration.border! as Border).top.color,
AppColors.outlineVariantDark,
);
expect((cardDecoration.border! as Border).top.width, 1);
expect(cardDecoration.boxShadow, contains(AppTheme.cardShadow));
expect(card.padding, const EdgeInsets.all(20));
final email = tester.widget<TextField>(
find.byKey(const Key('auth-email')),
);
expect(email.decoration?.fillColor, AppColors.bar);
expect(email.decoration?.fillColor, AppColors.card);
expect(email.style?.color, AppColors.onSurface);
expect(email.style?.fontSize, 15);
expect(email.cursorColor, AppColors.blue);
expect(tester.getSize(find.byKey(const Key('auth-email'))).height, 52);
final emailBorder = email.decoration!.border! as OutlineInputBorder;
final emailBorder =
email.decoration!.enabledBorder! as OutlineInputBorder;
expect(emailBorder.borderRadius, BorderRadius.circular(14));
expect(emailBorder.borderSide.color, AppColors.border);
expect(emailBorder.borderSide.width, 1);
final password = tester.widget<TextField>(
find.byKey(const Key('auth-password')),
);
expect(password.style?.color, AppColors.onSurface);
expect(password.style?.fontSize, 15);
expect(password.cursorColor, AppColors.blue);
final submit = tester.widget<FilledButton>(
find.byKey(const Key('auth-submit')),
@@ -123,11 +163,11 @@ void main() {
submit.style!.backgroundColor!.resolve(const {WidgetState.pressed}),
AppColors.bluePressed,
);
expect(tester.getSize(find.byKey(const Key('auth-submit'))).height, 52);
expect(tester.getSize(find.byKey(const Key('auth-submit'))).height, 50);
expect(
(submit.style!.shape!.resolve(const {})! as RoundedRectangleBorder)
.borderRadius,
BorderRadius.circular(26),
BorderRadius.circular(25),
);
expect(find.text('Sign In'), findsWidgets);
@@ -139,6 +179,23 @@ void main() {
},
);
testWidgets('should_render_40px_back_button_when_page_is_pushed', (
tester,
) async {
await pumpAuthPage(tester, openEmail: false, asRoute: true);
final back = find.byKey(const Key('auth-back'));
expect(tester.getSize(back), const Size(40, 40));
expect(
tester
.widget<Material>(
find.descendant(of: back, matching: find.byType(Material)),
)
.color,
AppColors.card,
);
});
testWidgets('should_fade_and_slide_content_in_within_220ms', (tester) async {
await pumpAuthPage(tester);
@@ -198,10 +255,10 @@ void main() {
final focusedBorder =
email.decoration!.focusedBorder! as OutlineInputBorder;
expect(focusedBorder.borderSide.color, AppColors.blue);
expect(focusedBorder.borderSide.width, 1.5);
expect(focusedBorder.borderSide.width, 1);
expect(
tester.widget<Icon>(find.byIcon(Icons.mail_outline_rounded)).color,
AppColors.blueSoft,
AppColors.blue,
);
await tester.tap(find.byKey(const Key('auth-password-visibility')));
@@ -280,6 +337,7 @@ void main() {
final error = tester.widget<Text>(errorFinder);
final scheme = Theme.of(tester.element(errorFinder)).colorScheme;
expect(error.style?.color, scheme.error);
expect(error.style?.fontSize, 12);
expect(
find.descendant(
of: capsuleFinder,
@@ -325,3 +383,22 @@ class _PendingAuthApi extends AuthApi {
throw const ApiException(500, 'pending failure');
}
}
class _AuthRouteHost extends StatelessWidget {
const _AuthRouteHost();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
key: const Key('auth-open'),
onPressed: () => Navigator.of(
context,
).push<void>(MaterialPageRoute(builder: (_) => const AuthPage())),
child: const Text('Open auth'),
),
),
);
}
}