Skip to main content

tests/test_browser_fixtures.py

1"""
2Tests for `chives.browser_fixtures`.
3"""
5import os
6from pathlib import Path
7import subprocess
9from playwright.sync_api import sync_playwright
10import pytest
11from pytest import Pytester
14git_root_cmd = ["git", "rev-parse", "--show-toplevel"]
15GIT_ROOT = subprocess.check_output(git_root_cmd, text=True).strip()
18@pytest.fixture(scope="session")
19def playwright_browsers_path() -> str:
20 """
21 Return the cache directory where Playwright browsers are installed.
22 """
23 with sync_playwright() as p:
24 # In my local builds, this returns a path like:
25 #
26 # ~/Library/Caches/ms-playwright/webkit-2272/pw_run.sh
27 #
28 # Unwrap two levels to get to the `ms-playwright` folder.
29 return str(Path(p.webkit.executable_path).parent.parent)
32@pytest.fixture
33def playwright_pytester(pytester: Pytester, playwright_browsers_path: str) -> Pytester:
34 """
35 Return a `Pytester` instance for which tests have access to the
36 `browser` and `page` fixtures, and which use the shared Playwright cache.
37 """
38 if "SKIP_PLAYWRIGHT" in os.environ: # pragma: no cover
39 pytest.skip(reason="skip slow Playwright tests")
41 pytester.makeconftest(f"""
42 import os
44 from chives.browser_fixtures import browser, page
46 os.environ["PLAYWRIGHT_BROWSERS_PATH"] = {playwright_browsers_path!r}
47 """)
49 return pytester
52class TestBrowserFixture:
53 """
54 Tests for the `browser` fixture.
55 """
57 def test_browser_fixture(self, playwright_pytester: Pytester) -> None:
58 """
59 Test the browser fixture.
60 """
61 playwright_pytester.makefile(".html", greeting="<p>Hello world!</p>")
62 playwright_pytester.makepyfile(
63 """
64 from playwright.sync_api import Browser, expect
65 from chives.browser_fixtures import file_uri
68 def test_browser(browser: Browser) -> None:
69 uri = file_uri("greeting.html")
71 p = browser.new_page()
72 p.goto(uri)
73 expect(p.get_by_text("Hello world!")).to_be_visible()
74 """
75 )
76 playwright_pytester.runpytest().assert_outcomes(passed=1)
79class TestPageFixture:
80 """
81 Tests for the `page` fixture.
82 """
84 def test_okay_page(self, playwright_pytester: Pytester) -> None:
85 """
86 Open a page and make a successful assertion about the contents.
87 """
88 playwright_pytester.makefile(".html", greeting="<p>Hello world!</p>")
89 playwright_pytester.makepyfile(
90 """
91 from playwright.sync_api import Page, expect
92 from chives.browser_fixtures import file_uri
95 def test_page(page: Page) -> None:
96 uri = file_uri("greeting.html")
97 page.goto(uri)
98 expect(page.get_by_text("Hello world!")).to_be_visible()
99 """
100 )
101 playwright_pytester.runpytest().assert_outcomes(passed=1)
103 @pytest.mark.parametrize(
104 "html",
105 [
106 pytest.param("<script>invalid</script>", id="invalid_js"),
107 pytest.param("<script>console.warn('BOOM')</script>", id="console_warning"),
108 pytest.param("<script>console.warn('BOOM')</script>", id="console_error"),
109 pytest.param("<img src='doesnotexist.jpg'>", id="missing_image"),
110 ],
111 )
112 def test_page_with_error(self, html: str, playwright_pytester: Pytester) -> None:
113 """
114 Open a page with errors/warnings, and check the fixture reports
115 an error.
116 """
117 playwright_pytester.makefile(".html", error=html)
118 playwright_pytester.makepyfile(
119 """
120 from playwright.sync_api import Page
121 from chives.browser_fixtures import file_uri
124 def test_page(page: Page) -> None:
125 uri = file_uri("error.html")
126 page.goto(uri)
127 """
128 )
129 playwright_pytester.runpytest().assert_outcomes(passed=1, errors=1)
131 def test_non_existent_page_is_error(self, playwright_pytester: Pytester) -> None:
132 """
133 Opening a non-existent file with the `page` fixture fails the test.
134 """
135 playwright_pytester.makepyfile(
136 """
137 from playwright.sync_api import Page
138 from chives.browser_fixtures import file_uri
141 def test_page(page: Page) -> None:
142 uri = file_uri("does_not_exist.html")
143 page.goto(uri)
144 """
145 )
146 playwright_pytester.runpytest().assert_outcomes(failed=1)
149def test_skip_playwright(pytester: Pytester) -> None:
150 """
151 If the SKIP_PLAYWRIGHT environment variable is set, the test is skipped.
152 """
153 pytester.makeconftest("""
154 import os
156 from chives.browser_fixtures import browser, page
158 os.environ["SKIP_PLAYWRIGHT"] = "true"
159 """)
160 pytester.makepyfile(
161 """
162 from playwright.sync_api import Browser, Page
165 def test_browser(browser: Browser) -> None:
166 pass
169 def test_page(page: Page) -> None:
170 pass
171 """
172 )
173 pytester.runpytest().assert_outcomes(skipped=2)