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

Switch to using pytest-playwright-asyncio #1894

Open
yuvipanda opened this issue Dec 9, 2024 · 1 comment
Open

Switch to using pytest-playwright-asyncio #1894

yuvipanda opened this issue Dec 9, 2024 · 1 comment

Comments

@yuvipanda
Copy link
Collaborator

As part of #1891, we're using the sync playwright api even in our async tests. playwright's sync api is written as a wrapper on top of its async api, so we have to use some hacks to use it given we have async tests.

so we currently have: async -> sync -> async

We can switch to pytest-playwright-asyncio and cut out the middle sync part.

I spent 30min trying this out as part of #1891, with this diff:

diff --git a/dev-requirements.txt b/dev-requirements.txt
index 13e76f2..73ad164 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -12,6 +12,6 @@ pytest
 pytest-asyncio
 pytest-cov
 pytest-timeout
-pytest_playwright
+pytest-playwright-asyncio
 requests
 ruamel.yaml>=0.17.30
diff --git a/integration-tests/conftest.py b/integration-tests/conftest.py
index f5632ca..e69de29 100644
--- a/integration-tests/conftest.py
+++ b/integration-tests/conftest.py
@@ -1,6 +0,0 @@
-import nest_asyncio
-
-
-def pytest_configure(config):
-    # Required for playwright to be run from within pytest
-    nest_asyncio.apply()
diff --git a/integration-tests/test_ui.py b/integration-tests/test_ui.py
index 2e4e4f8..db4c359 100644
--- a/integration-tests/test_ui.py
+++ b/integration-tests/test_ui.py
@@ -9,9 +9,10 @@ import time
 import pytest
 import requests
 import requests.exceptions
-from playwright.sync_api import Page
+from playwright.async_api import Page
 
 from binderhub import __version__ as binder_version
+
 from binderhub.tests.utils import async_requests, random_port
 
 
@@ -104,15 +105,15 @@ async def test_loading_page(
     provider_spec = f"{provider_prefix}/{spec}"
     query = f"{path_type}path={path}" if path else ""
     uri = f"/v2/{provider_spec}?{query}"
-    r = page.goto(local_hub_local_binder + uri)
+    r = await page.goto(local_hub_local_binder + uri)
 
     assert r.status == status_code
 
     if status_code == 200:
-        assert page.query_selector("#log-container")
-        iframe = page.query_selector("#nbviewer-preview iframe")
+        assert page.locator("#log-container")
+        iframe = page.locator("#nbviewer-preview iframe")
         assert iframe is not None
-        nbviewer_url = iframe.get_attribute("src")
+        nbviewer_url = await iframe.get_attribute("src")
         r = await async_requests.get(nbviewer_url)
         assert r.status_code == 200, f"{r.status_code} {nbviewer_url}"
 
@@ -153,35 +154,35 @@ async def test_loading_page(
 async def test_main_page(
     local_hub_local_binder, page: Page, repo, ref, path, path_type, shared_url
 ):
-    resp = page.goto(local_hub_local_binder)
+    resp = await page.goto(local_hub_local_binder)
     assert resp.status == 200
 
-    page.get_by_placeholder("GitHub repository name or URL").type(repo)
+    await page.get_by_placeholder("GitHub repository name or URL").type(repo)
 
     if ref:
-        page.locator("#ref").type(ref)
+        await page.locator("#ref").type(ref)
 
     if path_type:
-        page.query_selector("#url-or-file-btn").click()
+        await page.locator("#url-or-file-btn").click()
         if path_type == "file":
-            page.locator("a:text-is('File')").click()
+            await page.locator("a:text-is('File')").click()
         elif path_type == "url":
-            page.locator("a:text-is('URL')").click()
+            await page.locator("a:text-is('URL')").click()
         else:
             raise ValueError(f"Unknown path_type {path_type}")
     if path:
-        page.locator("#filepath").type(path)
+        await page.locator("#filepath").type(path)
 
     assert (
-        page.query_selector("#basic-url-snippet").inner_text()
+        await page.locator("#basic-url-snippet").inner_text()
         == f"{local_hub_local_binder}{shared_url}"
     )
 
-
 async def test_about_page(local_hub_local_binder, page: Page):
-    r = page.goto(f"{local_hub_local_binder}about")
+    r = await page.goto(f"{local_hub_local_binder}about")
 
     assert r.status == 200
 
-    assert "This website is powered by" in page.content()
-    assert binder_version.split("+")[0] in page.content()
+    content = await page.content()
+    assert "this website is powered by" in content
+    assert binder_version.split("+")[0] in content

However, I could not get it to work - things seem to get stuck in the await page.goto.

@yuvipanda
Copy link
Collaborator Author

JupyterHub implements its own pytest fixture, however that means we don't get the ability to upload traces for debugging only on failure. We could implement that ourselves too, but using the upstream provided pytest plugin feels better longer term.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant