Files
memind/wechat/handlers/intent-transaction.test.mjs
T
john d58dc2a251 feat(wechat): add Intent Transaction Layer with unified task schema
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind
feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts
so reminders and automations get explicit user confirmation before persisting.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 15:59:17 +08:00

136 lines
4.3 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { handleWechatIntentTransaction } from './intent-transaction.mjs';
function createDraftStore() {
let pending = null;
return {
async getPendingDraft(userId) {
return pending?.userId === userId ? pending : null;
},
async createDraft(payload) {
pending = {
id: 'draft-1',
userId: payload.userId,
layer: payload.layer,
draftType: payload.draftType,
actionLevel: payload.actionLevel,
title: payload.title,
payload: payload.payload,
cardText: payload.cardText,
status: 'draft',
};
return pending;
},
async cancelDraft(id, userId) {
if (pending?.id === id && pending.userId === userId) pending = null;
return { id, status: 'cancelled' };
},
async markDraftCommitted(id, userId, committedRef) {
if (pending?.id === id && pending.userId === userId) {
pending = { ...pending, status: 'committed', committedRef };
}
return pending;
},
};
}
function createScheduleService() {
return {
async createItem(payload) {
return { id: 'item-1', ...payload };
},
async createReminder(payload) {
return { id: 'reminder-1', ...payload };
},
buildTodoDigestText() {
return '今天有 1 条待办。';
},
};
}
const enabledEnv = { H5_INTENT_TRANSACTION_ENABLED: '1', H5_DEFAULT_TIMEZONE: 'Asia/Shanghai' };
test('intent transaction returns null when feature disabled', async () => {
const reply = await handleWechatIntentTransaction({
intent: { agentText: '下午2点半提醒我开会', msgId: 'm1' },
user: { userId: 'user-1' },
intentDraftService: createDraftStore(),
scheduleService: createScheduleService(),
env: { H5_INTENT_TRANSACTION_ENABLED: '0' },
});
assert.equal(reply, null);
});
test('intent transaction creates action card for simple timed reminder', async () => {
const drafts = createDraftStore();
const reply = await handleWechatIntentTransaction({
intent: { agentText: '下午2点半提醒我开项目计划例会', msgId: 'm2' },
user: { userId: 'user-1' },
intentDraftService: drafts,
scheduleService: createScheduleService(),
env: enabledEnv,
});
assert.match(reply, /我准备执行/);
assert.match(reply, /确认/);
const pending = await drafts.getPendingDraft('user-1');
assert.equal(pending.draftType, 'timed_reminder');
});
test('intent transaction commits draft after user confirms', async () => {
const drafts = createDraftStore();
const scheduleService = createScheduleService();
const calls = [];
scheduleService.createItem = async (payload) => {
calls.push(['createItem', payload.title]);
return { id: 'item-1', ...payload };
};
scheduleService.createReminder = async (payload) => {
calls.push(['createReminder', payload.itemId]);
return { id: 'reminder-1', ...payload };
};
await handleWechatIntentTransaction({
intent: { agentText: '下午2点半提醒我开项目计划例会', msgId: 'm3' },
user: { userId: 'user-1' },
intentDraftService: drafts,
scheduleService,
env: enabledEnv,
});
const reply = await handleWechatIntentTransaction({
intent: { agentText: '确认', msgId: 'm4' },
user: { userId: 'user-1' },
intentDraftService: drafts,
scheduleService,
env: enabledEnv,
});
assert.match(reply, /已设置提醒/);
assert.equal(calls.length, 2);
});
test('intent transaction asks for slot fill without creating draft', async () => {
const drafts = createDraftStore();
const reply = await handleWechatIntentTransaction({
intent: { agentText: '设置提醒', msgId: 'm6' },
user: { userId: 'user-2' },
intentDraftService: drafts,
scheduleService: createScheduleService(),
env: enabledEnv,
});
assert.match(reply, /补充/);
assert.equal(await drafts.getPendingDraft('user-2'), null);
});
test('intent transaction answers query guard without creating draft', async () => {
const drafts = createDraftStore();
const reply = await handleWechatIntentTransaction({
intent: { agentText: '看看我的待办', msgId: 'm5' },
user: { userId: 'user-1' },
intentDraftService: drafts,
scheduleService: createScheduleService(),
env: enabledEnv,
});
assert.match(reply, /待办/);
assert.equal(await drafts.getPendingDraft('user-1'), null);
});