import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import test from "node:test"; // 公开数据采集失败兜底闭环(2026-10-09): // 自动采集优先 → 采集失败时催 KOC 补交数据截图 → 运营按截图核对补录互动数据。 // 同时修正门户创作者数据区块的表述:公开数据系统自动采集,KOC 不需要每天手动填。 test("koc can submit a public-metrics screenshot when auto collection fails", async () => { const [uploadRoute, imageRoute, partnerRoute, page, schema, migration] = await Promise.all([ readFile(new URL("../app/api/partner-upload/route.ts", import.meta.url), "utf8"), readFile(new URL("../app/api/partner-image/route.ts", import.meta.url), "utf8"), readFile(new URL("../app/api/partner/route.ts", import.meta.url), "utf8"), readFile(new URL("../koc-portal/app/page.tsx", import.meta.url), "utf8"), readFile(new URL("../db/schema.ts", import.meta.url), "utf8"), readFile(new URL("../mysql/0022_public_metrics_screenshot.sql", import.meta.url), "utf8"), ]); assert.match(migration, /ALTER TABLE distributions ADD COLUMN public_metrics_screenshot_key TEXT/); assert.match(schema, /publicMetricsScreenshotKey/); // 上传通道:仅发布后可补交,落 public-metrics/ 目录并标记待核对 assert.match(uploadRoute, /"public-metrics"/); assert.match(uploadRoute, /\(isCreatorCenter \|\| isPublicMetrics\) && !assignment\.publish_url/); assert.match(uploadRoute, /public-metrics\/\$\{upload\.distributionId\}/); assert.match(uploadRoute, /public_metrics_screenshot_key = \?/); assert.match(uploadRoute, /KOC已补交数据截图,待运营核对/); // 领取载荷:门户能感知采集状态、已采集到的公开数据与补交截图 assert.match(partnerRoute, /d\.collection_status,/); assert.match(partnerRoute, /d\.latest_likes,/); assert.match(partnerRoute, /d\.public_metrics_screenshot_key,/); // 图片服务:KOC 可查看自己补交的数据截图(可变凭证不缓存) assert.match(imageRoute, /imageKind === "public-metrics"/); assert.match(imageRoute, /d\.public_metrics_screenshot_key/); assert.match(imageRoute, /imageKind === "public-metrics"/); // 门户:仅采集失败且已发布时展示补交入口 assert.match(page, /collection_status === "failed"/); assert.match(page, /"public-metrics"/); assert.match(page, /submitPublicMetricsShot/); assert.match(page, /自动采集失败,请补交数据截图/); assert.match(page, /运营核对后会补录数据/); }); test("creator data section reads as one-time d7 step, not a daily manual form", async () => { const [page, styles] = await Promise.all([ readFile(new URL("../koc-portal/app/page.tsx", import.meta.url), "utf8"), readFile(new URL("../koc-portal/app/globals.css", import.meta.url), "utf8"), ]); // 自动采集状态行:有数据时直接展示最近采到的赞藏评 assert.match(page, /auto-collect-line/); assert.match(page, /公开数据系统自动采集中/); assert.match(page, /由系统每天自动采集,无需你填写/); // 一次性表述 + 仅识别失败才手动填 assert.match(page, /这一步只需做一次/); assert.match(page, /仅当识别失败时才需要手动填写这两个数字/); assert.match(page, /只有识别失败时才需要手动修改/); assert.match(styles, /\.auto-collect-line/); assert.match(styles, /\.metrics-fallback/); }); test("admin reviews the fallback screenshot and records engagement metrics", async () => { const [actionRoute, adminApp, creatorRoute] = await Promise.all([ readFile(new URL("../app/api/action/route.ts", import.meta.url), "utf8"), readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"), readFile(new URL("../app/api/creator-screenshot/route.ts", import.meta.url), "utf8"), ]); // manual_metrics:曝光/阅读可留空;补录互动数据并把采集状态置成功 assert.match(actionRoute, /publicLikes/); assert.match(actionRoute, /latest_likes = CASE WHEN \? THEN \? ELSE latest_likes END/); assert.match(actionRoute, /collection_status = CASE WHEN \? THEN 'success' ELSE collection_status END/); assert.match(actionRoute, /运营已按补交截图核对补录/); // 后台:采集失败行出现「核对补录」入口,状态列可直达补交截图 assert.match(adminApp, /核对补录/); assert.match(adminApp, /KOC补交截图/); assert.match(adminApp, /kind=public-metrics/); assert.match(adminApp, /请至少填写创作者数据或公开互动数据中的一项/); // 截图服务:kind=public-metrics 仅管理端可读 assert.match(creatorRoute, /"public-metrics"/); assert.match(creatorRoute, /public_metrics_screenshot_key/); }); test("due-soon reminders include failed collections as a metrics phase", async () => { const [notifier, adminApp] = await Promise.all([ readFile(new URL("../lib/wecom-notifier-service.ts", import.meta.url), "utf8"), readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"), ]); // 催办查询纳入采集失败(不限日期),文案区分「公开数据待补交」 assert.match(notifier, /WHEN d\.collection_status = 'failed' THEN 'metrics'/); assert.match(notifier, /AND d\.collection_status = 'failed'\)/); assert.match(notifier, /公开数据待补交/); // 回收队列的「催办未完成」计数与催办口径对齐(含采集失败行) assert.match(adminApp, /\(recoveryEnabled \? recoveryPending : 0\) \+/); assert.match(adminApp, /\+\s*failedCollectionCount/); });