kopia lustrzana https://github.com/jupyterhub/repo2docker
Add basic UI Playwright tests
rodzic
95e3adc0c8
commit
0186eef20d
|
@ -68,6 +68,10 @@ jobs:
|
||||||
- ubuntu_version: "20.04"
|
- ubuntu_version: "20.04"
|
||||||
python_version: "3.6"
|
python_version: "3.6"
|
||||||
repo_type: venv
|
repo_type: venv
|
||||||
|
# Playwright test
|
||||||
|
- ubuntu_version: "24.04"
|
||||||
|
python_version: "3.13"
|
||||||
|
repo_type: ui
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -80,6 +84,12 @@ jobs:
|
||||||
pip install -r dev-requirements.txt
|
pip install -r dev-requirements.txt
|
||||||
pip freeze
|
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
|
- name: Install repo2docker
|
||||||
run: |
|
run: |
|
||||||
python -m build --wheel .
|
python -m build --wheel .
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
-r dev-requirements.txt
|
||||||
|
pytest-playwright
|
|
@ -39,7 +39,7 @@ def pytest_collect_file(parent, file_path):
|
||||||
return RemoteRepoList.from_parent(parent, path=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"""
|
"""Generate a test function that runs repo2docker"""
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
|
@ -82,6 +82,10 @@ def make_test_func(args, skip_build=False, extra_run_kwargs=None):
|
||||||
success = True
|
success = True
|
||||||
break
|
break
|
||||||
assert success, f"Notebook never started in {container}"
|
assert success, f"Notebook never started in {container}"
|
||||||
|
|
||||||
|
if external_script:
|
||||||
|
subprocess.check_call([external_script, f"http://localhost:{port}"])
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# stop the container
|
# stop the container
|
||||||
container.stop()
|
container.stop()
|
||||||
|
@ -202,12 +206,21 @@ class Repo2DockerTest(pytest.Function):
|
||||||
"""A pytest.Item for running repo2docker"""
|
"""A pytest.Item for running repo2docker"""
|
||||||
|
|
||||||
def __init__(
|
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.args = args
|
||||||
self.save_cwd = os.getcwd()
|
self.save_cwd = os.getcwd()
|
||||||
f = parent.obj = make_test_func(
|
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)
|
super().__init__(name, parent, callobj=f)
|
||||||
|
|
||||||
|
@ -246,6 +259,17 @@ class LocalRepo(pytest.File):
|
||||||
args.append(str(self.path.parent))
|
args.append(str(self.path.parent))
|
||||||
yield Repo2DockerTest.from_parent(self, name="build", args=args)
|
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=self.path.name,
|
||||||
|
args=args,
|
||||||
|
skip_build=True,
|
||||||
|
external_script=external_verify_script,
|
||||||
|
)
|
||||||
|
|
||||||
yield Repo2DockerTest.from_parent(
|
yield Repo2DockerTest.from_parent(
|
||||||
self,
|
self,
|
||||||
name=self.path.name,
|
name=self.path.name,
|
||||||
|
|
|
@ -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.
|
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- r-base
|
|
@ -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
|
|
@ -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()
|
|
@ -0,0 +1,2 @@
|
||||||
|
- --env
|
||||||
|
- JUPYTER_TOKEN=token
|
|
@ -0,0 +1 @@
|
||||||
|
#!/bin/sh
|
Ładowanie…
Reference in New Issue