From fa4e18e64643e833da9b9aaa439079819ca137ea Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Fri, 2 Feb 2024 10:03:29 -0500 Subject: [PATCH 1/6] Modify Playwright test to account for changes in JupyterLab UI. --- tests/common/navigator.py | 12 ++++-------- tests/common/run_notebook.py | 2 +- tests/tests_e2e/playwright/test_playwright.py | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/common/navigator.py b/tests/common/navigator.py index dc2adc9eba..ff56c8c5c2 100644 --- a/tests/common/navigator.py +++ b/tests/common/navigator.py @@ -320,15 +320,13 @@ def _set_environment_via_popup(self, kernel=None): # failure here indicates that the environment doesn't exist either # because of incorrect naming syntax or because the env is still # being built - self.page.get_by_role("combobox").nth(1).select_option( - f'{{"name":"{kernel}"}}' - ) + self.page.get_by_role("combobox").nth(1).select_option(kernel) # click Select to close popup (deal with the two formats of this dialog) try: - self.page.get_by_role("button", name="Select", exact=True).click() + self.page.get_by_role("button", name="Select Kernel").click() except Exception: self.page.locator("div").filter(has_text="No KernelSelect").get_by_role( - "button", name="Select" + "button", name="Select Kernel" ).click() def set_environment(self, kernel): @@ -360,10 +358,8 @@ def set_environment(self, kernel): self._set_environment_via_popup(kernel) # wait for the jupyter UI to catch up before moving forward - # extract conda env name - conda_env_label = re.search("conda-env-(.*)-py", kernel).group(1) # see if the jupyter notebook label for the conda env is visible - kernel_label_loc = self.page.get_by_role("button", name=conda_env_label) + kernel_label_loc = self.page.get_by_role("button", name=kernel) if not kernel_label_loc.is_visible(): kernel_label_loc.wait_for(state="attached") diff --git a/tests/common/run_notebook.py b/tests/common/run_notebook.py index 03c383299a..10d28d6637 100644 --- a/tests/common/run_notebook.py +++ b/tests/common/run_notebook.py @@ -220,7 +220,7 @@ def _restart_run_all(self): # Restart dialog appears most, but not all of the time (e.g. set # No Kernel, then Restart Run All) restart_dialog_button = self.nav.page.get_by_role( - "button", name="Restart", exact=True + "button", name="Confirm Kernel Restart" ) if restart_dialog_button.is_visible(): restart_dialog_button.click() diff --git a/tests/tests_e2e/playwright/test_playwright.py b/tests/tests_e2e/playwright/test_playwright.py index 7f4dabac08..903af3f0dd 100644 --- a/tests/tests_e2e/playwright/test_playwright.py +++ b/tests/tests_e2e/playwright/test_playwright.py @@ -13,6 +13,6 @@ def test_notebook(navigator, test_data_root): test_app.run( path=notebook_name, expected_outputs=["success: 6"], - conda_env="conda-env-default-py", + conda_env="default *", timeout=500, ) From a605a248ad15ea2a33dbf9d54a5efda3409b7fe2 Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Fri, 2 Feb 2024 12:53:16 -0500 Subject: [PATCH 2/6] Add header with xrsf token as API complains when not passed. --- tests/tests_deployment/utils.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/tests_deployment/utils.py b/tests/tests_deployment/utils.py index 327de53309..b2b2a707b6 100644 --- a/tests/tests_deployment/utils.py +++ b/tests/tests_deployment/utils.py @@ -28,16 +28,17 @@ def get_jupyterhub_session(): def get_jupyterhub_token(note="jupyterhub-tests-deployment"): session = get_jupyterhub_session() + xsrf_token = session.cookies.get("_xsrf") + headers = {"Referer": f"https://{constants.NEBARI_HOSTNAME}/hub/token"} + if xsrf_token: + headers["X-XSRFToken"] = xsrf_token + data = {"note": note, "expires_in": None} r = session.post( f"https://{constants.NEBARI_HOSTNAME}/hub/api/users/{constants.KEYCLOAK_USERNAME}/tokens", - headers={ - "Referer": f"https://{constants.NEBARI_HOSTNAME}/hub/token", - }, - json={ - "note": note, - "expires_in": None, - }, + headers=headers, + json=data, ) + print(xsrf_token, note, r.json()) return r.json()["token"] From 311b00d5cd9eedd62cb12e99fb73fa72c14721eb Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Fri, 2 Feb 2024 12:54:03 -0500 Subject: [PATCH 3/6] Extract api_token as a session fixture to avoid token conflicts when server starts. --- tests/tests_deployment/test_jupyterhub_ssh.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/tests_deployment/test_jupyterhub_ssh.py b/tests/tests_deployment/test_jupyterhub_ssh.py index 0e90927a4c..fd6b0799d5 100644 --- a/tests/tests_deployment/test_jupyterhub_ssh.py +++ b/tests/tests_deployment/test_jupyterhub_ssh.py @@ -14,10 +14,14 @@ TIMEOUT_SECS = 300 +@pytest.fixture(scope="session") +def api_token(): + return get_jupyterhub_token("jupyterhub-ssh") + + @pytest.fixture(scope="function") -def paramiko_object(): +def paramiko_object(api_token): """Connects to JupyterHub ssh cluster from outside the cluster.""" - api_token = get_jupyterhub_token("jupyterhub-ssh") try: client = paramiko.SSHClient() From 4aa145724dbd20f15da5a5a1b81721a02bfc8f2d Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Fri, 2 Feb 2024 13:23:41 -0500 Subject: [PATCH 4/6] Remove print statement. --- tests/tests_deployment/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests_deployment/utils.py b/tests/tests_deployment/utils.py index b2b2a707b6..d175a2dd05 100644 --- a/tests/tests_deployment/utils.py +++ b/tests/tests_deployment/utils.py @@ -38,7 +38,7 @@ def get_jupyterhub_token(note="jupyterhub-tests-deployment"): headers=headers, json=data, ) - print(xsrf_token, note, r.json()) + return r.json()["token"] From 874a2d83baf084a0342478b451a22f2fd6360c35 Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Mon, 5 Feb 2024 13:30:23 -0500 Subject: [PATCH 5/6] Add function to stop server, making sure that it's not running when running deployment tests. --- tests/common/navigator.py | 17 +++++++++++++++++ tests/common/playwright_fixtures.py | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/tests/common/navigator.py b/tests/common/navigator.py index ff56c8c5c2..50fc1837bc 100644 --- a/tests/common/navigator.py +++ b/tests/common/navigator.py @@ -407,3 +407,20 @@ def write_file(self, filepath, content): self.run_terminal_command(f"ls {filepath}") logger.debug(f"time to complete {dt.datetime.now() - start}") time.sleep(2) + + def stop_server(self) -> None: + """Stops the JupyterHub server by navigating to the Hub Control Panel.""" + self.page.get_by_text("File", exact=True).click() + + with self.context.expect_page() as page_info: + self.page.get_by_role( + "menuitem", name="Hub Control Panel", exact=True + ).click() + + home_page = page_info.value + home_page.wait_for_load_state() + stop_button = home_page.get_by_role("button", name="Stop My Server") + if not stop_button.is_visible(): + stop_button.wait_for(state="visible") + stop_button.click() + stop_button.wait_for(state="hidden") diff --git a/tests/common/playwright_fixtures.py b/tests/common/playwright_fixtures.py index 388f6ef4b0..03e17a5065 100644 --- a/tests/common/playwright_fixtures.py +++ b/tests/common/playwright_fixtures.py @@ -48,6 +48,10 @@ def _navigator_session(request, browser_name, pytestconfig): logger.debug(e) raise finally: + try: + nav.stop_server() + except Exception as e: + logger.debug(e) nav.teardown() From 446d790558266d5924a0eb6e6c8f1fbf7bf2ceaf Mon Sep 17 00:00:00 2001 From: Marcelo Villa Date: Tue, 6 Feb 2024 11:56:45 -0500 Subject: [PATCH 6/6] Remove JupyterHub Notebook Tests as the same functionality is being tested with Playwright and Deployment tests. --- .github/workflows/test_local_integration.yaml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/test_local_integration.yaml b/.github/workflows/test_local_integration.yaml index 8ddc1f9690..8f8e47951f 100644 --- a/.github/workflows/test_local_integration.yaml +++ b/.github/workflows/test_local_integration.yaml @@ -167,22 +167,6 @@ jobs: run: | pytest tests/tests_deployment/ -v -s - - name: JupyterHub Notebook Tests - timeout-minutes: 2 - # run jhub-client after pytest since jhubctl can cleanup - # the running server - env: - JUPYTERHUB_USERNAME: ${{ env.TEST_USERNAME }} - JUPYTERHUB_PASSWORD: ${{ env.TEST_PASSWORD }} - run: | - sleep 60 - jhubctl --verbose run --hub=https://github-actions.nebari.dev\ - --auth-type=keycloak \ - --validate --no-verify-ssl \ - --kernel python3 \ - --stop-server \ - --notebook tests/tests_deployment/assets/notebook/simple.ipynb \ - ### CLEANUP AFTER TESTS - name: Cleanup nebari deployment if: always()