diff --git a/test/automation/src/positron/positronEditor.ts b/test/automation/src/positron/positronEditor.ts index b2adbaea6cc..91a719b84c3 100644 --- a/test/automation/src/positron/positronEditor.ts +++ b/test/automation/src/positron/positronEditor.ts @@ -3,7 +3,7 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ -import { expect } from '@playwright/test'; +import { expect, FrameLocator, Locator } from '@playwright/test'; import { Code } from '../code'; // currently a dupe of declaration in ../editor.ts but trying not to modifiy that file @@ -11,9 +11,21 @@ const EDITOR = (filename: string) => `.monaco-editor[data-uri$="${filename}"]`; const CURRENT_LINE = '.view-overlays .current-line'; const PLAY_BUTTON = '.codicon-play'; +const OUTER_FRAME = '.webview'; +const INNER_FRAME = '#active-frame'; export class PositronEditor { + viewerFrame = this.code.driver.page.frameLocator(OUTER_FRAME).frameLocator(INNER_FRAME); + + getEditorViewerLocator(locator: string,): Locator { + return this.viewerFrame.locator(locator); + } + + getEditorViewerFrame(): FrameLocator { + return this.viewerFrame; + } + constructor(private code: Code) { } async pressPlay(): Promise { @@ -21,7 +33,7 @@ export class PositronEditor { // await appearance and disappearance of the toast await expect(this.code.driver.page.locator('.notifications-toasts')).toBeVisible({ timeout: 30000 }); - await expect(this.code.driver.page.locator('.notifications-toasts')).not.toBeVisible({ timeout: 30000 }); + await expect(this.code.driver.page.locator('.notifications-toasts')).not.toBeVisible({ timeout: 50000 }); } async pressToLine(filename: string, lineNumber: number, press: string): Promise { diff --git a/test/automation/src/positron/positronViewer.ts b/test/automation/src/positron/positronViewer.ts index 4464ccdd7ad..2a90a16ae53 100644 --- a/test/automation/src/positron/positronViewer.ts +++ b/test/automation/src/positron/positronViewer.ts @@ -33,6 +33,15 @@ export class PositronViewer { async clearViewer() { await this.code.driver.page.getByRole('tab', { name: 'Viewer' }).locator('a').click(); - await this.fullApp.getByLabel(/Clear the/).click(); + + const clearRegex = /Clear the/; + + if (await this.fullApp.getByLabel(clearRegex).isVisible()) { + await this.fullApp.getByLabel(clearRegex).click(); + } + } + + async openViewerToEditor() { + await this.code.driver.page.locator('.codicon-go-to-file').click(); } } diff --git a/test/smoke/src/areas/positron/apps/python-apps.test.ts b/test/smoke/src/areas/positron/apps/python-apps.test.ts index 0305667b1e8..bedbac93515 100644 --- a/test/smoke/src/areas/positron/apps/python-apps.test.ts +++ b/test/smoke/src/areas/positron/apps/python-apps.test.ts @@ -12,6 +12,8 @@ test.use({ test.describe('Python Applications', { tag: ['@pr'] }, () => { test.afterEach(async function ({ app }) { + await app.workbench.quickaccess.runCommand('workbench.action.closeAllEditors'); + await app.workbench.quickaccess.runCommand('workbench.action.terminal.focus'); await app.workbench.positronTerminal.sendKeysToTerminal('Control+C'); // unreliable on ubuntu: @@ -26,17 +28,35 @@ test.describe('Python Applications', { tag: ['@pr'] }, () => { await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'workspaces', 'python_apps', 'dash_example', 'dash_example.py')); await app.workbench.positronEditor.pressPlay(); await expect(viewer.getViewerFrame().getByText('Hello World')).toBeVisible({ timeout: 30000 }); + + await test.step('Verify app can be opened in editor', async () => { + await app.workbench.positronViewer.openViewerToEditor(); + await app.workbench.positronViewer.clearViewer(); + + const editorFrameLocator = app.workbench.positronEditor.getEditorViewerFrame(); + + await expect(editorFrameLocator.getByText('Hello World')).toBeVisible({ timeout: 30000 }); + }); }); - // FastAPI is not working as expected on Ubuntu test('Python - Verify Basic FastAPI App [C903306]', async function ({ app, python }) { const viewer = app.workbench.positronViewer; await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'workspaces', 'python_apps', 'fastapi_example', 'fastapi_example.py')); await app.workbench.positronEditor.pressPlay(); await expect(viewer.getViewerFrame().getByText('FastAPI')).toBeVisible({ timeout: 30000 }); + + await test.step('Verify app can be opened in editor', async () => { + await app.workbench.positronViewer.openViewerToEditor(); + await app.workbench.positronViewer.clearViewer(); + + const editorHeaderLocator = app.workbench.positronEditor.getEditorViewerLocator('h2'); + + await expect(editorHeaderLocator).toContainText('FastAPI', { timeout: 30000 }); + }); }); + // TODO: update for pop out to editor when issue resolved test.skip('Python - Verify Basic Gradio App [C903307]', { tag: ['@win'], annotation: [{ type: 'issue', description: 'https://github.com/posit-dev/positron/issues/5459' }] @@ -69,6 +89,20 @@ test.describe('Python Applications', { tag: ['@pr'] }, () => { await expect(headerLocator).toBeVisible({ timeout: 30000 }); }).toPass({ timeout: 60000 }); + + await test.step('Verify app can be opened in editor', async () => { + await app.workbench.positronViewer.openViewerToEditor(); + await app.workbench.positronViewer.clearViewer(); + + const editor = app.workbench.positronEditor; + const editorFrame = editor.getEditorViewerFrame(); + + const headerLocator = app.web + ? editorFrame.frameLocator('iframe').getByRole('button', { name: 'Deploy' }) + : editorFrame.getByRole('button', { name: 'Deploy' }); + + await expect(headerLocator).toBeVisible({ timeout: 30000 }); + }); }); test('Python - Verify Basic Flask App [C1013655]', { @@ -80,7 +114,6 @@ test.describe('Python Applications', { tag: ['@pr'] }, () => { await app.workbench.quickaccess.runCommand('workbench.action.toggleSidebarVisibility'); await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); await app.workbench.positronEditor.pressPlay(); - await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); const viewerFrame = viewer.getViewerFrame(); const loginLocator = app.web ? viewerFrame.frameLocator('iframe').getByText('Log In') @@ -89,6 +122,21 @@ test.describe('Python Applications', { tag: ['@pr'] }, () => { await expect(async () => { await expect(loginLocator).toBeVisible({ timeout: 30000 }); }).toPass({ timeout: 60000 }); + + await test.step('Verify app can be opened in editor', async () => { + await app.workbench.positronViewer.openViewerToEditor(); + await app.workbench.positronViewer.clearViewer(); + + const editor = app.workbench.positronEditor; + const editorFrame = editor.getEditorViewerFrame(); + + const loginLocator = app.web + ? editorFrame.frameLocator('iframe').getByText('Log In') + : editorFrame.getByText('Log In'); + + await expect(loginLocator).toBeVisible({ timeout: 30000 }); + }); + await app.workbench.quickaccess.runCommand('workbench.action.toggleSidebarVisibility'); }); });