Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add jupyter lab 3.6.5 tests #32

Merged
merged 1 commit into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Tests
name: Tests - lab 3

on:
push:
Expand Down Expand Up @@ -27,7 +27,7 @@ jobs:
- run: pip install tox

- name: run Python tests
run: tox -e tests
run: tox -e tests-lab-3

- name: run Python tests for coverage
run: tox -e coverage
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/tests-notebook-7.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Tests - notebook 7

on:
push:
branches: [main]
pull_request:
# Check all PR

jobs:
tests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-22.04
python-version: "3.11"

steps:
- uses: actions/checkout@v3
- name: Install Firefox
uses: browser-actions/setup-firefox@latest

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- run: pip install tox

- name: run Python tests
run: tox -e tests-notebook-7

- name: run Python tests for coverage
run: tox -e coverage
- uses: codecov/codecov-action@v3
with:
files: coverage.xml
verbose: true

129 changes: 114 additions & 15 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,48 @@
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

# Can be "notebook" for jupyter notebook or "lab" for jupyter lab
JUPYTER_TYPE = os.environ["JUPYTER_TYPE"] if "JUPYTER_TYPE" in os.environ else "lab"
# Because for the tests frontend elements are retrieved by class names which change
# between versions, these veriable are change depending on the version. The version is
# automatically determined on initialization of tests
JUPYTER_VERSION = None


def get_jupyter_version() -> str:
"""
Function so we can update the jupyter version during initialization
and use it in other files
"""
global JUPYTER_VERSION
if JUPYTER_VERSION is None:
raise ValueError("JUPYTER_VERSION was not correctly on initialization")
return JUPYTER_VERSION


@pytest.fixture(scope="session")
def notebook_service():
global JUPYTER_VERSION

if JUPYTER_TYPE not in ["lab", "notebook"]:
raise ValueError(
f"Tests do not support jupyter type {JUPYTER_TYPE!r}. Please use"
" 'notebook' or 'lab'."
)

# some hard coded port and token
port = 8815
token = "fe47337ccb5b331e3d26a36b92112664af06462e511f66bb"
jupyter_version = subprocess.check_output(
["jupyter", f"{JUPYTER_TYPE}", "--version"]
)
# convert to string
JUPYTER_VERSION = jupyter_version.decode().replace("\n", "")

