import type { Page } from '@playwright/test' import type { DifyWorld } from '../../support/world' import { Then, When } from '@cucumber/cucumber' import { expect } from '@playwright/test' import { getAgentComposerDraft } from '../../agent-v2/support/agent' import { agentBuilderExpectedTokens } from '../../agent-v2/support/agent-builder-resources' import { getCurrentAgentId, getDialog, getWebAppCard } from './access-point-helpers' const WEB_APP_RUNTIME_RESPONSE_STEP_TIMEOUT_MS = 180_000 const getWebAppMessageInput = (webAppPage: Page) => webAppPage.getByPlaceholder(/^Talk to /).last() const recordComposerDraftSnapshot = async (world: DifyWorld) => { const draft = await getAgentComposerDraft(getCurrentAgentId(world)) world.agentBuilder.accessPoint.composerDraftSnapshot = JSON.stringify(draft.agent_soul ?? {}) } Then('I should see the Agent v2 Web app access URL', async function (this: DifyWorld) { const webAppCard = getWebAppCard(this) await expect(webAppCard.getByRole('heading', { name: 'Web app' })).toBeVisible() await expect(webAppCard.getByText('Access URL')).toBeVisible() await expect(webAppCard.getByLabel('Copy access URL')).toBeEnabled() await expect(webAppCard.getByRole('link', { name: 'Launch' })).toBeVisible() }) When('I copy the Agent v2 Web app access URL', async function (this: DifyWorld) { await recordComposerDraftSnapshot(this) await getWebAppCard(this).getByLabel('Copy access URL').click() }) Then('the Agent v2 Web app access URL should show it was copied', async function (this: DifyWorld) { await expect(this.getPage().getByLabel('Copied')).toBeVisible() }) When('I launch the Agent v2 Web app', async function (this: DifyWorld) { await recordComposerDraftSnapshot(this) const launchLink = getWebAppCard(this).getByRole('link', { name: 'Launch' }) const href = await launchLink.getAttribute('href') if (!href) throw new Error('Agent v2 Web app Launch link does not expose an href.') const [webAppPage] = await Promise.all([this.getPage().waitForEvent('popup'), launchLink.click()]) this.agentBuilder.accessPoint.webAppURL = href this.agentBuilder.accessPoint.webAppPage = webAppPage }) When('I open the Agent v2 Web app URL', async function (this: DifyWorld) { const webAppURL = this.agentBuilder.accessPoint.webAppURL if (!webAppURL) throw new Error('No Agent v2 Web app URL was recorded.') if (!this.context) throw new Error('Playwright browser context has not been initialized.') const webAppPage = await this.context.newPage() await webAppPage.goto(webAppURL) this.agentBuilder.accessPoint.webAppPage = webAppPage }) When('I send an E2E message in the Agent v2 Web app', async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage if (!webAppPage) throw new Error('No Agent v2 Web app page was opened.') const messageInput = getWebAppMessageInput(webAppPage) await expect(messageInput).toBeEditable({ timeout: 30_000 }) await messageInput.fill('Please reply with the test success marker.') await messageInput.press('Enter') }) Then('the Agent v2 Web app should open in a new tab', async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage const webAppURL = this.agentBuilder.accessPoint.webAppURL if (!webAppPage || !webAppURL) throw new Error('No Agent v2 Web app page was opened.') await expect(webAppPage).toHaveURL(webAppURL) await expect(getWebAppMessageInput(webAppPage)).toBeEditable({ timeout: 30_000 }) await webAppPage.close() this.agentBuilder.accessPoint.webAppPage = undefined this.agentBuilder.accessPoint.webAppURL = undefined }) Then( 'the Agent v2 Web app response should include the updated E2E marker', { timeout: WEB_APP_RUNTIME_RESPONSE_STEP_TIMEOUT_MS }, async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage if (!webAppPage) throw new Error('No Agent v2 Web app page was opened.') await expect(webAppPage.getByText(agentBuilderExpectedTokens.updatedAgentReply)).toBeVisible({ timeout: 120_000, }) }, ) Then( 'the Agent v2 Web app response should include the normal E2E marker', { timeout: WEB_APP_RUNTIME_RESPONSE_STEP_TIMEOUT_MS }, async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage if (!webAppPage) throw new Error('No Agent v2 Web app page was opened.') await expect(webAppPage.getByText(agentBuilderExpectedTokens.agentReply)).toBeVisible({ timeout: 120_000, }) }, ) Then( 'the Agent v2 Web app response should not include the updated E2E marker', async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage if (!webAppPage) throw new Error('No Agent v2 Web app page was opened.') await expect( webAppPage.getByText(agentBuilderExpectedTokens.updatedAgentReply), ).not.toBeVisible() }, ) When('I close the Agent v2 Web app', async function (this: DifyWorld) { const webAppPage = this.agentBuilder.accessPoint.webAppPage if (!webAppPage) throw new Error('No Agent v2 Web app page was opened.') await webAppPage.close() this.agentBuilder.accessPoint.webAppPage = undefined }) When('I open Agent v2 Embedded configuration', async function (this: DifyWorld) { await recordComposerDraftSnapshot(this) await getWebAppCard(this).getByRole('button', { name: 'Embedded' }).click() }) Then('I should see the Agent v2 Embedded configuration dialog', async function (this: DifyWorld) { const dialog = getDialog(this, 'Embed on website') await expect(dialog).toBeVisible() await expect(dialog.getByText('Embed on website')).toBeVisible() await expect(dialog.getByText(/iframe|script/i)).toBeVisible() }) When('I open Agent v2 Web app customization', async function (this: DifyWorld) { await recordComposerDraftSnapshot(this) await getWebAppCard(this).getByRole('button', { name: 'Custom Frontend' }).click() }) Then('I should see the Agent v2 Web app customization dialog', async function (this: DifyWorld) { const dialog = getDialog(this, 'Custom Frontend') await expect(dialog).toBeVisible() await expect(dialog.getByText('Custom Frontend')).toBeVisible() await expect(dialog.getByText(/NEXT_PUBLIC_APP_ID|NEXT_PUBLIC_API_URL/)).toBeVisible() }) When('I open Agent v2 Web app settings', async function (this: DifyWorld) { await recordComposerDraftSnapshot(this) await getWebAppCard(this).getByRole('button', { name: 'Branding' }).click() }) Then('I should see the Agent v2 Web app settings dialog', async function (this: DifyWorld) { const dialog = getDialog(this, 'Branding') await expect(dialog).toBeVisible() await expect(dialog.getByRole('heading', { name: 'Branding' })).toBeVisible() await expect(dialog.getByText('web app Name')).toBeVisible() await expect(dialog.getByText('web app Description')).toBeVisible() }) Then( 'the current Agent v2 orchestration draft should be unchanged', async function (this: DifyWorld) { const snapshot = this.agentBuilder.accessPoint.composerDraftSnapshot if (!snapshot) throw new Error('No Agent v2 orchestration draft snapshot was recorded.') const draft = await getAgentComposerDraft(getCurrentAgentId(this)) expect(JSON.stringify(draft.agent_soul ?? {})).toBe(snapshot) }, )