From 9d858046178da1bae0c31309db1a8d8f5ebc8b28 Mon Sep 17 00:00:00 2001 From: Christopher Mead Date: Thu, 25 Jul 2024 12:25:37 -0600 Subject: [PATCH] Notebook smoke tests robustness fixes (#4153) This PR has some notebook test robustness fixes. The basic notebook test now has two types of retries: * retry entry of code in cell if entered text not visible post entry * retry cell execution if output does not appear The notebook variables test just has one minor fix: allow one second post execution before beginning to look for variables. Note that there is an open issue that might still lead to these tests failing: https://github.com/posit-dev/positron/issues/3805 ### QA Notes All smoke tests should pass --- .../src/positron/positronNotebooks.ts | 28 +++++++++++-------- .../src/positron/positronVariables.ts | 7 +++++ .../positron/notebook/notebookCreate.test.ts | 12 +++++--- .../variables/notebookVariables.test.ts | 18 +++++++++--- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/test/automation/src/positron/positronNotebooks.ts b/test/automation/src/positron/positronNotebooks.ts index d0e4ab6819b..5bd60d533d1 100644 --- a/test/automation/src/positron/positronNotebooks.ts +++ b/test/automation/src/positron/positronNotebooks.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ +import { expect } from '@playwright/test'; import { Code } from '../code'; import { Notebook } from '../notebook'; import { QuickAccess } from '../quickaccess'; @@ -51,20 +52,23 @@ export class PositronNotebooks { await this.quickaccess.runCommand(NEW_NOTEBOOK_COMMAND); } - async executeInFirstCell(code: string) { - await this.quickaccess.runCommand(EDIT_CELL_COMMAND); + async addCodeToFirstCell(code: string) { - // If this function is being called a second time as part of a retry, the cell may already have content - // so we need to clear it first - if (process.platform === 'darwin') { - await this.code.dispatchKeybinding('cmd+A'); - } - else { - await this.code.dispatchKeybinding('ctrl+A'); - } - await this.code.dispatchKeybinding('Delete'); + // Attempt to add code to a cell. If the code is not added correctly, delete the cell and try + // again for up to 60 seconds + await expect(async () => { + try { + await this.quickaccess.runCommand(EDIT_CELL_COMMAND); + await this.notebook.waitForTypeInEditor(code); + await this.notebook.waitForActiveCellEditorContents(code); + } catch (e) { + await this.notebook.deleteActiveCell(); + throw e; + } + }).toPass({ timeout: 60000 }); + } - await this.notebook.waitForTypeInEditor(code); + async executeCodeInCell() { await this.quickaccess.runCommand(EXECUTE_CELL_COMMAND); } diff --git a/test/automation/src/positron/positronVariables.ts b/test/automation/src/positron/positronVariables.ts index 663a510640e..a8ed3be6581 100644 --- a/test/automation/src/positron/positronVariables.ts +++ b/test/automation/src/positron/positronVariables.ts @@ -6,6 +6,7 @@ import { Code } from '../code'; import * as os from 'os'; +import { IElement } from '../driver'; interface FlatVariables { value: string; @@ -17,6 +18,7 @@ const VARIABLE_NAMES = 'name-column'; const VARIABLE_DETAILS = 'details-column'; const VARIABLES_NAME_COLUMN = '.variable-item .name-column'; const VARIABLES_SECTION = '[aria-label="Variables Section"]'; +const VARIABLES_INTERPRETER = '.positron-variables-container .action-bar-button-text'; /* * Reuseable Positron variables functionality for tests to leverage. @@ -65,4 +67,9 @@ export class PositronVariables { await this.code.waitForElement(VARIABLES_SECTION); } + + async getVariablesInterpreter(): Promise { + const interpreter = await this.code.waitForElement(VARIABLES_INTERPRETER); + return interpreter; + } } diff --git a/test/smoke/src/areas/positron/notebook/notebookCreate.test.ts b/test/smoke/src/areas/positron/notebook/notebookCreate.test.ts index fd9830f0690..ad11699e754 100644 --- a/test/smoke/src/areas/positron/notebook/notebookCreate.test.ts +++ b/test/smoke/src/areas/positron/notebook/notebookCreate.test.ts @@ -39,10 +39,12 @@ export function setup(logger: Logger) { await app.workbench.positronNotebooks.selectInterpreter('Python Environments', process.env.POSITRON_PY_VER_SEL!); + await app.workbench.positronNotebooks.addCodeToFirstCell('eval("8**2")'); + await expect(async () => { - await app.workbench.positronNotebooks.executeInFirstCell('eval("8**2")'); + await app.workbench.positronNotebooks.executeCodeInCell(); expect(await app.workbench.positronNotebooks.getPythonCellOutput()).toBe('64'); - }).toPass({timeout: 60000}); + }).toPass({ timeout: 60000 }); }); @@ -86,10 +88,12 @@ export function setup(logger: Logger) { await app.workbench.positronNotebooks.selectInterpreter('R Environments', process.env.POSITRON_R_VER_SEL!); + await app.workbench.positronNotebooks.addCodeToFirstCell('eval(parse(text="8**2"))'); + await expect(async () => { - await app.workbench.positronNotebooks.executeInFirstCell('eval(parse(text="8**2"))'); + await app.workbench.positronNotebooks.executeCodeInCell(); expect(await app.workbench.positronNotebooks.getRCellOutput()).toBe('[1] 64'); - }).toPass({timeout: 60000}); + }).toPass({ timeout: 60000 }); }); diff --git a/test/smoke/src/areas/positron/variables/notebookVariables.test.ts b/test/smoke/src/areas/positron/variables/notebookVariables.test.ts index fa13be3c6f4..42f2322e081 100644 --- a/test/smoke/src/areas/positron/variables/notebookVariables.test.ts +++ b/test/smoke/src/areas/positron/variables/notebookVariables.test.ts @@ -37,9 +37,14 @@ export function setup(logger: Logger) { await app.workbench.positronNotebooks.selectInterpreter('Python Environments', process.env.POSITRON_PY_VER_SEL!); - await app.workbench.positronNotebooks.executeInFirstCell('y = [2, 3, 4, 5]'); + await app.workbench.positronNotebooks.addCodeToFirstCell('y = [2, 3, 4, 5]'); - const interpreter = await app.code.waitForElement('.positron-variables-container .action-bar-button-text'); + await app.workbench.positronNotebooks.executeCodeInCell(); + + // just to be safe, give cell some execution time + await app.code.wait(1000); + + const interpreter = await app.workbench.positronVariables.getVariablesInterpreter(); expect(interpreter.textContent).toBe('Untitled-1.ipynb'); @@ -81,9 +86,14 @@ export function setup(logger: Logger) { await app.workbench.positronNotebooks.selectInterpreter('R Environments', process.env.POSITRON_R_VER_SEL!); - await app.workbench.positronNotebooks.executeInFirstCell('y <- c(2, 3, 4, 5)'); + await app.workbench.positronNotebooks.addCodeToFirstCell('y <- c(2, 3, 4, 5)'); + + await app.workbench.positronNotebooks.executeCodeInCell(); + + // just to be safe, give cell some execution time + await app.code.wait(1000); - const interpreter = await app.code.waitForElement('.positron-variables-container .action-bar-button-text'); + const interpreter = await app.workbench.positronVariables.getVariablesInterpreter(); expect(interpreter.textContent).toBe('Untitled-1.ipynb');