mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 00:33:20 +08:00
feat: support limiting session list results
This commit is contained in:
parent
52deb872aa
commit
37ec6abb06
16 changed files with 373 additions and 225 deletions
|
|
@ -4739,6 +4739,50 @@ test('/sessions alias uses the interactive session list and paginates across 25
|
|||
assert.equal(useActionsFromCard(page1)[0], 'session-11');
|
||||
});
|
||||
|
||||
test('Feishu session limit caps card pages and survives paging and watch refresh', async () => {
|
||||
const { state } = await watchStoreFixture();
|
||||
const work = realpathSync(tmpdir());
|
||||
const sessions = Array.from({ length: 25 }, (_, index) => ({
|
||||
sessionId: `limited-card-${String(index + 1).padStart(2, '0')}`,
|
||||
title: `Limited Card ${index + 1}`,
|
||||
lastSeq: index,
|
||||
}));
|
||||
const harness = watchHarness({ current: work, sessionsByWorkspace: { [work]: sessions } });
|
||||
const sent = [];
|
||||
const patches = [];
|
||||
const bridge = new FeishuHarnessBridge({
|
||||
client: cardClient(
|
||||
async (outgoing) => sent.push(outgoing),
|
||||
async (request) => patches.push(request),
|
||||
),
|
||||
channel: {},
|
||||
harness,
|
||||
state,
|
||||
status: bridgeStatus(),
|
||||
allowedSenderOpenIds: new Set(['ou_owner']),
|
||||
});
|
||||
|
||||
await bridge.accept(event('limited-card-open', '/sessionlist --limit 12', { senderOpenId: 'ou_owner' }));
|
||||
await bridge.waitForIdle();
|
||||
const page0 = cards(sent).at(-1).content;
|
||||
assert.equal(useActionsFromCard(page0).length, 10);
|
||||
assert.match(page0.body.elements[0].text.content, /共 \*\*12\*\* 个会话/);
|
||||
|
||||
await bridge.onCardAction(cardActionEvent('om_card_1', 'sessions:1', 'ou_owner'));
|
||||
await bridge.waitForIdle();
|
||||
const page1 = JSON.parse(patches.at(-1).data.content);
|
||||
assert.deepEqual(useActionsFromCard(page1), ['limited-card-11', 'limited-card-12']);
|
||||
|
||||
await bridge.onCardAction(cardActionEvent('om_card_1', 'watch:limited-card-11', 'ou_owner'));
|
||||
await bridge.waitForIdle();
|
||||
const refreshed = JSON.parse(patches.at(-1).data.content);
|
||||
assert.deepEqual(useActionsFromCard(refreshed), ['limited-card-11', 'limited-card-12']);
|
||||
assert.equal(
|
||||
buttonsFromCard(refreshed).some((button) => callbackAction(button) === 'unwatch:limited-card-11'),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('number replies on a later session page use page-local labels', async () => {
|
||||
const fixture = stateFixture();
|
||||
const sent = [];
|
||||
|
|
|
|||
|
|
@ -1149,6 +1149,51 @@ test('/sessionlist supports the current workspace, list numbers, and absolute pa
|
|||
assert.equal(workspaceListCalls, 1, 'only numeric selection needs the workspace registry order');
|
||||
});
|
||||
|
||||
test('/sessionlist and /sessions accept a one-off --limit for the current workspace', async (t) => {
|
||||
const { defaultWorkspace } = await fixture(t);
|
||||
const sessions = Array.from({ length: 4 }, (_, index) => ({
|
||||
sessionId: `limited-session-${index + 1}`,
|
||||
title: `Limited Session ${index + 1}`,
|
||||
archived: false,
|
||||
summaryAvailable: true,
|
||||
}));
|
||||
let listCalls = 0;
|
||||
const harness = {
|
||||
currentWorkspace() { return defaultWorkspace; },
|
||||
async listWorkspaceSessions(workspace) {
|
||||
listCalls += 1;
|
||||
return { workspace, sessions };
|
||||
},
|
||||
};
|
||||
|
||||
const limited = await runWorkspaceCommand('/sessionlist --limit 2', harness);
|
||||
assert.match(limited.message, /会话(2):/);
|
||||
assert.match(limited.message, /limited-session-1/);
|
||||
assert.match(limited.message, /limited-session-2/);
|
||||
assert.doesNotMatch(limited.message, /limited-session-3|limited-session-4/);
|
||||
|
||||
const alias = await runWorkspaceCommand('/SESSIONS --LIMIT 1', harness);
|
||||
assert.match(alias.message, /会话(1):/);
|
||||
assert.match(alias.message, /limited-session-1/);
|
||||
assert.doesNotMatch(alias.message, /limited-session-2/);
|
||||
|
||||
const oversized = await runWorkspaceCommand('/sessionlist --limit 99', harness);
|
||||
assert.match(oversized.message, /会话(4):/);
|
||||
assert.equal(listCalls, 3);
|
||||
|
||||
for (const command of [
|
||||
'/sessionlist --limit',
|
||||
'/sessionlist --limit 0',
|
||||
'/sessionlist --limit -1',
|
||||
'/sessionlist --limit many',
|
||||
'/sessionlist --limit 2 1',
|
||||
]) {
|
||||
const result = await runWorkspaceCommand(command, harness);
|
||||
assert.match(result.message, /\/sessionlist --limit N/);
|
||||
}
|
||||
assert.equal(listCalls, 3, 'invalid limits must not query Harness');
|
||||
});
|
||||
|
||||
test('/sessions reuses /sessionlist parsing for current, numbered, and absolute workspaces', async (t) => {
|
||||
const { defaultWorkspace, alternateWorkspace } = await fixture(t);
|
||||
const calls = [];
|
||||
|
|
@ -1332,6 +1377,7 @@ test('all nine channel bridge families advertise and fan out workspace command r
|
|||
const source = await readFile(new URL(file, import.meta.url), 'utf8');
|
||||
assert.match(source, /\/workspacelist 列出工作区绝对路径/);
|
||||
assert.match(source, /\/sessionlist 或 \/sessions \[工作区序号或绝对路径\] 列出会话 ID 和标题/);
|
||||
assert.match(source, /\/sessionlist --limit N 仅列出当前工作区前 N 个会话/);
|
||||
assert.match(source, /workspaceCommand\.messages \?\? \[workspaceCommand\.message\]/);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue