dsh-im-ops/test/channels/weixin/stores.test.mjs
2026-08-15 15:40:53 +08:00

62 lines
2.5 KiB
JavaScript

import assert from 'node:assert/strict';
import { mkdtemp, readFile, stat, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import {
deriveWeixinBotIdentity,
WeixinConfigStore,
} from '../../../src/channels/weixin/config-store.mjs';
import { WeixinStateStore } from '../../../src/channels/weixin/state-store.mjs';
test('config store persists non-secret account facts atomically with restrictive permissions', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-weixin-config-'));
const path = join(root, 'nested', 'config.json');
const store = await new WeixinConfigStore(path).load();
const identity = deriveWeixinBotIdentity('account@im.bot');
await store.save({
...identity,
accountId: 'account@im.bot',
ownerUserId: 'owner-user',
baseUrl: 'https://ilinkai.weixin.qq.com',
createdAt: '2026-08-15T00:00:00.000Z',
});
const raw = await readFile(path, 'utf8');
assert.match(raw, /"accountId": "account@im\.bot"/);
assert.doesNotMatch(raw, /bot_token|secret-token/);
assert.equal((await stat(path)).mode & 0o777, 0o600);
assert.deepEqual((await new WeixinConfigStore(path).load()).list(), store.list());
});
test('config store rejects duplicate or tampered identities', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-weixin-invalid-'));
const path = join(root, 'config.json');
await writeFile(path, JSON.stringify({
version: 1,
accounts: [{
botId: 'wx_000000000000000000000000',
accountId: 'real@im.bot',
tokenRef: 'DSH_WEIXIN_BOT_TOKEN_000000000000000000000000',
ownerUserId: 'owner',
baseUrl: 'https://ilinkai.weixin.qq.com',
}],
}));
await assert.rejects(new WeixinConfigStore(path).load(), /invalid account data/);
});
test('state store retains sessions, deduplication, and the getUpdates cursor', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-weixin-state-'));
const path = join(root, 'account', 'state.json');
const state = await new WeixinStateStore(path).load();
await state.setSession('p2p:user', 'session-1');
await state.markSeen('message-1');
await state.setGetUpdatesBuf('cursor-2');
const restored = await new WeixinStateStore(path).load();
assert.equal(restored.sessionFor('p2p:user'), 'session-1');
assert.equal(restored.hasSeen('message-1'), true);
assert.equal(restored.getUpdatesBuf(), 'cursor-2');
assert.equal((await stat(path)).mode & 0o777, 0o600);
});