124 lines
3.6 KiB
JavaScript
124 lines
3.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import {
|
|
buildCollectionFinishedMessage,
|
|
buildPublishSubmittedMessage,
|
|
notifyCollectionFinished,
|
|
notifyPartnerSubmitted,
|
|
} from "../lib/wecom-feedback-service.ts";
|
|
import { resolveWecomConfig } from "../lib/wecom-client.ts";
|
|
|
|
const config = resolveWecomConfig({
|
|
WECOM_CORP_ID: "corp-test",
|
|
WECOM_AGENT_ID: "1000001",
|
|
WECOM_SECRET: "secret-test",
|
|
WECOM_ROBOT_WEBHOOK: "https://qyapi.example.com/webhook/send?key=abc",
|
|
});
|
|
|
|
const submittedRow = {
|
|
claimant_name: "小王",
|
|
partner_name: "合作方甲",
|
|
task_name: "夏日轻盈计划",
|
|
content_title: "好物分享笔记",
|
|
publish_url: "https://www.xiaohongshu.com/explore/abc",
|
|
};
|
|
|
|
function robotFetch(calls) {
|
|
return async (input, init = {}) => {
|
|
const url = new URL(String(input));
|
|
calls.push({ url, init });
|
|
return Response.json({ errcode: 0, errmsg: "ok" });
|
|
};
|
|
}
|
|
|
|
function fakeSubmittedDb(row = submittedRow) {
|
|
return {
|
|
prepare(sql) {
|
|
return {
|
|
bind() {
|
|
return {
|
|
async first() {
|
|
if (/FROM distributions d/.test(sql)) return row;
|
|
return null;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
test("publish submitted message covers partner, task and link", () => {
|
|
const message = buildPublishSubmittedMessage(submittedRow, "publish");
|
|
assert.match(message, /【KOC 已提交发布】/);
|
|
assert.match(message, /合作方:合作方甲/);
|
|
assert.match(message, /夏日轻盈计划/);
|
|
assert.match(message, /xiaohongshu\.com\/explore\/abc/);
|
|
const screenshot = buildPublishSubmittedMessage(submittedRow, "screenshot");
|
|
assert.match(screenshot, /【KOC 已提交截图】/);
|
|
assert.doesNotMatch(screenshot, /链接:/);
|
|
});
|
|
|
|
test("collection digest includes failure hint only when failed", () => {
|
|
const ok = buildCollectionFinishedMessage({
|
|
currentDate: "2026-09-01",
|
|
dueTasks: 3,
|
|
attempted: 10,
|
|
succeeded: 10,
|
|
failed: 0,
|
|
});
|
|
assert.match(ok, /成功 10、失败 0/);
|
|
assert.doesNotMatch(ok, /重试/);
|
|
const bad = buildCollectionFinishedMessage({
|
|
currentDate: "2026-09-01",
|
|
dueTasks: 3,
|
|
attempted: 10,
|
|
succeeded: 7,
|
|
failed: 3,
|
|
});
|
|
assert.match(bad, /重试/);
|
|
});
|
|
|
|
test("notifyPartnerSubmitted posts robot message and skips without webhook", async () => {
|
|
const calls = [];
|
|
const sent = await notifyPartnerSubmitted(
|
|
fakeSubmittedDb(),
|
|
{ distributionId: "d-1", kind: "publish" },
|
|
config,
|
|
robotFetch(calls),
|
|
);
|
|
assert.equal(sent, true);
|
|
assert.equal(calls.length, 1);
|
|
const body = JSON.parse(String(calls[0].init.body));
|
|
assert.equal(body.msgtype, "text");
|
|
assert.match(body.text.content, /【KOC 已提交发布】/);
|
|
|
|
const noWebhook = await notifyPartnerSubmitted(
|
|
fakeSubmittedDb(),
|
|
{ distributionId: "d-1", kind: "publish" },
|
|
resolveWecomConfig({}),
|
|
robotFetch([]),
|
|
);
|
|
assert.equal(noWebhook, false);
|
|
});
|
|
|
|
test("notifyCollectionFinished skips empty batches and posts on activity", async () => {
|
|
const calls = [];
|
|
const idle = await notifyCollectionFinished(
|
|
{ currentDate: "2026-09-01", dueTasks: 0, attempted: 0, succeeded: 0, failed: 0 },
|
|
config,
|
|
robotFetch(calls),
|
|
);
|
|
assert.equal(idle, false);
|
|
assert.equal(calls.length, 0);
|
|
|
|
const active = await notifyCollectionFinished(
|
|
{ currentDate: "2026-09-01", dueTasks: 2, attempted: 5, succeeded: 4, failed: 1 },
|
|
config,
|
|
robotFetch(calls),
|
|
);
|
|
assert.equal(active, true);
|
|
assert.equal(calls.length, 1);
|
|
assert.match(JSON.parse(String(calls[0].init.body)).text.content, /成功 4、失败 1/);
|
|
});
|