补齐 XP 与连续学习测试覆盖

This commit is contained in:
Wang Zhuoxuan 2026-05-13 10:55:17 +08:00
parent c08d3f75b9
commit 1ad26d0fe8
3 changed files with 27 additions and 1 deletions

View File

@ -59,13 +59,14 @@
| G2-4 | 将连续学习改为按挑战组完成计算 | [x] | 每天至少完成 1 组挑战才更新 streak不再依赖当天正确题数阈值 | | G2-4 | 将连续学习改为按挑战组完成计算 | [x] | 每天至少完成 1 组挑战才更新 streak不再依赖当天正确题数阈值 |
| G2-5 | 实现连续学习里程碑奖励 | [x] | 3/7/14/30/100 天奖励可发放且不可重复领取 | | G2-5 | 实现连续学习里程碑奖励 | [x] | 3/7/14/30/100 天奖励可发放且不可重复领取 |
| G2-6 | 实现每日首次进入送红心 | [x] | 每日首次 bootstrap 或专用 check-in 最多补 1 颗,不超过上限 | | G2-6 | 实现每日首次进入送红心 | [x] | 每日首次 bootstrap 或专用 check-in 最多补 1 颗,不超过上限 |
| G2-7 | 添加 XP/streak 测试 | [ ] | 覆盖等级边界、首次知识卡、完成组奖励、全对奖励、看解析奖励、连续学习保护 | | G2-7 | 添加 XP/streak 测试 | [x] | 覆盖等级边界、首次知识卡、完成组奖励、全对奖励、看解析奖励、连续学习保护 |
验证记录2026-05-13G2-2 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .``bun` 当前 shell 不在 PATH`./node_modules/.bin/vitest run` 启动阶段被 macOS 拒绝加载未签名的 `@rolldown/binding-darwin-x64` 原生 binding需修复本地依赖安装或签名后复跑。 验证记录2026-05-13G2-2 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .``bun` 当前 shell 不在 PATH`./node_modules/.bin/vitest run` 启动阶段被 macOS 拒绝加载未签名的 `@rolldown/binding-darwin-x64` 原生 binding需修复本地依赖安装或签名后复跑。
验证记录2026-05-13G2-3 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/xp-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。 验证记录2026-05-13G2-3 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/xp-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。
验证记录2026-05-13G2-4 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/streak-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。 验证记录2026-05-13G2-4 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/streak-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。
验证记录2026-05-13G2-5 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/streak-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。 验证记录2026-05-13G2-5 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/streak-service.test.ts src/__tests__/services/learning/challenge-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。
验证记录2026-05-13G2-6 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/learning/progress-summary-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。 验证记录2026-05-13G2-6 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/learning/progress-summary-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。
验证记录2026-05-13G2-7 已通过 `./node_modules/.bin/tsc --noEmit``./node_modules/.bin/eslint .`;定向运行 `./node_modules/.bin/vitest run src/__tests__/services/progress/xp-service.test.ts src/__tests__/services/progress/streak-service.test.ts src/__tests__/services/learning/challenge-service.test.ts src/__tests__/services/learning/progress-summary-service.test.ts` 仍在启动阶段被同一个 `@rolldown/binding-darwin-x64` 原生 binding 签名问题阻塞。
## Phase G3金币、商店和道具 ## Phase G3金币、商店和道具

View File

@ -1,6 +1,7 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { beforeEach, describe, expect, it, vi } from 'vitest';
import { db } from '../../../db/client.js'; import { db } from '../../../db/client.js';
import { import {
freezeStreak,
getStreakMilestoneReward, getStreakMilestoneReward,
grantStreakMilestoneReward, grantStreakMilestoneReward,
updateStreakForCompletedChallenge, updateStreakForCompletedChallenge,
@ -143,4 +144,22 @@ describe('Streak service — completed challenge updates', () => {
expect(rewards).toEqual([]); expect(rewards).toEqual([]);
expect(db.insert).not.toHaveBeenCalled(); expect(db.insert).not.toHaveBeenCalled();
}); });
it('freezes streak protection for today without incrementing streak days', async () => {
selectQueue([
[{ streakDays: 12 }],
]);
const update = mockUpdate();
const result = await freezeStreak('user-1');
expect(result).toEqual({
days: 12,
lastDate: new Date().toISOString().slice(0, 10),
frozen: true,
});
expect(update.set).toHaveBeenCalledWith(expect.objectContaining({
streakLastDate: expect.any(Object),
}));
});
}); });

View File

@ -90,6 +90,12 @@ describe('XP service', () => {
amount: 15, amount: 15,
title: '首次知识卡 +15 XP', title: '首次知识卡 +15 XP',
}); });
expect(createXpReward('review_explanation')).toEqual({
type: 'xp',
source: 'review_explanation',
amount: 3,
title: '查看解析 +3 XP',
});
}); });
}); });
}); });