From 93a7d221edf807ff8e3826308d7e2a3e667ceca3 Mon Sep 17 00:00:00 2001 From: ZiyaZhang <199893125+ZiyaZhang@users.noreply.github.com> Date: Mon, 28 Sep 2026 06:55:46 -0700 Subject: [PATCH] test(web): align plugin menu snapshots and verify Creator flow --- apps/web/tests/agent-preset-selection.e2e.ts | 74 +++++++++++++++++++ .../plugin-config/official.expected.md | 4 +- .../plugin-manager/live-enabled.expected.md | 4 +- .../plugin-manager/loading.expected.md | 4 +- .../plugin-manager/manager.expected.md | 4 +- apps/web/tests/plugin-manager.e2e.ts | 2 +- 6 files changed, 87 insertions(+), 5 deletions(-) diff --git a/apps/web/tests/agent-preset-selection.e2e.ts b/apps/web/tests/agent-preset-selection.e2e.ts index 48f1722d7c..1c99be13a3 100644 --- a/apps/web/tests/agent-preset-selection.e2e.ts +++ b/apps/web/tests/agent-preset-selection.e2e.ts @@ -401,3 +401,77 @@ describe('web e2e: agent-preset selection', () => { expect(tripwire.warnings).toEqual([]) }) }) + +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' } }) + let browser: Browser | undefined + try { + browser = await chromium.launch() + const page = await newEnglishPage(browser) + const tripwire = watchConsole(page) + onTestFailed(() => saveFailureShot(page, 'web-e2e-plugin-creator')) + await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' }) + await connectFreshWorkspace(page, scaffold.workspaceCwd) + const creator = scaffold.ctx.agents.list()[0] + if (creator === undefined) throw new Error('Connecting the workspace did not create a Session') + expect(scaffold.ctx.agentPresets.composedPreset(creator.ctx)).toBe('standard') + expect(await page.getByRole('button', { name: 'Standard mode', exact: true }).count()).toBe(0) + + 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 page.getByRole('menuitem', { name: /^Let the agent create a plugin/ }).click() + const label = page.getByRole('button', { name: 'Mode details: Creator mode', exact: true }) + await label.waitFor() + expect(await label.getAttribute('aria-haspopup')).toBe('dialog') + expect(await page.getByRole('dialog', { name: 'Add plugin', exact: true }).count()).toBe(0) + await expect.poll(() => scaffold.ctx.sessionProjections.stateOf(creator.session, 'agentPreset')).toBe('cordis') + expect(scaffold.ctx.agentPresets.composedPreset(creator.ctx)).toBe('cordis') + expect(scaffold.ctx.tools.schemas(creator).map(tool => tool.name)) + .toEqual(expect.arrayContaining(['cordis_inspect_list', 'cordis_inspect_query', 'plugin_manager'])) + 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.agentPresets.defaultId).toBe('standard') + + await label.click() + await page.getByRole('dialog', { name: 'Creator mode', exact: true }).waitFor() + 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()]) + await label.waitFor() + // New Session deliberately reuses the unstarted draft; it is not proof of a new default. + expect(scaffold.ctx.agents.list().map(agent => agent.id)).toEqual([creator.id]) + expect(scaffold.ctx.agentPresets.composedPreset(creator.ctx)).toBe('cordis') + + // Close a fixture turn on the real Creator Session without requesting a model. + 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' }, + }), { surfaceOp: 'append' }) + creator.session.append('session/title', { title: 'Creator fixture', messageSeqs: [user.seq], source: { kind: 'fallback' } }) + creator.session.append('turn/end', { turn: 1, reason: { kind: 'completed' } }) + await scaffold.ctx.sessions.flush(creator.session) + await page.getByText('Creator fixture completed without a model call.', { exact: true }).waitFor() + await newSession.click() + await expect.poll(() => scaffold.ctx.agents.list().find(agent => agent.id !== creator.id)).toBeDefined() + const next = scaffold.ctx.agents.list().find(agent => agent.id !== creator.id)! + expect(next.id).not.toBe(creator.id) + expect(next.session.header.agentPreset).toBe('standard') + expect(scaffold.ctx.sessionProjections.stateOf(next.session, 'agentPreset')).toBe('standard') + expect(scaffold.ctx.agentPresets.composedPreset(next.ctx)).toBe('standard') + expect(scaffold.ctx.sessionProjections.stateOf(creator.session, 'agentPreset')).toBe('cordis') + await expect.poll(() => label.count()).toBe(0) + 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(scaffold.ctx.agentPresets.defaultId).toBe('standard') + expect(tripwire.pageErrors).toEqual([]) + expect(tripwire.warnings).toEqual([]) + } finally { + await browser?.close() + await scaffold.close() + } +}) diff --git a/apps/web/tests/expected/plugin-config/official.expected.md b/apps/web/tests/expected/plugin-config/official.expected.md index 3906b58624..f4b2293eb0 100644 --- a/apps/web/tests/expected/plugin-config/official.expected.md +++ b/apps/web/tests/expected/plugin-config/official.expected.md @@ -2,7 +2,9 @@ - text: 安装、启用和配置插件 - button "插件说明" - button "刷新" -- button "添加插件" +- group "添加插件": + - button "添加插件" + - button "选择添加插件方式" - heading "官方" [level=3] - text: "8" - list: diff --git a/apps/web/tests/expected/plugin-manager/live-enabled.expected.md b/apps/web/tests/expected/plugin-manager/live-enabled.expected.md index 23d74b2077..fa9fd12631 100644 --- a/apps/web/tests/expected/plugin-manager/live-enabled.expected.md +++ b/apps/web/tests/expected/plugin-manager/live-enabled.expected.md @@ -2,7 +2,9 @@ - text: 安装、启用和配置插件 - button "插件说明" - button "刷新" -- button "添加插件" +- group "添加插件": + - button "添加插件" + - button "选择添加插件方式" - heading "官方" [level=3] - text: "8" - list: diff --git a/apps/web/tests/expected/plugin-manager/loading.expected.md b/apps/web/tests/expected/plugin-manager/loading.expected.md index 9c6fea0d43..4cf8d9ea23 100644 --- a/apps/web/tests/expected/plugin-manager/loading.expected.md +++ b/apps/web/tests/expected/plugin-manager/loading.expected.md @@ -2,7 +2,9 @@ - text: 安装、启用和配置插件 - button "插件说明" - button "刷新" [disabled] -- button "添加插件" [disabled] +- group "添加插件": + - button "添加插件" [disabled] + - button "选择添加插件方式" [disabled] - status "正在读取插件…" 1680px: 4 rows; page/group headers, rows, icons, text lines and blank action spaces align within 0.1px diff --git a/apps/web/tests/expected/plugin-manager/manager.expected.md b/apps/web/tests/expected/plugin-manager/manager.expected.md index 7e126cd61b..89ca0d1416 100644 --- a/apps/web/tests/expected/plugin-manager/manager.expected.md +++ b/apps/web/tests/expected/plugin-manager/manager.expected.md @@ -2,7 +2,9 @@ - text: 安装、启用和配置插件 - button "插件说明" - button "刷新" -- button "添加插件" +- group "添加插件": + - button "添加插件" + - button "选择添加插件方式" - heading "官方" [level=3] - text: "8" - list: diff --git a/apps/web/tests/plugin-manager.e2e.ts b/apps/web/tests/plugin-manager.e2e.ts index b89279d173..8f55363b81 100644 --- a/apps/web/tests/plugin-manager.e2e.ts +++ b/apps/web/tests/plugin-manager.e2e.ts @@ -124,7 +124,7 @@ describe('web e2e: plugin manager', () => { expect(await skeleton.getAttribute('aria-label')).toBe('正在读取插件…') expect(await panel.getAttribute('aria-busy')).toBe('true') const actions = panel.locator(':scope > header > div:last-child button') - expect(await actions.count()).toBe(2) + expect(await actions.count()).toBe(3) for (const action of await actions.all()) expect(await action.isDisabled()).toBe(true) expect(await panel.getByRole('button', { name: '插件说明' }).isEnabled()).toBe(true) const loadingAria = await captureStableAria(probe, '[data-plugin-panel]', scaffold.workspaceCwd)