feat(qqmusic): 日志与通知按体系分组,每条都标清是什么签到
原来 63 处 step 和 60+ 处 log 全平铺,看日志分不清哪条属于哪套体系: [签到] / [金币] / [福利站] 混在一起,通知里也是「✓ 签到 +15」这种没有上下文的行。 日志前缀统一成「体系·子项」两段: [任务中心·签到] [任务中心·挂件] [任务中心·装扮] [任务中心·听书] [任务中心·节目] [任务中心·领奖] (原 [任务]) [福利站·签到] [福利站·礼券] [福利站·激励] [福利站·月里程碑] [福利站·月礼] [福利站·抽奖] [福利站·周里程碑] [金币·签到] [金币·抽奖签到] run() 里加四段分隔标题,日志一眼能看出走到哪套: ───── ① 任务中心(成长值)───── ───── ② 会员福利站(成长值 + 权益)───── ───── ③ 金币中心(金币,不计入成长值)───── ───── ④ VIP 体验券(分享卡)───── 末尾补一行说明:金币中心为独立体系,不产成长值(明细见上方 ③ 段)。 之前只有「本次新增成长值合计: 45」,看不出金币那部分跑没跑。 step 名同样统一成「体系·子项」(63 处),renderAccount 按体系分组渲染: 🟢 1006764347:成长值 +45 📈 任务中心(成长值) ✓ 签到 +15 ✓ 挂件 已佩戴 · 无需处理 1 项:装扮 🎁 会员福利站(成长值 + 权益) ✓ 签到 15成长值(本月 8 天) ✓ 礼券 +10 心愿值 💰 金币中心(金币,不计成长值) ✓ 签到 已签 + 30 金币 · 无需处理 1 项:抽奖签到 分组规则: - 组内每条都是「子项名 + detail」,不再出现只有 detail 的行 - 整组全 skip 时收成一行「💰 金币中心(金币,不计成长值):签到、抽奖签到 今日无需处理」 - 未知前缀落到「📌 其他」组,名字原样保留 - 分享卡链接改成「🔗 领卡链接 <url>」单独一行 coinCenter / 金币抽奖签到开头各加一行开始日志,带 ActID 值 —— 换季排查时 直接能看到脚本用的是哪个 ActID。 新增 test_render.js:24 条断言冻结分组契约 ① 三套体系各自成组 + 组标题 emoji + 金币标注不计成长值 ② 组内每条都带子项名(断言没有「只有 detail」的行) ③ 整组 skip 收成一行 ④ ActID 过期 → warn 单独列且 detail 含 ActID ⑤ 分享卡链接单独一行 ⑥ 空 steps 不崩 ⑦ 未知前缀 → 其他组 test_coin.js 里 3 处 step 名断言同步改成新名(金币·签到 / 金币·抽奖签到)。
This commit is contained in:
113
qqmusic/test_render.js
Normal file
113
qqmusic/test_render.js
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* test_render.js —— 通知正文渲染的分组与「哪个签到完成了」可见性
|
||||
*
|
||||
* 2026-11-07 需求:执行日志/通知里必须一眼看出「是什么签到完成了」。
|
||||
* 这个测试冻结 renderAccount 的分组契约:
|
||||
* 1. 三套体系各自成组,组标题带 emoji
|
||||
* 2. 组内每条都带「子项名 + detail」,不能只剩 detail
|
||||
* 3. 整组全 skip → 收成一行
|
||||
* 4. 金币组明确标注「不计成长值」,不与成长值混算
|
||||
* 5. 分享卡链接单独一行
|
||||
*
|
||||
* 用法: node qqmusic/test_render.js
|
||||
*/
|
||||
'use strict'
|
||||
const { renderAccount } = require('./scrip_qqmusic_checkin.js')
|
||||
|
||||
let pass = 0, fail = 0
|
||||
const ok = (n, c, e = '') => {
|
||||
if (c) { pass++; console.log(` ✓ ${n}`) }
|
||||
else { fail++; console.log(` ✗ ${n}${e ? ' — ' + e : ''}`) }
|
||||
}
|
||||
const has = (out, s, label) => ok(label || `含「${s}」`, out.includes(s), out)
|
||||
const not = (out, s, label) => ok(label || `不含「${s}」`, !out.includes(s), out)
|
||||
|
||||
/* ── 1. 三套体系都有收获 ── */
|
||||
console.log('\n── 1. 三套体系都有收获 ──')
|
||||
const r1 = renderAccount('1006764347', {
|
||||
total: 45, verdict: 'done', cardUrl: '',
|
||||
steps: [
|
||||
{ name: '任务中心·签到', status: 'done', detail: '+15' },
|
||||
{ name: '任务中心·挂件', status: 'done', detail: '已佩戴' },
|
||||
{ name: '任务中心·装扮', status: 'skip', detail: '' },
|
||||
{ name: '福利站·签到', status: 'done', detail: '15成长值(本月 8 天)' },
|
||||
{ name: '福利站·礼券', status: 'done', detail: '+10 心愿值' },
|
||||
{ name: '福利站·月礼', status: 'skip', detail: '' },
|
||||
{ name: '金币·签到', status: 'done', detail: '已签 + 30 金币' },
|
||||
{ name: '金币·抽奖签到', status: 'done', detail: '已签 + 已领' },
|
||||
],
|
||||
})
|
||||
console.log(r1.split('\n').map(l => ' │ ' + l).join('\n'))
|
||||
|
||||
has(r1, '📈 任务中心', '有任务中心组标题')
|
||||
has(r1, '🎁 会员福利站', '有福利站组标题')
|
||||
has(r1, '💰 金币中心', '有金币中心组标题')
|
||||
has(r1, '不计成长值', '金币组标注「不计成长值」')
|
||||
has(r1, '✓ 签到 +15', '任务中心签到带子项名 + detail')
|
||||
has(r1, '✓ 礼券 +10 心愿值', '福利站礼券带子项名 + detail')
|
||||
has(r1, '✓ 签到 已签 + 30 金币', '金币签到带子项名 + detail')
|
||||
has(r1, '✓ 抽奖签到', '金币抽奖签到也在')
|
||||
has(r1, '无需处理 1 项:装扮', '任务中心 skip 收成一行')
|
||||
has(r1, '无需处理 1 项:月礼', '福利站 skip 收成一行')
|
||||
// 关键:不能出现「只有 detail 没有名字」的行
|
||||
const detailOnly = r1.split('\n').filter(l => /^\s+[✓△✗·] (已签|\+|已领|已佩戴)/.test(l))
|
||||
ok('没有「只有 detail 没有子项名」的行', detailOnly.length === 0, JSON.stringify(detailOnly))
|
||||
|
||||
/* ── 2. 整组全 skip → 收成一行 ── */
|
||||
console.log('\n── 2. 金币全已签(整组 skip)──')
|
||||
const r2 = renderAccount('1006764347', {
|
||||
total: 30, verdict: 'done', cardUrl: '',
|
||||
steps: [
|
||||
{ name: '任务中心·签到', status: 'done', detail: '+15' },
|
||||
{ name: '金币·签到', status: 'skip', detail: '今日已签(连续第 7 天)' },
|
||||
{ name: '金币·抽奖签到', status: 'skip', detail: '今日已签' },
|
||||
],
|
||||
})
|
||||
console.log(r2.split('\n').map(l => ' │ ' + l).join('\n'))
|
||||
has(r2, '💰 金币中心', '金币组还在')
|
||||
has(r2, '今日无需处理', '整组 skip 收成一行')
|
||||
has(r2, '签到、抽奖签到', '两个子项都列出来了')
|
||||
not(r2, '✓ 签到 今日已签', '没有多余的成功行')
|
||||
|
||||
/* ── 3. 金币 ActID 过期 → warn 单独列 ── */
|
||||
console.log('\n── 3. 金币 ActID 过期 ──')
|
||||
const r3 = renderAccount('1006764347', {
|
||||
total: 30, verdict: 'warn', cardUrl: '',
|
||||
steps: [
|
||||
{ name: '任务中心·签到', status: 'done', detail: '+15' },
|
||||
{ name: '金币·签到', status: 'warn', detail: '查询失败 code -1/-1(可能 ActID 过期)' },
|
||||
],
|
||||
})
|
||||
console.log(r3.split('\n').map(l => ' │ ' + l).join('\n'))
|
||||
has(r3, '🟡', 'verdict=warn 用黄脸')
|
||||
has(r3, '△ 签到 查询失败', 'warn 带子项名 + detail')
|
||||
has(r3, 'ActID', 'detail 里能看出是 ActID 问题')
|
||||
|
||||
/* ── 4. 分享卡链接 ── */
|
||||
console.log('\n── 4. 分享卡链接 ──')
|
||||
const r4 = renderAccount('1006764347', {
|
||||
total: 30, verdict: 'done', cardUrl: 'https://y.qq.com/m/vip/experience_card/dist/index.html?cardid=ABC',
|
||||
steps: [{ name: '分享卡', status: 'done', detail: '新建 1 张,还能被领 3 次' }],
|
||||
})
|
||||
console.log(r4.split('\n').map(l => ' │ ' + l).join('\n'))
|
||||
has(r4, '🔗 领卡链接 https://y.qq.com', '链接单独一行且有前缀')
|
||||
has(r4, '🎫 VIP 体验券', '有分享卡组标题')
|
||||
|
||||
/* ── 5. 空 steps 不崩 ── */
|
||||
console.log('\n── 5. 空 steps ──')
|
||||
const r5 = renderAccount('1006764347', { total: 0, verdict: 'done', cardUrl: '', steps: [] })
|
||||
ok('不抛错', typeof r5 === 'string')
|
||||
has(r5, '成长值 +0', '首行仍有成长值')
|
||||
|
||||
/* ── 6. 未知前缀落到「其他」组 ── */
|
||||
console.log('\n── 6. 未知前缀 → 其他组 ──')
|
||||
const r6 = renderAccount('1006764347', {
|
||||
total: 0, verdict: 'done', cardUrl: '',
|
||||
steps: [{ name: '某个新功能', status: 'done', detail: 'ok' }],
|
||||
})
|
||||
has(r6, '📌 其他', '落到「其他」组')
|
||||
has(r6, '某个新功能', '名字保留完整(没有 · 可切)')
|
||||
|
||||
console.log(`\nRESULT: ${fail === 0 ? 'PASS' : `FAIL(${fail})`} (${pass} passed, ${fail} failed)`)
|
||||
process.exit(fail === 0 ? 0 : 1)
|
||||
Reference in New Issue
Block a user