62caf4134b
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>
142 lines
4.1 KiB
JavaScript
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,
|
|
);
|
|
});
|