diff --git a/README.md b/README.md index c1f9ce8..ed7aed0 100644 --- a/README.md +++ b/README.md @@ -15,33 +15,33 @@ pip install pytest-playwright-async [Here](https://github.com/m9810223/playwright-async-pytest/blob/master/tests) you can find more examples. -```py -# tests/conftest.py +--- -import asyncio +```py +# tests/async/conftest.py -import nest_asyncio # pip install nest-asyncio import pytest -@pytest.fixture(scope='session', autouse=True) -def event_loop(): - policy = asyncio.get_event_loop_policy() - loop = policy.new_event_loop() - nest_asyncio._patch_loop(loop) # * - yield loop - loop.close() - - -@pytest.fixture(scope='session', autouse=True) -# pip install anyio -def anyio_backend(): - return 'asyncio' +# install anyio +# install uvloop +@pytest.fixture( + scope='session', + params=[ + # https://anyio.readthedocs.io/en/stable/testing.html#specifying-the-backends-to-run-on + pytest.param(('asyncio', {'use_uvloop': True}), id='asyncio+uvloop'), + pytest.param(('asyncio', {'use_uvloop': False}), id='asyncio'), + # pytest.param(('trio', {'restrict_keyboard_interrupt_to_checkpoints': True}), id='trio'), + ], + autouse=True, +) +def anyio_backend(request): + return request.param ``` ```py -# tests/test_for_readme.py +# tests/async/test_for_readme.py from playwright.async_api import Page diff --git a/pdm.lock b/pdm.lock index 49f9d08..b549176 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = [] lock_version = "4.5.0" -content_hash = "sha256:7bea02e190c372ba0ae50280ee1d22b616da7ce00807ba080dd3a98142098371" +content_hash = "sha256:c75b60c24c01156049ed61d9b305840f3651e3ac7111daaea3f765393a67f87c" [[metadata.targets]] requires_python = ">=3.8" @@ -618,6 +618,45 @@ files = [ {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, ] +[[package]] +name = "uvloop" +version = "0.20.0" +requires_python = ">=3.8.0" +summary = "Fast implementation of asyncio event loop on top of libuv" +files = [ + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996"}, + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66"}, + {file = "uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469"}, +] + [[package]] name = "wcwidth" version = "0.2.13" diff --git a/pyproject.toml b/pyproject.toml index aed21a0..0f99e44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,8 +26,9 @@ distribution = true dev = [ "pytest", "ipython<8.13.1", - "nest-asyncio", "anyio<4.6.0", + "nest-asyncio", + "uvloop", ] [tool.pdm.scripts] diff --git a/tests/async/__init__.py b/tests/async/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/async/conftest.py b/tests/async/conftest.py new file mode 100644 index 0000000..6128f3c --- /dev/null +++ b/tests/async/conftest.py @@ -0,0 +1,17 @@ +import pytest + + +# install anyio +# install uvloop +@pytest.fixture( + scope='session', + params=[ + # https://anyio.readthedocs.io/en/stable/testing.html#specifying-the-backends-to-run-on + pytest.param(('asyncio', {'use_uvloop': True}), id='asyncio+uvloop'), + pytest.param(('asyncio', {'use_uvloop': False}), id='asyncio'), + # pytest.param(('trio', {'restrict_keyboard_interrupt_to_checkpoints': True}), id='trio'), + ], + autouse=True, +) +def anyio_backend(request): + return request.param diff --git a/tests/test_for_readme.py b/tests/async/test_for_readme.py similarity index 100% rename from tests/test_for_readme.py rename to tests/async/test_for_readme.py diff --git a/tests/test_from_playwright_docs.py b/tests/async/test_from_playwright_docs.py similarity index 100% rename from tests/test_from_playwright_docs.py rename to tests/async/test_from_playwright_docs.py diff --git a/tests/test_playwright.py b/tests/async/test_playwright.py similarity index 54% rename from tests/test_playwright.py rename to tests/async/test_playwright.py index 78fc449..3d6f8e0 100644 --- a/tests/test_playwright.py +++ b/tests/async/test_playwright.py @@ -1,17 +1,13 @@ +import asyncio import typing as t +import nest_asyncio # install nest-asyncio from playwright.async_api import Browser from playwright.async_api import BrowserContext from playwright.async_api import BrowserType from playwright.async_api import Page from playwright.async_api import Playwright from playwright.async_api import async_playwright -from playwright.sync_api import Browser as SBrowser -from playwright.sync_api import BrowserContext as SBrowserContext -from playwright.sync_api import BrowserType as SBrowserType -from playwright.sync_api import Page as SPage -from playwright.sync_api import Playwright as SPlaywright -from playwright.sync_api import sync_playwright import pytest @@ -22,7 +18,15 @@ def check_title(title): assert 'Playwright' in title -async def test_async_playwright(): +@pytest.fixture +def event_loop(): + loop = asyncio.get_event_loop_policy().new_event_loop() + nest_asyncio.apply(loop) + yield loop + loop.close() + + +async def test_async_playwright(event_loop): async with async_playwright() as playwright: async with await playwright.chromium.launch() as browser: async with await browser.new_context() as context: @@ -31,16 +35,6 @@ async def test_async_playwright(): check_title(await page.title()) -@pytest.mark.skip(reason='Not working') -def test_sync_playwright(): - with sync_playwright() as playwright: - with playwright.chromium.launch() as browser: - with browser.new_context() as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - # https://playwright.dev/python/docs/test-runners#fixtures @@ -49,71 +43,36 @@ async def test_is_working_playwright_async(playwright_async: Playwright): assert isinstance(playwright_async, Playwright) -def test_is_working_playwright_sync(playwright: SPlaywright): - print(f'\n{playwright = }') - assert isinstance(playwright, SPlaywright) - - async def test_is_working_browser_async(browser_async: Browser): print(f'\n{browser_async = }') assert isinstance(browser_async, Browser) -def test_is_working_browser_sync(browser: SBrowser): - print(f'\n{browser = }') - assert isinstance(browser, SBrowser) - - async def test_is_working_browser_name_async(browser_name: str): print(f'\n{browser_name = }') assert isinstance(browser_name, str) -def test_is_working_browser_name(browser_name: str): - print(f'\n{browser_name = }') - assert isinstance(browser_name, str) - - async def test_is_working_browser_channel_async(browser_channel: t.Optional[str]): print(f'\n{browser_channel = }') assert isinstance(browser_channel, str) or browser_channel is None -def test_is_working_browser_channel(browser_channel: t.Optional[str]): - print(f'\n{browser_channel = }') - assert isinstance(browser_channel, str) or browser_channel is None - - async def test_is_working_context_async(context_async: BrowserContext): print(f'\n{context_async = }') assert isinstance(context_async, BrowserContext) -def test_is_working_context_sync(context: SBrowserContext): - print(f'\n{context = }') - assert isinstance(context, SBrowserContext) - - async def test_is_working_browser_context_args_async(browser_context_args_async: dict): print(f'\n{browser_context_args_async = }') assert isinstance(browser_context_args_async, dict) -def test_is_working_browser_context_args_sync(browser_context_args: dict): - print(f'\n{browser_context_args = }') - assert isinstance(browser_context_args, dict) - - async def test_is_working_page_async(page_async: Page): print(f'\n{page_async = }') assert isinstance(page_async, Page) -def test_is_working_page_sync(page: SPage): - print(f'\n{page = }') - assert isinstance(page, SPage) - - ### @@ -127,17 +86,6 @@ async def test_browser_context_args_async(browser_context_args_async: t.Dict): check_title(await page.title()) -@pytest.mark.skip(reason='Not working') -def test_browser_context_args_sync(browser_context_args: t.Dict): - print(f'\n{browser_context_args, type(browser_context_args) = }') - with sync_playwright() as playwright: - with playwright.chromium.launch() as browser: - with browser.new_context(**browser_context_args) as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_playwright_async(playwright_async: Playwright): print(f'\n{playwright_async, type(playwright_async) = }') async with await playwright_async.chromium.launch() as browser: @@ -147,15 +95,6 @@ async def test_playwright_async(playwright_async: Playwright): check_title(await page.title()) -def test_playwright_sync(playwright: SPlaywright): - print(f'\n{playwright, type(playwright) = }') - with playwright.chromium.launch() as browser: - with browser.new_context() as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_browser_type_async(browser_type_async: BrowserType): print(f'\n{browser_type_async, type(browser_type_async) = }') async with await browser_type_async.launch() as browser: @@ -165,15 +104,6 @@ async def test_browser_type_async(browser_type_async: BrowserType): check_title(await page.title()) -def test_browser_type_sync(browser_type: SBrowserType): - print(f'\n{browser_type, type(browser_type) = }') - with browser_type.launch() as browser: - with browser.new_context() as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_launch_browser_async(launch_browser_async: t.Callable[..., t.Awaitable[Browser]]): print(f'\n{launch_browser_async, type(launch_browser_async) = }') browser = await launch_browser_async() @@ -183,15 +113,6 @@ async def test_launch_browser_async(launch_browser_async: t.Callable[..., t.Awai check_title(await page.title()) -def test_launch_browser_sync(launch_browser: t.Callable[..., SBrowser]): - print(f'\n{launch_browser, type(launch_browser) = }') - browser = launch_browser() - with browser.new_context() as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_browser_async(browser_async: Browser): print(f'\n{browser_async, type(browser_async) = }') async with await browser_async.new_context() as context: @@ -200,14 +121,6 @@ async def test_browser_async(browser_async: Browser): check_title(await page.title()) -def test_browser_sync(browser: SBrowser): - print(f'\n{browser, type(browser) = }') - with browser.new_context() as context: - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_context_async(context_async: BrowserContext): print(f'\n{context_async = }') async with await context_async.new_page() as page: @@ -215,20 +128,7 @@ async def test_context_async(context_async: BrowserContext): check_title(await page.title()) -def test_context_sync(context: SBrowserContext): - print(f'\n{context = }') - with context.new_page() as page: - page.goto(URL) - check_title(page.title()) - - async def test_page_async(page_async: Page): print(f'\n{page_async = }') await page_async.goto(URL) check_title(await page_async.title()) - - -def test_page_sync(page: SPage): - print(f'\n{page = }') - page.goto(URL) - check_title(page.title()) diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index f1782fd..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,19 +0,0 @@ -import asyncio - -import nest_asyncio # pip install nest-asyncio -import pytest - - -@pytest.fixture(scope='session', autouse=True) -def event_loop(): - policy = asyncio.get_event_loop_policy() - loop = policy.new_event_loop() - nest_asyncio._patch_loop(loop) # * - yield loop - loop.close() - - -@pytest.fixture(scope='session', autouse=True) -# pip install anyio -def anyio_backend(): - return 'asyncio' diff --git a/tests/sync/__init__.py b/tests/sync/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/sync/test_for_readme.py b/tests/sync/test_for_readme.py new file mode 100644 index 0000000..481c321 --- /dev/null +++ b/tests/sync/test_for_readme.py @@ -0,0 +1,7 @@ +from playwright.sync_api import Page + + +def test_page_async(page: Page): + print(f'\n{page = }') + page.goto('https://playwright.dev/') + assert 'Playwright' in page.title() diff --git a/tests/sync/test_from_playwright_docs.py b/tests/sync/test_from_playwright_docs.py new file mode 100644 index 0000000..e882542 --- /dev/null +++ b/tests/sync/test_from_playwright_docs.py @@ -0,0 +1,25 @@ +""" +https://playwright.dev/python/docs/writing-tests#first-test +""" + +import re + +from playwright.sync_api import Page +from playwright.sync_api import expect + + +def test_has_title(page: Page): + page.goto('https://playwright.dev/') + + # Expect a title "to contain" a substring. + expect(page).to_have_title(re.compile('Playwright')) + + +def test_get_started_link(page: Page): + page.goto('https://playwright.dev/') + + # Click the get started link. + page.get_by_role('link', name='Get started').click() + + # Expects page to have a heading with the name of Installation. + expect(page.get_by_role('heading', name='Installation')).to_be_visible() diff --git a/tests/sync/test_playwright.py b/tests/sync/test_playwright.py new file mode 100644 index 0000000..eb3d0b3 --- /dev/null +++ b/tests/sync/test_playwright.py @@ -0,0 +1,126 @@ +import typing as t + +from playwright.sync_api import Browser as SBrowser +from playwright.sync_api import BrowserContext as SBrowserContext +from playwright.sync_api import BrowserType as SBrowserType +from playwright.sync_api import Page as SPage +from playwright.sync_api import Playwright as SPlaywright +from playwright.sync_api import sync_playwright +import pytest + + +URL = 'https://playwright.dev/' + + +def check_title(title): + assert 'Playwright' in title + + +@pytest.mark.xfail(reason='Not working') +def test_sync_playwright(): + with sync_playwright() as playwright: + with playwright.chromium.launch() as browser: + with browser.new_context() as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +# https://playwright.dev/python/docs/test-runners#fixtures + + +def test_is_working_playwright_sync(playwright: SPlaywright): + print(f'\n{playwright = }') + assert isinstance(playwright, SPlaywright) + + +def test_is_working_browser_sync(browser: SBrowser): + print(f'\n{browser = }') + assert isinstance(browser, SBrowser) + + +def test_is_working_browser_name(browser_name: str): + print(f'\n{browser_name = }') + assert isinstance(browser_name, str) + + +def test_is_working_browser_channel(browser_channel: t.Optional[str]): + print(f'\n{browser_channel = }') + assert isinstance(browser_channel, str) or browser_channel is None + + +def test_is_working_context_sync(context: SBrowserContext): + print(f'\n{context = }') + assert isinstance(context, SBrowserContext) + + +def test_is_working_browser_context_args_sync(browser_context_args: dict): + print(f'\n{browser_context_args = }') + assert isinstance(browser_context_args, dict) + + +def test_is_working_page_sync(page: SPage): + print(f'\n{page = }') + assert isinstance(page, SPage) + + +### + + +@pytest.mark.xfail(reason='Not working') +def test_browser_context_args_sync(browser_context_args: t.Dict): + print(f'\n{browser_context_args, type(browser_context_args) = }') + with sync_playwright() as playwright: + with playwright.chromium.launch() as browser: + with browser.new_context(**browser_context_args) as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_playwright_sync(playwright: SPlaywright): + print(f'\n{playwright, type(playwright) = }') + with playwright.chromium.launch() as browser: + with browser.new_context() as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_browser_type_sync(browser_type: SBrowserType): + print(f'\n{browser_type, type(browser_type) = }') + with browser_type.launch() as browser: + with browser.new_context() as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_launch_browser_sync(launch_browser: t.Callable[..., SBrowser]): + print(f'\n{launch_browser, type(launch_browser) = }') + browser = launch_browser() + with browser.new_context() as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_browser_sync(browser: SBrowser): + print(f'\n{browser, type(browser) = }') + with browser.new_context() as context: + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_context_sync(context: SBrowserContext): + print(f'\n{context = }') + with context.new_page() as page: + page.goto(URL) + check_title(page.title()) + + +def test_page_sync(page: SPage): + print(f'\n{page = }') + page.goto(URL) + check_title(page.title())