Files
memind/wechat-news-morning-draft-worker.test.mjs
T
john 62caf4134b feat(wechat): add Portal worker for daily news morning draft auto push
Run scheduled page generation before push time and write WeChat drafts from admin config so news morning reports no longer require manual pushes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-11 08:48:02 +08:00

142 lines
4.1 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import { PUBLIC_ZONE_DIR, PUBLISH_ROOT_DIR } from './user-publish.mjs';
import { startWechatNewsMorningDraftWorker } from './wechat-news-morning-draft-worker.mjs';
import {
createWechatNewsMorningDraftService,
wechatNewsMorningDraftInternals,
} from './wechat-news-morning-draft.mjs';
const SAMPLE_HTML = `<!DOCTYPE html><html><body><h1>📰 每日新闻早报</h1></body></html>`;
function createPool() {
const rows = [];
return {
rows,
async query(sql, params = []) {
if (sql.includes('CREATE TABLE')) return [[], []];
if (sql.includes('FROM h5_wechat_admin_config')) return [[], []];
if (sql.includes('INSERT INTO h5_wechat_news_draft_runs')) {
rows.push({
id: params[0],
status: params[1],
pageSlug: params[2],
pageUrl: params[3],
draftMediaId: params[4],
errorMessage: params[5],
triggeredBy: params[6],
createdAt: Number(params[7]),
});
return [[], []];
}
if (sql.includes('FROM h5_wechat_news_draft_runs')) {
return [rows.slice().reverse(), []];
}
return [[], []];
},
};
}
test('news morning draft worker auto-pushes at configured time', async () => {
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'news-draft-worker-'));
const userId = 'user-news';
const publicDir = path.join(tmpRoot, PUBLISH_ROOT_DIR, userId, PUBLIC_ZONE_DIR);
fs.mkdirSync(publicDir, { recursive: true });
fs.writeFileSync(path.join(publicDir, 'daily-news-0911.html'), SAMPLE_HTML);
const pool = createPool();
const service = createWechatNewsMorningDraftService(pool, {
mpConfig: { enabled: true, appId: 'app', appSecret: 'secret' },
h5Root: tmpRoot,
env: {
H5_WECHAT_NEWS_MORNING_DRAFT_ENABLED: '1',
H5_WECHAT_NEWS_MORNING_DRAFT_AUTO: '1',
H5_WECHAT_NEWS_MORNING_DRAFT_USER_ID: userId,
H5_WECHAT_NEWS_MORNING_DRAFT_HOUR: '6',
H5_WECHAT_NEWS_MORNING_DRAFT_MINUTE: '0',
},
});
const pushCalls = [];
service.pushDraft = async (options = {}) => {
pushCalls.push(options);
return {
ok: true,
draftMediaId: 'draft-1',
preview: { page: { slug: 'daily-news-0911' } },
};
};
service.hasSuccessfulAutoPushToday = async () => false;
const fixedNow = Date.UTC(2026, 8, 10, 22, 0, 0);
const originalNow = Date.now;
Date.now = () => fixedNow;
try {
const worker = startWechatNewsMorningDraftWorker({
wechatNewsMorningDraftService: service,
mpConfig: { enabled: true },
userAuth: { canUseChat: async () => ({ ok: true }) },
tkmindProxy: { id: 'proxy' },
h5Root: tmpRoot,
env: {
H5_WECHAT_NEWS_MORNING_DRAFT_WORKER_ENABLED: '1',
},
intervalMs: 30_000,
runOnStart: false,
setIntervalFn: () => ({ unref() {} }),
});
await worker.runOnce();
assert.equal(pushCalls.length, 1);
assert.deepEqual(pushCalls[0], { triggeredBy: 'auto-push' });
} finally {
Date.now = originalNow;
fs.rmSync(tmpRoot, { recursive: true, force: true });
}
});
test('schedule helpers detect today page and due windows', () => {
const {
isNewsMorningPageForToday,
isLocalScheduleDue,
isWithinNewsMorningGenerateLeadWindow,
formatLocalDateParts,
} = wechatNewsMorningDraftInternals;
const now = Date.UTC(2026, 8, 10, 22, 0, 0);
const parts = formatLocalDateParts(new Date(now), 'Asia/Shanghai');
assert.equal(parts.mmdd, '0911');
assert.equal(
isNewsMorningPageForToday(
{ slug: 'daily-news-0911' },
{ date: new Date(now), timezone: 'Asia/Shanghai' },
),
true,
);
assert.equal(
isLocalScheduleDue(
{ hour: 6, minute: 0, timezone: 'Asia/Shanghai' },
now,
1,
),
true,
);
assert.equal(
isWithinNewsMorningGenerateLeadWindow(
{
pushHour: 6,
pushMinute: 0,
generateLeadMinutes: 60,
timezone: 'Asia/Shanghai',
},
Date.UTC(2026, 8, 10, 21, 15, 0),
),
true,
);
});