Merge pull request #1410 from manics/playwright

Add basic UI Playwright tests
pull/1411/head
Simon Li 2025-02-12 17:32:47 +00:00 zatwierdzone przez GitHub
commit f50c0c52eb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
9 zmienionych plików z 101 dodań i 3 usunięć

Wyświetl plik

@ -71,6 +71,10 @@ jobs:
- ubuntu_version: "20.04"
python_version: "3.6"
repo_type: venv
# Playwright test
- ubuntu_version: "24.04"
python_version: "3.13"
repo_type: ui
steps:
- uses: actions/checkout@v4
@ -83,6 +87,12 @@ jobs:
pip install -r dev-requirements.txt
pip freeze
- name: Install UI test dependencies
if: matrix.repo_type == 'ui'
run: |
pip install -r playwright-requirements.txt
playwright install firefox
- name: Install repo2docker
run: |
python -m build --wheel .

Wyświetl plik

@ -0,0 +1,2 @@
-r dev-requirements.txt
pytest-playwright

Wyświetl plik

@ -39,7 +39,7 @@ def pytest_collect_file(parent, file_path):
return RemoteRepoList.from_parent(parent, path=file_path)
def make_test_func(args, skip_build=False, extra_run_kwargs=None):
def make_test_func(args, skip_build=False, extra_run_kwargs=None, external_script=None):
"""Generate a test function that runs repo2docker"""
def test():
@ -82,6 +82,10 @@ def make_test_func(args, skip_build=False, extra_run_kwargs=None):
success = True
break
assert success, f"Notebook never started in {container}"
if external_script:
subprocess.check_call([external_script, f"http://localhost:{port}"])
finally:
# stop the container
container.stop()
@ -202,12 +206,21 @@ class Repo2DockerTest(pytest.Function):
"""A pytest.Item for running repo2docker"""
def __init__(
self, name, parent, args=None, skip_build=False, extra_run_kwargs=None
self,
name,
parent,
args=None,
skip_build=False,
extra_run_kwargs=None,
external_script=None,
):
self.args = args
self.save_cwd = os.getcwd()
f = parent.obj = make_test_func(
args, skip_build=skip_build, extra_run_kwargs=extra_run_kwargs
args,
skip_build=skip_build,
extra_run_kwargs=extra_run_kwargs,
external_script=external_script,
)
super().__init__(name, parent, callobj=f)
@ -246,6 +259,17 @@ class LocalRepo(pytest.File):
args.append(str(self.path.parent))
yield Repo2DockerTest.from_parent(self, name="build", args=args)
# If external-verify exists it should be run on the host
external_verify_script = self.path.parent / "external-verify"
if external_verify_script.exists():
yield Repo2DockerTest.from_parent(
self,
name=external_verify_script.name,
args=args,
skip_build=True,
external_script=external_verify_script,
)
yield Repo2DockerTest.from_parent(
self,
name=self.path.name,

Wyświetl plik

@ -0,0 +1,9 @@
# User interface tests
This contains very basic [Playwright](https://playwright.dev/python/) tests to check the
- JupyterLab
- RStudio
- RShiny
interfaces can be accessed.

Wyświetl plik

@ -0,0 +1,2 @@
dependencies:
- r-base

Wyświetl plik

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# This script is run outside the container
set -eux
export TEST_REPO2DOCKER_URL="${1}/?token=token"
pytest --verbose --color=yes --browser=firefox tests/ui/browser/external-verify.py

Wyświetl plik

@ -0,0 +1,41 @@
import os
from subprocess import check_output
from urllib.parse import urlsplit
import pytest
from playwright.sync_api import Page, expect
# To run this test manually:
# - Run: repo2docker tests/ui/browser/
# - Run: TEST_REPO2DOCKER_URL=<connection-url> python -mpytest --browser=firefox tests/ui/browser/external-verify.py [--headed]
def test_user_interfaces(page: Page) -> None:
url = os.getenv("TEST_REPO2DOCKER_URL")
u = urlsplit(url)
# Includes token
page.goto(url)
# Initial page should be Jupyter Notebook
page.wait_for_url(f"{u.scheme}://{u.netloc}/tree")
# Check JupyterLab
page.goto(f"{u.scheme}://{u.netloc}/lab")
expect(page.get_by_text("Python 3 (ipykernel)").nth(1)).to_be_visible()
# Check JupyterLab RStudio launcher
with page.expect_popup() as page1_info:
page.get_by_text("RStudio [↗]").click()
page1 = page1_info.value
page1.wait_for_url(f"{u.scheme}://{u.netloc}/rstudio/")
# Top-left logo
expect(page1.locator("#rstudio_rstudio_logo")).to_be_visible()
# Initial RStudio console text
expect(page1.get_by_text("R version ")).to_be_visible()
# Check JupyterLab RShiny launcher
with page.expect_popup() as page2_info:
page.get_by_text("Shiny [↗]").click()
page2 = page2_info.value
page2.wait_for_url(f"{u.scheme}://{u.netloc}/shiny/")
expect(page2.get_by_text("Index of /")).to_be_visible()

Wyświetl plik

@ -0,0 +1,2 @@
- --env
- JUPYTER_TOKEN=token

Wyświetl plik

@ -0,0 +1 @@
#!/bin/sh