test(web): verify plugin entry across modes and session states
This commit is contained in:
1 parent
6dccc57a5c
commit
66f00a9170
3 files changed
+52
-12
No files matched your search
@@ -412,8 +412,8 @@ describe('web e2e: agent-preset selection', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('starts one real Creator composition from Plugins with Coding Tools off and keeps the next task on Standard', async () => {
|
||||
const scaffold = await launchWebScaffold({ developerTools: false, agentPresets: { default: 'standard' } })
|
||||
it.each([false, true])('starts Creator from Plugins with Coding Tools=%s without changing drafts or defaults', async (developerTools) => {
|
||||
const scaffold = await launchWebScaffold({ developerTools, agentPresets: { default: 'standard' } })
|
||||
let browser: Browser | undefined
|
||||
try {
|
||||
browser = await chromium.launch()
|
||||
@@ -426,6 +426,9 @@ it('starts one real Creator composition from Plugins with Coding Tools off and k
|
||||
if (creator === undefined) throw new Error('Connecting the workspace did not create a Session')
|
||||
expect(scaffold.ctx.agentPresets.composedPreset(creator.ctx)).toBe('standard')
|
||||
await page.getByRole('button', { name: 'Standard mode', exact: true }).waitFor()
|
||||
const composer = page.locator('[data-composer-input][contenteditable="true"]').last()
|
||||
const draft = 'Keep this unsent plugin idea.'
|
||||
await writeComposerDraft(page, composer, draft)
|
||||
|
||||
await page.getByRole('navigation', { name: 'Global panels' }).getByRole('button', { name: 'Plugins', exact: true }).click()
|
||||
await page.getByRole('button', { name: 'Choose how to add a plugin', exact: true }).click()
|
||||
@@ -435,6 +438,8 @@ it('starts one real Creator composition from Plugins with Coding Tools off and k
|
||||
])
|
||||
const picker = page.getByTitle('Choose the agent preset for your new task', { exact: true }).filter({ hasText: 'Creator mode' })
|
||||
await picker.waitFor()
|
||||
await composer.filter({ hasText: draft }).waitFor()
|
||||
expect(await composer.innerText()).toBe(draft)
|
||||
expect(await picker.getAttribute('aria-haspopup')).toBe('menu')
|
||||
expect(await page.getByRole('dialog', { name: 'Add plugin', exact: true }).count()).toBe(0)
|
||||
expect(scaffold.ctx.sessionProjections.stateOf(creator.session, 'agentPreset')).toBe('cordis')
|
||||
@@ -444,13 +449,13 @@ it('starts one real Creator composition from Plugins with Coding Tools off and k
|
||||
expect(creator.session.snapshotEvents().some(event => event.type === 'agent-preset/selected'
|
||||
&& event.data.agentPreset === 'cordis')).toBe(true)
|
||||
expect(creator.session.snapshotEvents().some(event => event.type === 'user/message' || event.type === 'turn/start')).toBe(false)
|
||||
expect(scaffold.ctx.settings.describe().find(row => row.ns === 'ui-settings')?.value).toMatchObject({ enabled: false })
|
||||
expect(scaffold.ctx.settings.describe().find(row => row.ns === 'ui-settings')?.value).toMatchObject({ enabled: developerTools })
|
||||
expect(scaffold.ctx.agentPresets.defaultId).toBe('standard')
|
||||
|
||||
await picker.click()
|
||||
await page.getByRole('menu').waitFor()
|
||||
expect(await page.getByRole('menuitem', { name: /^Standard mode|^Creator mode/ }).count()).toBe(2)
|
||||
expect(await page.getByRole('menuitem', { name: /^PTC mode|^Minimal mode/ }).count()).toBe(0)
|
||||
expect(await page.getByRole('menuitem', { name: /^PTC mode|^Minimal mode/ }).count()).toBe(developerTools ? 2 : 0)
|
||||
await page.keyboard.press('Escape')
|
||||
const newSession = page.getByRole('button', { name: 'New session', exact: true }).filter({ hasText: 'New Session' })
|
||||
await Promise.all([page.waitForResponse('**/api/session/create'), newSession.click()])
|
||||
@@ -460,6 +465,7 @@ it('starts one real Creator composition from Plugins with Coding Tools off and k
|
||||
expect(scaffold.ctx.agentPresets.composedPreset(creator.ctx)).toBe('cordis')
|
||||
|
||||
// Close a fixture turn on the real Creator Session without requesting a model.
|
||||
await writeComposerDraft(page, composer, '')
|
||||
creator.session.append('turn/start', { turn: 1 })
|
||||
const user = creator.session.append('user/message', createUserMessage({
|
||||
content: [{ type: 'text', text: 'Creator fixture completed without a model call.' }], source: { kind: 'user' },
|
||||
@@ -480,8 +486,37 @@ it('starts one real Creator composition from Plugins with Coding Tools off and k
|
||||
await openSettings(page, 'en')
|
||||
const settings = page.getByRole('dialog', { name: 'Settings' })
|
||||
await settings.getByRole('button', { name: 'General', exact: true }).click()
|
||||
expect(await settings.getByRole('switch', { name: 'Coding Tools' }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(scaffold.ctx.settings.describe().find(row => row.ns === 'ui-settings')?.value).toMatchObject({ enabled: false })
|
||||
expect(await settings.getByRole('switch', { name: 'Coding Tools' }).getAttribute('aria-checked')).toBe(String(developerTools))
|
||||
expect(scaffold.ctx.settings.describe().find(row => row.ns === 'ui-settings')?.value).toMatchObject({ enabled: developerTools })
|
||||
expect(scaffold.ctx.agentPresets.defaultId).toBe('standard')
|
||||
await settings.getByRole('button', { name: 'Close', exact: true }).last().click()
|
||||
|
||||
// A completed source stays intact; the entry reuses the workspace's remaining blank task.
|
||||
await page.getByRole('treeitem').filter({ has: page.getByText('Creator fixture', { exact: true }) }).click()
|
||||
await page.getByText('Creator fixture completed without a model call.', { exact: true }).waitFor()
|
||||
const source = scaffold.ctx.agents.get(creator.id)
|
||||
if (source === undefined) throw new Error('The completed source Session did not reopen')
|
||||
const sourceEvents = source.session.snapshotEvents()
|
||||
await page.getByRole('navigation', { name: 'Global panels' }).getByRole('button', { name: 'Plugins', exact: true }).click()
|
||||
await page.getByRole('button', { name: 'Choose how to add a plugin', exact: true }).click()
|
||||
await Promise.all([
|
||||
page.waitForResponse('**/api/agentPresets/select'),
|
||||
page.getByRole('menuitem', { name: /^Let the agent create a plugin/ }).click(),
|
||||
])
|
||||
await picker.waitFor()
|
||||
const reentered = scaffold.ctx.agents.get(next.id)
|
||||
if (reentered === undefined) throw new Error('Creator did not reuse the blank Session')
|
||||
expect(scaffold.ctx.agentPresets.composedPreset(reentered.ctx)).toBe('cordis')
|
||||
expect(reentered.session.snapshotEvents().some(event => event.type === 'user/message' || event.type === 'turn/start')).toBe(false)
|
||||
expect(source.session.snapshotEvents()).toEqual(sourceEvents)
|
||||
|
||||
await page.reload({ waitUntil: 'load' })
|
||||
await picker.waitFor()
|
||||
const resumed = scaffold.ctx.agents.get(next.id)
|
||||
if (resumed === undefined) throw new Error('Creator did not survive the page reload')
|
||||
expect(scaffold.ctx.sessionProjections.stateOf(resumed.session, 'agentPreset')).toBe('cordis')
|
||||
expect(scaffold.ctx.agentPresets.composedPreset(resumed.ctx)).toBe('cordis')
|
||||
expect(scaffold.ctx.settings.describe().find(row => row.ns === 'ui-settings')?.value).toMatchObject({ enabled: developerTools })
|
||||
expect(scaffold.ctx.agentPresets.defaultId).toBe('standard')
|
||||
expect(tripwire.pageErrors).toEqual([])
|
||||
expect(tripwire.warnings).toEqual([])
|
||||
|
||||
@@ -832,6 +832,16 @@ describe('web e2e: plugin manager', () => {
|
||||
const dialog = page.getByRole('dialog', { name: '添加插件' })
|
||||
await dialog.waitFor({ timeout: 10_000 })
|
||||
const field = dialog.getByRole('textbox', { name: '包名或地址' })
|
||||
expect(await page.getByRole('menu').count()).toBe(0)
|
||||
await expect.poll(() => field.evaluate(element => document.activeElement === element)).toBe(true)
|
||||
await dialog.getByRole('button', { name: '关闭', exact: true }).click()
|
||||
await dialog.waitFor({ state: 'hidden' })
|
||||
await panel.getByRole('button', { name: '选择添加插件方式', exact: true }).click()
|
||||
const menu = page.getByRole('menu')
|
||||
await menu.getByRole('menuitem', { name: /^安装第三方插件/ }).click()
|
||||
await menu.waitFor({ state: 'hidden' })
|
||||
await dialog.waitFor({ state: 'visible' })
|
||||
await expect.poll(() => field.evaluate(element => document.activeElement === element)).toBe(true)
|
||||
const install = dialog.getByRole('button', { name: '安装', exact: true })
|
||||
expect(await install.isDisabled()).toBe(true)
|
||||
expect(await dialog.getByRole('note').textContent()).toContain('请确认插件来源可信')
|
||||
|
||||
@@ -80,17 +80,12 @@
|
||||
.addMenu [role='menuitem'] {
|
||||
height: 72px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
/* Keep both action icons centred beside the complete text block. */
|
||||
.addMenu [role='menuitem'] > span:first-child:has(> svg) {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.addMenu [role='menuitem'] > span:first-child:has(> svg),
|
||||
.addMenu [role='menuitem'] > span:first-child:has(> svg) > svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
Reference in new issue
Block a user