jupyter_process = subprocess.Popen(
[
"jupyter",
"notebook",
f"{JUPYTER_TYPE}",
f"--NotebookApp.token={token}",
"--no-browser",
f"--port={port}",
Expand All @@ -33,7 +65,7 @@ def notebook_service():
yield url, token

# teardown juypter notebook
os.system(f"jupyter notebook stop {port}")
os.system(f"jupyter {JUPYTER_TYPE} stop {port}")
time.sleep(2)
os.system(f"kill {jupyter_process.pid}")

Expand All @@ -48,66 +80,133 @@ def _selenium_driver(nb_path):
"""
:param nb_path: jupyter notebook path
"""
global JUPYTER_TYPE
url, token = notebook_service
url_with_token = urljoin(url, f"tree/{nb_path}?token={token}")

if JUPYTER_TYPE == "lab":
nb_path_prefix = "lab/tree"
elif JUPYTER_TYPE == "notebook":
nb_path_prefix = "tree"
else:
raise ValueError(
f"Tests do not support jupyter type {JUPYTER_TYPE!r}. Please use"
" 'notebook' or 'lab'."
)

# nb_path_prefix =
url_with_token = urljoin(url, f"{nb_path_prefix}/{nb_path}?token={token}")
selenium.get(f"{url_with_token}")
selenium.implicitly_wait(10)
window_width = 1280
window_height = 1024
selenium.set_window_size(window_width, window_height)

# Click on restart kernel button
# ------------------------------

# jupyter lab < 4
if JUPYTER_TYPE == "lab":
if get_jupyter_version() < "4.0.0":
restart_kernel_button_class_name = (
"bp3-button.bp3-minimal.jp-ToolbarButtonComponent.minimal.jp-Button"
)
restart_kernel_button_title_attribute = (
"Restart Kernel and Run All Cells…"
)
else:
raise ValueError("jupyter lab > 4.0.0 is not supported.")
elif JUPYTER_TYPE == "notebook":
if get_jupyter_version() < "7.0.0":
restart_kernel_button_class_name = "btn.btn-default"
restart_kernel_button_title_attribute = (
"restart the kernel, then re-run the whole notebook (with dialog)"
)
else:
restart_kernel_button_class_name = (
"jp-ToolbarButtonComponent.jp-mod-minimal.jp-Button"
)
restart_kernel_button_title_attribute = (
"Restart the kernel and run all cells"
)

# the code below imitates this code which cannot find the button
# I think it is because the button is hidden by another element
# WebDriverWait(driver, 5).until(
# expected_conditions.text_to_be_present_in_element_attribute(
# (By.CLASS_NAME, "jp-ToolbarButtonComponent.jp-mod-minimal.jp-Button"),
# (By.CLASS_NAME, restart_kernel_button_class_name),
# "title",
# "Restart the kernel and run all cells"
# restart_kernel_button_title_attribute
# )
# )
restart_kernel_button = None
waiting_time = 10
start = time.time()

while restart_kernel_button is None and time.time() - start < waiting_time:
# does not work for older notebook versions
buttons = selenium.find_elements(
By.CLASS_NAME, "jp-ToolbarButtonComponent.jp-mod-minimal.jp-Button"
By.CLASS_NAME, restart_kernel_button_class_name
)
for button in buttons:
try:
title = button.get_attribute("title")
if title == "Restart the kernel and run all cells":
if (
button.is_displayed()
and title == restart_kernel_button_title_attribute
):
restart_kernel_button = button
except StaleElementReferenceException:
# element is not ready, go sleep
continue

time.sleep(0.1)
if restart_kernel_button is None:
raise ValueError('"Restart the kernel and run all cells" button not found.')
raise ValueError(
f"{restart_kernel_button_title_attribute!r} button not found."
)
restart_kernel_button.click()

# Click on confirm restart dialog
# -------------------------------

if JUPYTER_TYPE == "lab":
if get_jupyter_version() < "4.0.0":
restart_button_class_name = (
"jp-Dialog-button.jp-mod-accept.jp-mod-warn.jp-mod-styled"
)
restart_button_text = "Restart"
else:
raise ValueError("jupyter lab > 4.0.0 is not supported.")
elif JUPYTER_TYPE == "notebook":
if get_jupyter_version() < "7.0.0":
restart_button_class_name = "btn.btn-default.btn-sm.btn-danger"
restart_button_text = "Restart and Run All Cells"
else:
restart_button_class_name = "jp-Dialog-buttonLabel"
restart_button_text = "Restart"

# the code below imitates this code which cannot find the button
# I think it is because the button is hidden by another element
# WebDriverWait(driver, 5).until(
# expected_conditions.text_to_be_present_in_element(
# (By.CLASS_NAME, "jp-Dialog-buttonLabel"),
# "Restart"
# (By.CLASS_NAME, restart_button_class_name),
# restart_button_text
# )
# )

restart_button = None
waiting_time = 10
start = time.time()
while restart_button is None and time.time() - start < waiting_time:
buttons = selenium.find_elements(By.CLASS_NAME, "jp-Dialog-buttonLabel")
buttons = selenium.find_elements(By.CLASS_NAME, restart_button_class_name)
for button in buttons:
if button.text == "Restart":
if button.text == restart_button_text:
restart_button = button
time.sleep(0.1)

if restart_button is None:
raise ValueError('"Restart" button not found.')
raise ValueError(f"{restart_button_text!r} button not found.")
restart_button.click()

# wait until everything has been run
WebDriverWait(selenium, 10).until(
expected_conditions.text_to_be_present_in_element_attribute(
(By.CLASS_NAME, "jp-Notebook-ExecutionIndicator"), "data-status", "idle"
Expand Down
Loading