Initial commit: 91dj android client dev_1.0.0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-10-08 11:37:25 +07:00
co-authored by Claude Opus 5.5
commit 97dd6a739a
1262 changed files with 119813 additions and 0 deletions
@@ -0,0 +1,189 @@
import 'package:analytics_sdk/manager/ad_impression_manager.dart';
import 'package:analytics_sdk/manager/session_manager.dart';
import 'package:flutter_test/flutter_test.dart';
/// SessionManager 回归测试
///
/// 覆盖 Bug 修复:
/// - _shouldCreateNewSession 是查询方法,不应在非超时分支清空 _backgroundTime。
/// 修复前:getSessionId() 在后台期间被调用时(如推送通知触发 track()),
/// 非超时分支的 `_backgroundTime = null` 会提前清空后台时间,
/// 导致后续 onAppForeground() 无法判断后台时长,旧会话被错误保留。
/// 修复点:session_manager.dart _shouldCreateNewSession 中只在超时分支清空。
void main() {
const page = 'test_page';
setUp(() {
SessionManager.instance.reset();
AdImpressionManager.instance.clear();
});
tearDown(() {
SessionManager.instance.reset();
AdImpressionManager.instance.clear();
});
group('_shouldCreateNewSession 不应提前清空 _backgroundTime(Bug 2 核心)', () {
test('onAppBackground 后 backgroundTime 非 null', () {
SessionManager.instance.getSessionId(); // 确保已初始化
SessionManager.instance.onAppBackground();
expect(
SessionManager.instance.backgroundTimeForTest,
isNotNull,
reason: 'onAppBackground() 应设置 _backgroundTime',
);
});
test('后台期间调用 getSessionId() 不应清空 backgroundTime', () {
SessionManager.instance.getSessionId(); // 初始化会话
SessionManager.instance.onAppBackground();
// 模拟后台期间有推送通知触发了 track() → getSessionId()
// 后台时间极短(< 30 min),不应触发新会话,但也不应清空 _backgroundTime
SessionManager.instance.getSessionId();
expect(
SessionManager.instance.backgroundTimeForTest,
isNotNull,
reason: '后台期间调用 getSessionId() 不应清空 _backgroundTime,'
'否则后续 onAppForeground() 无法正确判断后台时长',
);
});
test('onAppForeground 后 backgroundTime 被正确清空', () {
SessionManager.instance.getSessionId();
SessionManager.instance.onAppBackground();
SessionManager.instance.onAppForeground();
expect(
SessionManager.instance.backgroundTimeForTest,
isNull,
reason: 'onAppForeground() 执行完毕后应清空 _backgroundTime',
);
});
test('未调用 onAppBackground 时,getSessionId 不影响 backgroundTime(始终为 null)', () {
SessionManager.instance.getSessionId();
expect(SessionManager.instance.backgroundTimeForTest, isNull);
SessionManager.instance.getSessionId();
expect(SessionManager.instance.backgroundTimeForTest, isNull);
});
});
group('新 session 时清空广告去重集(session 级去重)', () {
test('新 session 创建后 AdImpressionManager 被清空', () {
SessionManager.instance.getSessionId();
AdImpressionManager.instance.markAsReportedBatch('ad1,ad2', pageKey: page);
// 确认已标记
expect(AdImpressionManager.instance.getUnreportedAdIds('ad1,ad2', pageKey: page), isEmpty);
// 重置触发新 session
SessionManager.instance.reset();
SessionManager.instance.getSessionId();
expect(
AdImpressionManager.instance.getUnreportedAdIds('ad1,ad2', pageKey: page),
equals(['ad1', 'ad2']),
reason: '新 session 后同一 adId 应视为未上报',
);
});
test('同一 session 内标记后不再返回未上报', () {
SessionManager.instance.getSessionId();
AdImpressionManager.instance.markAsReportedBatch('ad1', pageKey: page);
// 没有新 session,ad1 应仍被去重
expect(
AdImpressionManager.instance.getUnreportedAdIds('ad1', pageKey: page),
isEmpty,
reason: '同 session 内 ad1 不应重复上报',
);
});
test('连续建立多个 session,每次都清空去重集', () {
const ids = 'ad1,ad2,ad3';
// Session 1
SessionManager.instance.getSessionId();
AdImpressionManager.instance.markAsReportedBatch(ids, pageKey: page);
expect(AdImpressionManager.instance.getUnreportedAdIds(ids, pageKey: page), isEmpty);
// Session 2
SessionManager.instance.reset();
SessionManager.instance.getSessionId();
expect(
AdImpressionManager.instance.getUnreportedAdIds(ids, pageKey: page),
equals(['ad1', 'ad2', 'ad3']),
reason: 'Session 2 开始时去重集应已清空',
);
// Session 2 内再次标记
AdImpressionManager.instance.markAsReportedBatch(ids, pageKey: page);
expect(AdImpressionManager.instance.getUnreportedAdIds(ids, pageKey: page), isEmpty);
// Session 3
SessionManager.instance.reset();
SessionManager.instance.getSessionId();
expect(
AdImpressionManager.instance.getUnreportedAdIds(ids, pageKey: page),
equals(['ad1', 'ad2', 'ad3']),
reason: 'Session 3 开始时去重集应再次清空',
);
});
test('端到端:上报 → 同 session 去重 → 新 session → 再次可报', () {
const adId = 'banner_001';
// Step 1: 首次出现 → 未上报
SessionManager.instance.getSessionId();
expect(AdImpressionManager.instance.getUnreportedAdIds(adId, pageKey: page), [adId]);
AdImpressionManager.instance.markAsReportedBatch(adId, pageKey: page);
// Step 2: 同 session 内再次出现 → 去重
expect(
AdImpressionManager.instance.getUnreportedAdIds(adId, pageKey: page),
isEmpty,
reason: '同 session 内不重复上报',
);
// Step 3: 新 session
SessionManager.instance.reset();
SessionManager.instance.getSessionId();
// Step 4: 新 session 内首次出现 → 可上报
expect(
AdImpressionManager.instance.getUnreportedAdIds(adId, pageKey: page),
equals([adId]),
reason: '新 session 内首次出现,应可上报',
);
// Step 5: 新 session 内标记后 → 再次去重
AdImpressionManager.instance.markAsReportedBatch(adId, pageKey: page);
expect(
AdImpressionManager.instance.getUnreportedAdIds(adId, pageKey: page),
isEmpty,
reason: '新 session 内已标记,不重复上报',
);
});
});
group('会话基础行为', () {
test('未初始化时 getSessionId 返回非空 ID', () {
final id = SessionManager.instance.getSessionId();
expect(id, isNotEmpty);
});
test('连续调用 getSessionId 返回相同 ID', () {
final id1 = SessionManager.instance.getSessionId();
final id2 = SessionManager.instance.getSessionId();
expect(id1, equals(id2));
});
test('reset 后 getSessionId 创建新 ID', () {
final id1 = SessionManager.instance.getSessionId();
SessionManager.instance.reset();
final id2 = SessionManager.instance.getSessionId();
expect(id1, isNot(equals(id2)));
});
});
}