Skip to content

Commit e29aa41

Browse files
committed
RHOAIENG-11156: chore(tests/containers/jupyterlab): check that the JupyterLab index.html contains the spinner code
1 parent 4a7c9f9 commit e29aa41

File tree

5 files changed

+70
-3
lines changed

5 files changed

+70
-3
lines changed

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pyfakefs = "^5.7.4"
1818
testcontainers = "^4.9.1"
1919
docker = "^7.1.0"
2020
pydantic = "^2.10.6"
21+
requests = "^2.32.3"
2122

2223
[build-system]
2324
requires = ["poetry-core"]

tests/containers/workbenches/jupyterlab/__init__.py

Whitespace-only changes.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
import requests
6+
7+
import allure
8+
import pytest
9+
10+
from tests.containers import docker_utils
11+
from tests.containers.workbenches.workbench_image_test import WorkbenchContainer, skip_if_not_workbench_image
12+
13+
if TYPE_CHECKING:
14+
import docker.models.images
15+
16+
17+
class TestJupyterLabImage:
18+
"""Tests for JupyterLab Workbench images in this repository."""
19+
20+
APP_ROOT_HOME = "/opt/app-root/src"
21+
22+
@allure.issue("RHOAIENG-11156")
23+
@allure.description("Check that the HTML for the spinner is contained in the initial page.")
24+
def test_spinner_html_loaded(self, image: str) -> None:
25+
skip_if_not_jupyterlab_image(image)
26+
27+
container = WorkbenchContainer(image=image, user=4321, group_add=[0])
28+
# if no env is specified, the image will run
29+
# > 4321 3334 3319 0 10:36 pts/0 00:00:01 /mnt/rosetta /opt/app-root/bin/python3.11 /opt/app-root/bin/jupyter-lab
30+
# > --ServerApp.root_dir=/opt/app-root/src --ServerApp.ip= --ServerApp.allow_origin=* --ServerApp.open_browser=False
31+
# which does not let us open a notebook and get a spinner, we need to disable auth at a minimum
32+
33+
# These NOTEBOOK_ARGS are what ODH Dashboard uses,
34+
# and we also have them in the Kustomize test files for Makefile tests
35+
container.with_env("NOTEBOOK_ARGS", "\n".join([
36+
"--ServerApp.port=8888",
37+
"--ServerApp.token=''",
38+
"--ServerApp.password=''",
39+
"--ServerApp.base_url=/notebook/opendatahub/jovyan",
40+
"--ServerApp.quit_button=False",
41+
"""--ServerApp.tornado_settings={"user":"jovyan","hub_host":"https://opendatahub.io","hub_prefix":"/notebookController/jovyan"}"""]))
42+
try:
43+
# we changed base_url, and wait_for_readiness=True would attempt connections to /
44+
container.start(wait_for_readiness=False)
45+
container._connect(base_url="/notebook/opendatahub/jovyan")
46+
47+
host_ip = container.get_container_host_ip()
48+
host_port = container.get_exposed_port(container.port)
49+
response = requests.get(f"http://{host_ip}:{host_port}/notebook/opendatahub/jovyan")
50+
assert response.status_code == 200
51+
assert "text/html" in response.headers["content-type"]
52+
assert 'class="pf-v6-c-spinner"' in response.text
53+
finally:
54+
docker_utils.NotebookContainer(container).stop(timeout=0)
55+
56+
57+
def skip_if_not_jupyterlab_image(image: str) -> docker.models.images.Image:
58+
image_metadata = skip_if_not_workbench_image(image)
59+
if "-jupyter-" not in image_metadata.labels['name']:
60+
pytest.skip(
61+
f"Image {image} does not have '-jupyter-' in {image_metadata.labels['name']=}'")
62+
63+
return image_metadata

tests/containers/workbenches/workbench_image_test.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,12 @@ def __init__(
137137
self.with_exposed_ports(self.port)
138138

139139
@testcontainers.core.waiting_utils.wait_container_is_ready(urllib.error.URLError)
140-
def _connect(self, container_host: str | None = None, container_port: int | None = None) -> None:
140+
def _connect(self, container_host: str | None = None, container_port: int | None = None,
141+
base_url: str = "") -> None:
141142
"""
142143
:param container_host: overrides the container host IP in connection check to use direct access
144+
:param container_port: overrides the container port
145+
:param base_url: needs to be with a leading /
143146
"""
144147
# are we still alive?
145148
self.get_wrapped_container().reload()
@@ -156,7 +159,7 @@ def _connect(self, container_host: str | None = None, container_port: int | None
156159
# host may be an ipv6 address, need to be careful with formatting this
157160
if ":" in host:
158161
host = f"[{host}]"
159-
result = opener.open(urllib.request.Request(f"http://{host}:{port}"), timeout=1)
162+
result = opener.open(urllib.request.Request(f"http://{host}:{port}{base_url}"), timeout=1)
160163
except urllib.error.URLError as e:
161164
raise e
162165

0 commit comments

Comments
 (0)