// 功能描述:验证作业前检查页面失败重试不会向 setState 返回异步任务。 // 版本:1.0.0 import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:service_app/app/dependencies.dart'; import 'package:service_app/data/repositories/service_repository.dart'; import 'package:service_app/data/services/api_client.dart'; import 'package:service_app/data/services/location_service.dart'; import 'package:service_app/data/services/secure_session_store.dart'; import 'package:service_app/domain/models/service_models.dart'; import 'package:service_app/ui/features/preflight/preflight_page.dart'; /// 提供无需平台插件的空会话存储。 class _EmptySessionStore implements SessionStore { @override Future delete(String key) async {} @override Future read(String key) async => null; @override Future write(String key, String value) async {} } /// 提供不会在重试测试中访问系统定位的占位实现。 class _UnusedLocationService implements LocationService { @override Future current() => throw UnimplementedError(); } /// 首次加载失败、第二次成功,用于验证真实重试路径。 class _FailOnceRepository extends ServiceRepository { _FailOnceRepository() : super( ApiClient(() => '', baseUrl: 'https://api.example.com'), _UnusedLocationService(), ); int calls = 0; @override Future preflight() async { calls += 1; if (calls == 1) throw StateError('temporary failure'); return const PreflightResult( roleCode: 'delivery', workStatus: 'off_duty', canWork: false, checks: {}, ); } } /// 返回包含一个真实阻断项和一个暂不检查项的固定预检结果。 class _BlockedRepository extends ServiceRepository { _BlockedRepository() : super( ApiClient(() => '', baseUrl: 'https://api.example.com'), _UnusedLocationService(), ); @override Future preflight() async => const PreflightResult( roleCode: 'delivery', workStatus: 'on_duty', canWork: false, checks: { 'credential': {'status': 'blocked', 'reason': 'missing'}, 'daily_training': {'status': 'not_configured'}, }, ); } /// 点击重新加载后应成功刷新,且测试过程不得出现 Flutter 断言。 void main() { testWidgets('作业检查失败后可重新加载', (tester) async { final repository = _FailOnceRepository(); final session = StaffSession(_EmptySessionStore()); await tester.pumpWidget( MaterialApp( home: PreflightPage(session: session, repository: repository), ), ); await tester.pumpAndSettle(); expect(find.text('作业检查加载失败'), findsOneWidget); expect(repository.calls, 1); await tester.tap(find.text('重新加载')); await tester.pumpAndSettle(); expect(find.text('作业检查加载失败'), findsNothing); expect(find.text('仍有前置条件未完成'), findsOneWidget); expect(repository.calls, 2); expect(tester.takeException(), isNull); }); testWidgets('仅统计阻断项并显示资质处理指引', (tester) async { await tester.pumpWidget( MaterialApp( home: PreflightPage( session: StaffSession(_EmptySessionStore()), repository: _BlockedRepository(), ), ), ); await tester.pumpAndSettle(); expect(find.text('完成 1 项阻断后可进入'), findsOneWidget); expect(find.text('暂不检查'), findsOneWidget); expect(find.text('尚未配置有效资质,请联系所属组织管理员补充或审核'), findsOneWidget); expect(find.text('下班打卡'), findsOneWidget); }); }