// 功能描述:设置确认操作、附属读取失败降级与登录密码表单回归;版本:1.0.0。 import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:user_app/app/dependencies.dart'; import 'package:user_app/data/services/api_client.dart'; import 'package:user_app/data/services/app_settings_service.dart'; import 'package:user_app/data/services/secure_session_store.dart'; import 'package:user_app/domain/models/client_models.dart'; import 'package:user_app/ui/core/app_theme.dart'; import 'package:user_app/ui/features/settings/settings_page.dart'; import 'package:user_app/ui/features/settings/login_password_page.dart'; import '../support/a1_fixture.dart'; class SettingsSession extends UserSession { SettingsSession() : super(SecureSessionStore()); int logouts = 0; @override Future logout() async { logouts++; } } class SettingsFixture extends A1FixtureRepository { bool failProfile = false, failPassword = true; int changes = 0; String? receivedCurrent, receivedNext; @override Future profile() async { if (failProfile) throw const ApiException(500, '资料暂时不可用'); return super.profile(); } @override Future changeLoginPassword(String currentPassword, String newPassword) async { changes++; receivedCurrent = currentPassword; receivedNext = newPassword; if (failPassword) throw const ApiException(1305, '当前密码错误'); } } class SettingsServiceFixture extends AppSettingsService { int clears = 0; @override Future version() async => '1.0.0 (1)'; @override int get imageCacheBytes => clears == 0 ? 1048576 : 0; @override void clearImageCache() { clears++; } } void main() { testWidgets('资料读取失败仍可清图片缓存,取消不清除,退出需确认', (tester) async { tester.view.physicalSize = const Size(390, 844); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); final repo = SettingsFixture()..failProfile = true; final session = SettingsSession(), service = SettingsServiceFixture(); await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: SettingsPage(repository: repo, session: session, service: service), ), ); await tester.pumpAndSettle(); expect(find.text('读取失败,点击重试'), findsOneWidget); await tester.scrollUntilVisible(find.text('清除缓存'), 300); await tester.pumpAndSettle(); await tester.tap(find.text('清除缓存')); await tester.pumpAndSettle(); await tester.tap(find.text('取消')); await tester.pumpAndSettle(); expect(service.clears, 0); await tester.tap(find.text('清除缓存')); await tester.pumpAndSettle(); await tester.tap(find.text('确认')); await tester.pumpAndSettle(); expect(service.clears, 1); expect(find.text('0.0MB 图片缓存'), findsOneWidget); await tester.scrollUntilVisible(find.text('退出登录'), 300); await tester.pumpAndSettle(); await tester.tap(find.text('退出登录')); await tester.pumpAndSettle(); await tester.tap(find.text('取消')); await tester.pumpAndSettle(); expect(session.logouts, 0); await tester.tap(find.text('退出登录')); await tester.pumpAndSettle(); await tester.tap(find.text('确认')); await tester.pumpAndSettle(); expect(session.logouts, 1); }); testWidgets('密码校验阻止错误提交,服务端失败保留输入,成功才退出', (tester) async { final repo = SettingsFixture(), session = SettingsSession(); await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: LoginPasswordPage(repository: repo, session: session), ), ); await tester.tap(find.text('确认修改并重新登录')); await tester.pumpAndSettle(); expect(repo.changes, 0); await tester.enterText(find.byKey(const ValueKey('password-0')), 'old-test-password'); await tester.enterText(find.byKey(const ValueKey('password-1')), 'new-test-password'); await tester.enterText(find.byKey(const ValueKey('password-2')), 'mismatch'); await tester.tap(find.text('确认修改并重新登录')); await tester.pumpAndSettle(); expect(find.text('两次新密码不一致'), findsOneWidget); expect(repo.changes, 0); await tester.enterText(find.byKey(const ValueKey('password-2')), 'new-test-password'); await tester.tap(find.text('确认修改并重新登录')); await tester.pumpAndSettle(); expect(find.text('当前密码错误'), findsOneWidget); expect(session.logouts, 0); expect( tester.widget(find.byKey(const ValueKey('password-1'))).controller!.text, 'new-test-password', ); repo.failPassword = false; await tester.tap(find.text('确认修改并重新登录')); await tester.pumpAndSettle(); expect(repo.changes, 2); expect(session.logouts, 1); expect(repo.receivedCurrent, 'old-test-password'); expect(repo.receivedNext, 'new-test-password'); expect( tester.widget(find.byKey(const ValueKey('password-1'))).controller!.text, '', ); }); }