新增:pet 域埋点强类型封装(06 号规划字典 v2 三事件)

- pet_create_started / succeeded / failed 三事件(13 号规范 §3.1
  强类型惯例:枚举编译期锁死,业务代码禁止手拼事件名与属性)
- entryPoint 三枚举(post_register_guide 预留);failureReason 四枚举
  (pet_limit_reached 因产品未设上限未纳入;5xx 与断网/超时客户端
  不可区分,并入 network_error)
- errorCode 携带业务码并推导 httpStatus(code ~/ 100);attemptSeq
  记录表单会话内提交序号
- 单元测试 4 个(属性齐备、可空属性缺席语义)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 11:59:32 +08:00
parent 3179528c57
commit c0a8a56e91
2 changed files with 148 additions and 0 deletions
@@ -0,0 +1,65 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:patbond_flutter/features/pets/pet_analytics.dart';
import 'package:patbond_flutter/features/pets/pet_models.dart';
void main() {
late List<(String, Map<String, dynamic>?)> events;
late PetAnalytics analytics;
setUp(() {
events = [];
analytics = PetAnalytics(
(name, [props]) async => events.add((name, props)),
);
});
test('pet_create_startedentryPoint 枚举值上报', () {
analytics.createStarted(entryPoint: PetCreateEntryPoint.profileEmptyState);
expect(events.single.$1, 'pet_create_started');
expect(events.single.$2, {'entryPoint': 'profile_empty_state'});
});
test('pet_create_succeededdurationMs/species/petIndex 三属性齐备', () {
analytics.createSucceeded(
durationMs: 1234,
species: PetSpecies.cat,
petIndex: 2,
);
expect(events.single.$1, 'pet_create_succeeded');
expect(events.single.$2, {
'durationMs': 1234,
'species': 'cat',
'petIndex': 2,
});
});
test('pet_create_failed:业务码携带 errorCode 并推导 httpStatus', () {
analytics.createFailed(
reason: PetCreateFailureReason.validationError,
attemptSeq: 2,
errorCode: 40903,
);
expect(events.single.$1, 'pet_create_failed');
expect(events.single.$2, {
'failureReason': 'validation_error',
'attemptSeq': 2,
'errorCode': 40903,
'httpStatus': 409,
});
});
test('pet_create_failed:本地校验/网络失败无 errorCode 时两可空属性缺席', () {
analytics.createFailed(
reason: PetCreateFailureReason.networkError,
attemptSeq: 1,
);
expect(events.single.$2, {
'failureReason': 'network_error',
'attemptSeq': 1,
});
});
}