Files
platforms/apps/service_app/test/ui/preflight_page_test.dart
2026-09-05 20:17:07 +08:00

115 lines
3.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 功能描述:验证作业前检查页面失败重试不会向 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<void> delete(String key) async {}
@override
Future<String?> read(String key) async => null;
@override
Future<void> write(String key, String value) async {}
}
/// 提供不会在重试测试中访问系统定位的占位实现。
class _UnusedLocationService implements LocationService {
@override
Future<LocationPoint> current() => throw UnimplementedError();
}
/// 首次加载失败、第二次成功,用于验证真实重试路径。
class _FailOnceRepository extends ServiceRepository {
_FailOnceRepository()
: super(
ApiClient(() => '', baseUrl: 'https://api.example.com'),
_UnusedLocationService(),
);
int calls = 0;
@override
Future<PreflightResult> 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<PreflightResult> 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);
});
}