-
Notifications
You must be signed in to change notification settings - Fork 538
[Test] Web acceptance stability #4506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
85d05b6
58e6bcb
efe400d
b0b48f1
6d4e8be
9caa9c0
9e70931
bfb21bf
8bb2e27
c576690
c262170
e19c844
3f1ff3d
1ac50c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import {test} from "@agenta/web-tests/tests/fixtures/base.fixture" | ||
| import useApiTests from "@agenta/oss/tests/playwright/10-use-api" | ||
|
|
||
| test.describe("Registry: use API snippets", useApiTests) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import useApiTests from "./acceptance/use-api" | ||
|
|
||
| export default useApiTests |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Tests: use-api/use-api.spec.ts -> use-api/index.ts | ||
| # RTM IDs: WEB-ACC-USEAPI-001, WEB-ACC-USEAPI-002 | ||
| # Tags: @scope:deployment @coverage:light @path:happy @speed:fast | ||
| # | ||
| # Implementation notes: | ||
| # - Variant mode: navigate to /apps/{id}/variants, click "Use API" (primary button) | ||
| # → DeploymentsDrawer opens in mode="variant" rendering VariantUseApiContent | ||
| # → Fetch Prompt/Config snippet uses application_variant_ref (variant-keyed endpoint) | ||
| # → Invoke LLM snippet uses axios.post to the variant invocation URL | ||
| # - Deployment mode: navigate to /apps/{id}/variants?tab=deployments&selectedEnvName=development | ||
| # → click "Use API" (primary button in the deployments tab header) | ||
| # → DeploymentsDrawer opens in mode="deployment" rendering UseApiContent | ||
| # → Fetch Prompt/Config snippet uses environment_ref (environment-keyed endpoint) | ||
| # → Invoke LLM snippet uses axios.post to the environment invocation URL | ||
| # - Both tests assert TypeScript tab only (Python and cURL are separate language concerns). | ||
|
|
||
| Feature: Registry Use API — TypeScript snippets | ||
| As a user | ||
| I want to view TypeScript code snippets for calling my app via API | ||
| So that I can integrate Agenta into my TypeScript project | ||
|
|
||
| Background: | ||
| Given the user is authenticated | ||
| And a completion app with at least one variant exists | ||
|
|
||
| @light @happy @scope:deployment @speed:fast | ||
| Scenario: Variant TypeScript snippet shows application_variant_ref in Fetch section | ||
| Given the user is on the Variants registry page | ||
| When the user opens the Use API drawer | ||
| And the user selects the TypeScript tab | ||
| Then the Fetch Prompt/Config section displays the variant TypeScript snippet | ||
| And the Invoke LLM section displays a TypeScript axios snippet | ||
|
|
||
| @light @happy @scope:deployment @speed:fast | ||
| Scenario: Deployment TypeScript snippet shows environment_ref in Fetch section | ||
| Given the user is on the Deployments registry page for the Development environment | ||
| When the user opens the Use API drawer | ||
| And the user selects the TypeScript tab | ||
| Then the Fetch Prompt/Config section displays the deployment TypeScript snippet | ||
| And the Invoke LLM section displays a TypeScript axios snippet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,20 +18,8 @@ import {expectAuthenticatedSession} from "../utils/auth" | |
| import {createScenarios} from "../utils/scenarios" | ||
| import {buildAcceptanceTags} from "../utils/tags" | ||
|
|
||
| interface WorkflowRevision { | ||
| id: string | ||
| workflow_id?: string | null | ||
| version?: number | null | ||
| } | ||
|
|
||
| interface WorkflowRevisionsResponse { | ||
| workflow_revisions: WorkflowRevision[] | ||
| count?: number | ||
| } | ||
|
|
||
| interface PromptRegistryApiHelpers { | ||
| getApp: (slug: string) => Promise<{id: string}> | ||
| waitForApiResponse: <T>(options: {route: string; method: string}) => Promise<T> | ||
| } | ||
|
|
||
| interface PromptRegistryUiHelpers { | ||
|
|
@@ -62,67 +50,41 @@ const getCompletionAppId = async (apiHelpers: { | |
| const openWorkflowRevisionsPage = async ( | ||
| page: Page, | ||
| uiHelpers: PromptRegistryUiHelpers, | ||
| apiHelpers: PromptRegistryApiHelpers, | ||
| appId: string, | ||
| ) => { | ||
| const basePath = getProjectScopedBasePath(page) | ||
| const revisionsResponsePromise = apiHelpers.waitForApiResponse<WorkflowRevisionsResponse>({ | ||
| route: "/api/workflows/revisions/query", | ||
| method: "POST", | ||
| }) | ||
|
|
||
| await page.goto(`${basePath}/apps/${appId}/variants`, { | ||
| waitUntil: "domcontentloaded", | ||
| }) | ||
| await uiHelpers.expectPath(`/apps/${appId}/variants`) | ||
|
|
||
| return await revisionsResponsePromise | ||
| const revisionsRadio = page.getByRole("radio", {name: "Revisions"}) | ||
| const revisionsControl = page | ||
| .locator(".ant-radio-button-wrapper") | ||
| .filter({hasText: "Revisions"}) | ||
| .first() | ||
| await expect(revisionsControl).toBeVisible({timeout: 15000}) | ||
| if (!(await revisionsRadio.isChecked())) { | ||
| await revisionsControl.click() | ||
| } | ||
|
Comment on lines
+62
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard
🛡️ Proposed fix- const revisionsRadio = page.getByRole("radio", {name: "Revisions"})
+ const revisionsRadio = page.getByRole("radio", {name: "Revisions"}).first() |
||
| } | ||
|
|
||
| const openFirstPublishedWorkflowRevision = async ( | ||
| page: Page, | ||
| revisionsResponse: WorkflowRevisionsResponse, | ||
| ) => { | ||
| const revisions = revisionsResponse.workflow_revisions.filter( | ||
| (revision) => (revision.version ?? 0) > 0, | ||
| ) | ||
|
|
||
| test.skip(revisions.length === 0, "No workflow revisions found in registry") | ||
|
|
||
| // The app may accumulate revisions across test runs, and the table uses | ||
| // virtual scrolling — so a specific revision ID from the API response may | ||
| // not be rendered if it is scrolled out of the viewport. Instead poll for | ||
| // ANY visible published revision row and click whichever appears first. | ||
| const publishedRevisionIds = new Set(revisions.map((r) => r.id)) | ||
| let foundRevisionId: string | null = null | ||
|
|
||
| await expect | ||
| .poll( | ||
| async () => { | ||
| const rows = page.locator("[data-row-key]") | ||
| const count = await rows.count() | ||
| for (let i = 0; i < count; i++) { | ||
| const row = rows.nth(i) | ||
| const key = await row.getAttribute("data-row-key").catch(() => null) | ||
| if ( | ||
| key && | ||
| publishedRevisionIds.has(key) && | ||
| (await row.isVisible().catch(() => false)) | ||
| ) { | ||
| foundRevisionId = key | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| }, | ||
| {timeout: 30000}, | ||
| ) | ||
| .toBe(true) | ||
| const openFirstPublishedWorkflowRevision = async (page: Page, appId: string) => { | ||
| const versionLabel = page.getByText(/^v[1-9]\d*$/).first() | ||
| await expect(versionLabel).toBeVisible({timeout: 30000}) | ||
| await versionLabel.click() | ||
|
|
||
| const row = page.locator(`[data-row-key="${foundRevisionId}"]`).first() | ||
| await row.click() | ||
| await page.waitForURL( | ||
| (url) => | ||
| url.pathname.endsWith(`/apps/${appId}/variants`) && | ||
| Boolean(url.searchParams.get("revisionId")), | ||
| {timeout: 15000}, | ||
| ) | ||
|
|
||
| return foundRevisionId! | ||
| const revisionId = new URL(page.url()).searchParams.get("revisionId") | ||
| expect(revisionId).toBeTruthy() | ||
| return revisionId! | ||
| } | ||
|
|
||
| const expectWorkflowRevisionDrawer = async (page: Page, appId: string, revisionId: string) => { | ||
|
|
@@ -176,7 +138,6 @@ const promptRegistryTests = () => { | |
| async ({page, uiHelpers, apiHelpers}) => { | ||
| let appId = "" | ||
| let revisionId = "" | ||
| let revisionsResponse: WorkflowRevisionsResponse | null = null | ||
| let workflowRevisionDrawer: ReturnType<typeof page.locator> | null = null | ||
|
|
||
| await scenarios.given("the user is authenticated", async () => { | ||
|
|
@@ -190,19 +151,14 @@ const promptRegistryTests = () => { | |
| await scenarios.and( | ||
| "the user is on the workflow revisions page for that app", | ||
| async () => { | ||
| revisionsResponse = await openWorkflowRevisionsPage( | ||
| page, | ||
| uiHelpers, | ||
| apiHelpers, | ||
| appId, | ||
| ) | ||
| await openWorkflowRevisionsPage(page, uiHelpers, appId) | ||
| }, | ||
| ) | ||
|
|
||
| await scenarios.when( | ||
| "the user opens the first published workflow revision", | ||
| async () => { | ||
| revisionId = await openFirstPublishedWorkflowRevision(page, revisionsResponse!) | ||
| revisionId = await openFirstPublishedWorkflowRevision(page, appId) | ||
| }, | ||
| ) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the email input timeout consistent in both code paths.
The email input visibility check uses a 20-second timeout inside the retry loop (line 70) but only a 10-second timeout in the fallback path (line 75). This inconsistency could cause the fallback to fail prematurely if the modal opens on the second attempt but the email input takes 11-19 seconds to render.
🔧 Proposed fix to unify timeout
📝 Committable suggestion