106 lines
4.2 KiB
JavaScript
106 lines
4.2 KiB
JavaScript
|
|
import assert from "node:assert/strict";
|
|||
|
|
import { readFile } from "node:fs/promises";
|
|||
|
|
import test from "node:test";
|
|||
|
|
|
|||
|
|
// 2026-10-08 第二轮交互走查修复:
|
|||
|
|
// 1) 完成态判据统一为「曝光量+阅读量齐即 complete」(原 d7_likes 条件全库无赋值方,永不触发)
|
|||
|
|
// 2) 回收队列头部统计改为「已发布 N / 总数」口径,未回填行不再计入
|
|||
|
|
// 3) 行内更新/补填链接从原生 prompt() 改为弹窗表单,失败保留已输入内容
|
|||
|
|
// 4) 顶栏「获取KOC领取链接」从导航跳转改为直接弹出各任务领取链接列表
|
|||
|
|
|
|||
|
|
test("creator metrics completion follows the exposure+views criterion", async () => {
|
|||
|
|
const sources = await Promise.all([
|
|||
|
|
readFile(new URL("../app/api/partner/route.ts", import.meta.url), "utf8"),
|
|||
|
|
readFile(new URL("../app/api/action/route.ts", import.meta.url), "utf8"),
|
|||
|
|
]);
|
|||
|
|
for (const source of sources) {
|
|||
|
|
assert.match(
|
|||
|
|
source,
|
|||
|
|
/status = CASE WHEN exposure IS NOT NULL AND views IS NOT NULL THEN 'complete' ELSE status END/,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
// 死条件必须清除:d7_likes 只被置 NULL 从不赋值,不能作为完成判据
|
|||
|
|
for (const source of sources) {
|
|||
|
|
assert.doesNotMatch(
|
|||
|
|
source,
|
|||
|
|
/CASE WHEN d7_likes IS NOT NULL THEN 'complete'/,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("manual metrics refreshes the task status afterwards", async () => {
|
|||
|
|
const source = await readFile(
|
|||
|
|
new URL("../app/api/action/route.ts", import.meta.url),
|
|||
|
|
"utf8",
|
|||
|
|
);
|
|||
|
|
assert.match(source, /import \{ refreshTaskStatus \} from "\.\.\/\.\.\/\.\.\/lib\/task-service";/);
|
|||
|
|
const manual = source.slice(
|
|||
|
|
source.indexOf('body.action === "manual_metrics"'),
|
|||
|
|
source.indexOf('body.action === "bind_wecom_external_id"'),
|
|||
|
|
);
|
|||
|
|
assert.ok(manual.includes("manual_metrics"), "必须截取到 manual_metrics 分支");
|
|||
|
|
assert.match(manual, /SELECT task_id FROM distributions WHERE id = \?/);
|
|||
|
|
assert.match(manual, /refreshTaskStatus\(ownerTask\.task_id, db\)/);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("recovery queue header counts only published rows", async () => {
|
|||
|
|
const source = await readFile(
|
|||
|
|
new URL("../app/admin-app.tsx", import.meta.url),
|
|||
|
|
"utf8",
|
|||
|
|
);
|
|||
|
|
assert.match(
|
|||
|
|
source,
|
|||
|
|
/const publishedCount = taskDistributions\.filter\(/,
|
|||
|
|
);
|
|||
|
|
assert.match(
|
|||
|
|
source,
|
|||
|
|
/已发布 \{publishedCount\} \/ \{taskDistributions\.length\} 篇/,
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("publish url editing uses a modal instead of window.prompt", async () => {
|
|||
|
|
const source = await readFile(
|
|||
|
|
new URL("../app/admin-app.tsx", import.meta.url),
|
|||
|
|
"utf8",
|
|||
|
|
);
|
|||
|
|
assert.match(source, /const \[publishUrlModal, setPublishUrlModal\]/);
|
|||
|
|
assert.match(source, /onSubmit=\{submitPublishUrl\}/);
|
|||
|
|
assert.match(source, /支持长链、短链或完整分享文案/);
|
|||
|
|
// 提交失败保留弹窗内容(runAction 失败返回 false)
|
|||
|
|
assert.match(source, /if \(updated\) setPublishUrlModal\(null\);/);
|
|||
|
|
// 更新链接流程本身不再用 prompt(剪贴板复制失败兜底的 prompt 保留)
|
|||
|
|
const updateFn = source.slice(
|
|||
|
|
source.indexOf("const updateDistributionPublishUrl"),
|
|||
|
|
source.indexOf("const submitPublishUrl"),
|
|||
|
|
);
|
|||
|
|
assert.ok(updateFn.includes("updateDistributionPublishUrl"), "必须截取到函数体");
|
|||
|
|
assert.doesNotMatch(updateFn, /prompt/);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("claim links button opens a modal listing every task link", async () => {
|
|||
|
|
const source = await readFile(
|
|||
|
|
new URL("../app/admin-app.tsx", import.meta.url),
|
|||
|
|
"utf8",
|
|||
|
|
);
|
|||
|
|
assert.match(source, /const \[claimLinksOpen, setClaimLinksOpen\] = useState\(false\);/);
|
|||
|
|
// 顶栏按钮不再是导航跳转
|
|||
|
|
assert.match(source, /onClick=\{\(\) => setClaimLinksOpen\(true\)\}/);
|
|||
|
|
assert.doesNotMatch(
|
|||
|
|
source,
|
|||
|
|
/onClick=\{\(\) => setActiveNav\("tasks"\)\}\s*\n\s*获取KOC领取链接/,
|
|||
|
|
);
|
|||
|
|
// 弹窗里每个任务给出复制按钮,无链接的任务明示未生成
|
|||
|
|
assert.match(source, /claim-links-list/);
|
|||
|
|
assert.match(source, /KOC领取链接已复制/);
|
|||
|
|
assert.match(source, /尚未生成领取链接/);
|
|||
|
|
// 弹窗内点击(含复制按钮)不能冒泡到 backdrop 导致误关闭
|
|||
|
|
const modal = source.slice(
|
|||
|
|
source.indexOf('className="modal-card compact claim-links-modal"'),
|
|||
|
|
source.indexOf('<div className="claim-links-list">'),
|
|||
|
|
);
|
|||
|
|
assert.match(
|
|||
|
|
modal,
|
|||
|
|
/onMouseDown=\{\(event\) => event\.stopPropagation\(\)\}/,
|
|||
|
|
);
|
|||
|
|
});
|