test(skill): snapshot invocation policy surfaces

This commit is contained in:
Tianyi Cui
2026-07-29 21:58:21 +08:00
parent 80ab0aa548
commit 7ff1246842
6 changed files with 146 additions and 9 deletions

View File

@@ -2,8 +2,9 @@
// Assembled keyless snapshot of the slash/input/session convergence under the
// agent-parity model: the New Session view state locks the composer until a
// Workspace is picked (connectWorkspace materializes the full Session+Agent),
// the '/' menu serves the session's wire command catalog (sessions are always
// agent-backed — no draft/materialized split), a leadingInput command claims,
// the '/' menu serves the session's filtered skill and wire command catalogs
// (sessions are always agent-backed — no draft/materialized split), a skill
// pick inserts its reference, a leadingInput command claims,
// submits over the wire, and notices its result, and the SAME composer
// textarea then carries the first plain send, whose ACCEPTANCE (not attempt)
// flips blank and surfaces the session in lists. This is the user-visible
@@ -114,7 +115,7 @@ async function typeComposer(composer: HTMLTextAreaElement, value: string): Promi
await waitFor(() => { expect(composer.value).toBe(value) })
}
it('locked view state, connectWorkspace unlock, /echo claim chain, and blank-on-acceptance ride one resident composer', async () => {
it('locked view state, skill discovery, /echo claim chain, and blank-on-acceptance ride one resident composer', async () => {
boot('?fixture=empty')
// View state: no session entity — the composer renders locked; only the
@@ -140,6 +141,18 @@ it('locked view state, connectWorkspace unlock, /echo claim chain, and blank-on-
)
expect(composer.disabled).toBe(false)
// The built skill plugin prewarms the session-addressed catalog; querying
// it exercises the assembled discovery path and picking inserts the literal
// reference into the resident composer.
await typeComposer(composer, '/fixture')
const skillMenu = await screen.findByRole('listbox', { name: 'Trigger suggestions' })
const skillOption = await within(skillMenu).findByRole('option', { name: /fixture-demo/ })
const skillMenuText = visibleText(skillMenu)
fireEvent.mouseDown(skillOption)
await waitFor(() => { expect(composer.value).toBe('/fixture-demo ') })
const pickedSkill = composer.value
await typeComposer(composer, '')
// '/' opens the menu with the session's wire command catalog (the session
// is agent-backed from birth — the catalog is the single-address list).
await typeComposer(composer, '/')
@@ -178,6 +191,8 @@ it('locked view state, connectWorkspace unlock, /echo claim chain, and blank-on-
menuHadEcho: menuText.includes('echo'),
menuHadCompact: menuText.includes('compact'),
composerSurvivedConversion: after === before,
skillMenuHadFixtureDemo: skillMenuText.includes('fixture-demo'),
skillPickInserted: pickedSkill,
sessionListed: visibleText(within(tree).getByText('1 session').closest('[role="treeitem"]')!),
}).toMatchInlineSnapshot(`
{
@@ -185,6 +200,8 @@ it('locked view state, connectWorkspace unlock, /echo claim chain, and blank-on-
"menuHadCompact": true,
"menuHadEcho": true,
"sessionListed": "nova1 session",
"skillMenuHadFixtureDemo": true,
"skillPickInserted": "/fixture-demo ",
}
`)
})