ba503327f5
CI / flutter-gates (push) Successful in 2m12s
- 照护提醒页:status 过滤(服务端白名单视图)、due_at ASC、逾期红标 双通道标识,四态齐备;创建表单(四类)+ 完成(completedAt 必带、 支持补记)/ 忽略(禁带 completedAt)流转,42202/40902 兜底重拉 - 档案页:「健康提醒」卡改真实待办数据驱动(取代 demo 硬编码文案, 最近到期一条 + 逾期警示形态),照护提醒导航入口带待办数副行 - 疫苗列表(25 号报告遗留①②):scheduled 行「标记完成/取消登记」 PATCH 流转;完成对话框补录厂商/批号(契约可选字段); 42201/40902/40402 兜底 - 埋点:create 三事件 + viewed(recordType=reminder)挂通; edit_succeeded/failed 挂 vaccine 流转(failureReason 含 conflict); 提醒完成/忽略按 06 §7 缺口 3 既定取舍不埋 - 测试 250 → 272 全绿(+22,较基线 +48);analyze 0 问题;format 无 diff Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
128 lines
4.0 KiB
Dart
128 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:patbond_flutter/core/network/api_exception.dart';
|
|
import 'package:patbond_flutter/core/theme/app_theme.dart';
|
|
import 'package:patbond_flutter/features/pets/care_reminder_form_page.dart';
|
|
import 'package:patbond_flutter/features/pets/health_record_analytics.dart';
|
|
import 'package:patbond_flutter/features/pets/pet_exceptions.dart';
|
|
import 'package:patbond_flutter/features/pets/pet_models.dart';
|
|
|
|
import '../../helpers/pet_test_helpers.dart';
|
|
|
|
void main() {
|
|
late FakePetsRepository repository;
|
|
late List<(String, Map<String, dynamic>?)> events;
|
|
late HealthRecordAnalytics analytics;
|
|
|
|
setUp(() {
|
|
repository = FakePetsRepository();
|
|
events = [];
|
|
analytics = HealthRecordAnalytics(
|
|
(name, [props]) async => events.add((name, props)),
|
|
);
|
|
});
|
|
|
|
List<Map<String, dynamic>?> eventsOf(String name) => [
|
|
for (final e in events)
|
|
if (e.$1 == name) e.$2,
|
|
];
|
|
|
|
Future<void> pumpForm(WidgetTester tester) async {
|
|
tester.view.physicalSize = const Size(700, 1600);
|
|
tester.view.devicePixelRatio = 1.0;
|
|
addTearDown(tester.view.reset);
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: buildAppTheme(),
|
|
home: Builder(
|
|
builder: (context) => Scaffold(
|
|
body: Center(
|
|
child: TextButton(
|
|
onPressed: () => Navigator.of(context).push(
|
|
MaterialPageRoute<CareReminder>(
|
|
builder: (_) => CareReminderFormPage(
|
|
repository: repository,
|
|
petId: 'p-1',
|
|
analytics: analytics,
|
|
),
|
|
),
|
|
),
|
|
child: const Text('打开表单'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await tester.tap(find.text('打开表单'));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
Future<void> fillValid(WidgetTester tester) async {
|
|
await tester.tap(find.text('用药'));
|
|
await tester.pump();
|
|
await tester.enterText(
|
|
find.widgetWithText(TextFormField, '提醒内容(如:体内外驱虫)'),
|
|
'心丝虫预防药',
|
|
);
|
|
await tester.tap(find.text('到期日期'));
|
|
await tester.pumpAndSettle();
|
|
await tester.tap(find.text('OK'));
|
|
await tester.pumpAndSettle();
|
|
}
|
|
|
|
testWidgets('started 去重:首次输入一次;四类类型可选', (tester) async {
|
|
await pumpForm(tester);
|
|
await fillValid(tester);
|
|
await tester.enterText(
|
|
find.widgetWithText(TextFormField, '提醒内容(如:体内外驱虫)'),
|
|
'改个名字',
|
|
);
|
|
await tester.pump();
|
|
|
|
final started = eventsOf('health_record_create_started');
|
|
expect(started.single, {
|
|
'recordType': 'reminder',
|
|
'entryPoint': 'record_list',
|
|
});
|
|
// 四类类型齐备。
|
|
for (final label in ['驱虫', '体检', '用药', '其他']) {
|
|
expect(find.text(label), findsOneWidget);
|
|
}
|
|
});
|
|
|
|
testWidgets('40300 横幅 / 网络 SnackBar 兜底 + 失败事件', (tester) async {
|
|
var attempt = 0;
|
|
repository.createCareReminderHandler = (petId, request) async {
|
|
attempt++;
|
|
if (attempt == 1) {
|
|
throw const PetAccessDeniedException(message: '无权限');
|
|
}
|
|
throw const ApiNetworkException('断网');
|
|
};
|
|
|
|
await pumpForm(tester);
|
|
await fillValid(tester);
|
|
|
|
await tester.tap(find.text('保存提醒'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('你没有权限为该宠物添加提醒'), findsOneWidget);
|
|
|
|
await tester.tap(find.text('保存提醒'));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('网络异常,请检查网络后重试'), findsOneWidget);
|
|
|
|
final failed = eventsOf('health_record_create_failed');
|
|
expect(failed.length, 2);
|
|
expect(failed[0], {
|
|
'recordType': 'reminder',
|
|
'failureReason': 'permission_denied',
|
|
'attemptSeq': 1,
|
|
'errorCode': 40300,
|
|
'httpStatus': 403,
|
|
});
|
|
expect(failed[1]!['failureReason'], 'network_error');
|
|
expect(failed[1]!['attemptSeq'], 2);
|
|
});
|
|
}
|