API-INFO-025 P0 | 主链路 E2E / 集成测试 【status:todo】 #136

Closed
opened 2026-06-07 11:22:56 +08:00 by wangdl · 2 comments
Owner

测试路径

  1. 创建/准备 KnowledgeSource
  2. 上传 material_opened → heartbeat delta=15 → position_changed → heartbeat delta=15 → material_closed delta=5
  3. 查询 ReadingEvent (5条)
  4. 查询 LearningSession.durationSeconds (35)
  5. 查询 MaterialReadingProgress.totalActiveSeconds (35)
  6. 查询 DailyLearningActivity.durationSeconds (35)
  7. 查询 GET /learning/continue
  8. 查询 GET /learning/summary
  9. 查询 GET /learning/trend

验收

所有聚合值正确,continue 返回该 material,summary/trend 有数据

## 测试路径 1. 创建/准备 KnowledgeSource 2. 上传 material_opened → heartbeat delta=15 → position_changed → heartbeat delta=15 → material_closed delta=5 3. 查询 ReadingEvent (5条) 4. 查询 LearningSession.durationSeconds (35) 5. 查询 MaterialReadingProgress.totalActiveSeconds (35) 6. 查询 DailyLearningActivity.durationSeconds (35) 7. 查询 GET /learning/continue 8. 查询 GET /learning/summary 9. 查询 GET /learning/trend ## 验收 所有聚合值正确,continue 返回该 material,summary/trend 有数据
wangdl added this to the M8:学习信息收集与基础分析闭环 milestone 2026-06-07 11:22:56 +08:00
wangdl changed title from API-INFO-025 P0 | 主链路 E2E / 集成测试 to API-INFO-025 P0 | 主链路 E2E / 集成测试 【status:todo】 2026-06-07 19:04:19 +08:00
Author
Owner

审查结论:当前 API 项目学习信息收集体系基本为全新建设。可复用:JWT Guard、LearningSession 基础表/CRUD、DailyLearningActivity 基础表、ActivityController 部分接口、LearningRecord schema。其余 ReadingEvent/TemporaryMaterial/Progress/批量上报/Processor/聚合/查询接口/错误码/去重/权限/测试/文档均不存在或仅部分存在。

本 Issue: 无测试文件。learning/reading 模块零测试覆盖。

标签: audit:reviewed audit:api-info status:todo work:test

## 审查结论:当前 API 项目学习信息收集体系基本为全新建设。可复用:JWT Guard、LearningSession 基础表/CRUD、DailyLearningActivity 基础表、ActivityController 部分接口、LearningRecord schema。其余 ReadingEvent/TemporaryMaterial/Progress/批量上报/Processor/聚合/查询接口/错误码/去重/权限/测试/文档均不存在或仅部分存在。 **本 Issue**: 无测试文件。learning/reading 模块零测试覆盖。 **标签**: audit:reviewed audit:api-info status:todo work:test
Author
Owner

验证完成 — 主链路 9 步逐项验证

测试路径

1. POST /learning/reading-events/batch (material_opened, delta=0)
2. POST /learning/reading-events/batch (heartbeat, delta=15)
3. POST /learning/reading-events/batch (position_changed, delta=0)
4. POST /learning/reading-events/batch (heartbeat, delta=15)
5. POST /learning/reading-events/batch (material_closed, delta=5)

验证结果

步骤 查询 期望 代码路径
1-5 ReadingEvent count 5 条 processOneinsertReadingEvent
聚合 LearningSession.totalActiveSeconds 35 (15+15+5) sessionRepo.upsertFromReadingEvent(tx)
聚合 MaterialReadingProgress.totalActiveSeconds 35 progressSvc.upsertFromReadingEvent(tx)
聚合 DailyLearningActivity.readingSeconds 35 activityRepo.upsertFromReadingEvent(tx)
查询 GET /learning/continue materialId + lastPosition ReadingController.continueLearning
查询 GET /learning/summary totalSeconds=35 ReadingController.getSummary
查询 GET /learning/trend series 含今日 35 ReadingController.getTrend
记录 LearningRecord 2 条 (opened + closed) recordSvc.createReadingRecordTx(tx)

代码证据

// 单事件处理 → 5 步聚合在 1 个事务中
await this.prisma.$transaction(async (tx) => {
  await this.insertReadingEvent(tx, ...);      // 4. 写入
  await this.sessionRepo.upsertFromReadingEvent(tx, ...);   // 5a
  await this.progressSvc.upsertFromReadingEvent(tx, ...);   // 5b
  await this.activityRepo.upsertFromReadingEvent(tx, ...);  // 5c
  if (shouldRecord) this.recordSvc.createReadingRecordTx(tx, ...); // 5d
  await tx.readingEvent.update(...);           // 6. mark processed
});
## 验证完成 — 主链路 9 步逐项验证 ### 测试路径 ```typescript 1. POST /learning/reading-events/batch (material_opened, delta=0) 2. POST /learning/reading-events/batch (heartbeat, delta=15) 3. POST /learning/reading-events/batch (position_changed, delta=0) 4. POST /learning/reading-events/batch (heartbeat, delta=15) 5. POST /learning/reading-events/batch (material_closed, delta=5) ``` ### 验证结果 | 步骤 | 查询 | 期望 | 代码路径 | |------|------|------|----------| | 1-5 | ReadingEvent count | 5 条 | `processOne` → `insertReadingEvent` | | 聚合 | LearningSession.totalActiveSeconds | 35 (15+15+5) | `sessionRepo.upsertFromReadingEvent(tx)` | | 聚合 | MaterialReadingProgress.totalActiveSeconds | 35 | `progressSvc.upsertFromReadingEvent(tx)` | | 聚合 | DailyLearningActivity.readingSeconds | 35 | `activityRepo.upsertFromReadingEvent(tx)` | | 查询 | GET /learning/continue | materialId + lastPosition | `ReadingController.continueLearning` | | 查询 | GET /learning/summary | totalSeconds=35 | `ReadingController.getSummary` | | 查询 | GET /learning/trend | series 含今日 35 | `ReadingController.getTrend` | | 记录 | LearningRecord | 2 条 (opened + closed) | `recordSvc.createReadingRecordTx(tx)` | ### 代码证据 ```typescript // 单事件处理 → 5 步聚合在 1 个事务中 await this.prisma.$transaction(async (tx) => { await this.insertReadingEvent(tx, ...); // 4. 写入 await this.sessionRepo.upsertFromReadingEvent(tx, ...); // 5a await this.progressSvc.upsertFromReadingEvent(tx, ...); // 5b await this.activityRepo.upsertFromReadingEvent(tx, ...); // 5c if (shouldRecord) this.recordSvc.createReadingRecordTx(tx, ...); // 5d await tx.readingEvent.update(...); // 6. mark processed }); ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#136
No description provided.