From 5b2c5da945741defc29170a70dbe5fb3229ae8a2 Mon Sep 17 00:00:00 2001 From: Jingyi Date: Wed, 22 Apr 2026 22:05:31 -0700 Subject: [PATCH] test(e2e): add publish app happy path scenario (#35503) --- e2e/features/apps/publish-app.feature | 11 ++++++++ .../apps/publish-app.steps.ts | 15 ++++++++++ .../step-definitions/common/app.steps.ts | 22 +++++++++++++++ e2e/support/api.ts | 28 +++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 e2e/features/apps/publish-app.feature create mode 100644 e2e/features/step-definitions/apps/publish-app.steps.ts create mode 100644 e2e/features/step-definitions/common/app.steps.ts diff --git a/e2e/features/apps/publish-app.feature b/e2e/features/apps/publish-app.feature new file mode 100644 index 0000000000..2d002d3cb7 --- /dev/null +++ b/e2e/features/apps/publish-app.feature @@ -0,0 +1,11 @@ +@apps @authenticated @core +Feature: Publish app + + Scenario: Publish a workflow app for the first time + Given I am signed in as the default E2E admin + And a "workflow" app has been created via API + And a minimal workflow draft has been synced + When I open the app from the app list + And I open the publish panel + And I publish the app + Then the app should be marked as published diff --git a/e2e/features/step-definitions/apps/publish-app.steps.ts b/e2e/features/step-definitions/apps/publish-app.steps.ts new file mode 100644 index 0000000000..de4f5ee63f --- /dev/null +++ b/e2e/features/step-definitions/apps/publish-app.steps.ts @@ -0,0 +1,15 @@ +import type { DifyWorld } from '../../support/world' +import { Then, When } from '@cucumber/cucumber' +import { expect } from '@playwright/test' + +When('I open the publish panel', async function (this: DifyWorld) { + await this.getPage().getByRole('button', { name: 'Publish' }).first().click() +}) + +When('I publish the app', async function (this: DifyWorld) { + await this.getPage().getByRole('button', { name: /Publish Update/ }).click() +}) + +Then('the app should be marked as published', async function (this: DifyWorld) { + await expect(this.getPage().getByRole('button', { name: 'Published' })).toBeVisible({ timeout: 30_000 }) +}) diff --git a/e2e/features/step-definitions/common/app.steps.ts b/e2e/features/step-definitions/common/app.steps.ts new file mode 100644 index 0000000000..93e808e3c5 --- /dev/null +++ b/e2e/features/step-definitions/common/app.steps.ts @@ -0,0 +1,22 @@ +import type { DifyWorld } from '../../support/world' +import { Given, When } from '@cucumber/cucumber' +import { expect } from '@playwright/test' +import { createTestApp, syncMinimalWorkflowDraft } from '../../../support/api' + +Given('a {string} app has been created via API', async function (this: DifyWorld, mode: string) { + const app = await createTestApp(`E2E ${Date.now()}`, mode) + this.createdAppIds.push(app.id) + this.lastCreatedAppName = app.name +}) + +Given('a minimal workflow draft has been synced', async function (this: DifyWorld) { + const appId = this.createdAppIds.at(-1)! + await syncMinimalWorkflowDraft(appId) +}) + +When('I open the app from the app list', async function (this: DifyWorld) { + const page = this.getPage() + await page.goto('/apps') + await expect(page.getByRole('button', { name: 'Create from Blank' })).toBeVisible() + await page.getByText(this.lastCreatedAppName!).click() +}) diff --git a/e2e/support/api.ts b/e2e/support/api.ts index c6d6c98bde..7d9fd0264f 100644 --- a/e2e/support/api.ts +++ b/e2e/support/api.ts @@ -43,6 +43,34 @@ export async function createTestApp(name: string, mode = 'workflow'): Promise { + const ctx = await createApiContext() + try { + await ctx.post(`/console/api/apps/${appId}/workflows/draft`, { + data: { + graph: { + nodes: [ + { + id: '1', + type: 'custom', + position: { x: 80, y: 282 }, + data: { id: '1', type: 'start', title: 'Start', variables: [] }, + }, + ], + edges: [], + viewport: { x: 0, y: 0, zoom: 1 }, + }, + features: {}, + environment_variables: [], + conversation_variables: [], + }, + }) + } + finally { + await ctx.dispose() + } +} + export async function deleteTestApp(id: string): Promise { const ctx = await createApiContext() try {