nonebot-plugin-htmlrender 0.6.8__tar.gz → 0.7.0a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. nonebot_plugin_htmlrender-0.7.0a2/.github/workflows/_test-os-arch.yml +67 -0
  2. nonebot_plugin_htmlrender-0.7.0a2/.github/workflows/codecov.yml +20 -0
  3. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/PKG-INFO +2 -1
  4. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/browser.py +85 -21
  5. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/config.py +14 -0
  6. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/install.py +4 -1
  7. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/pyproject.toml +2 -1
  8. nonebot_plugin_htmlrender-0.7.0a2/tests/conftest.py +42 -0
  9. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/test_htmlrender.py +2 -1
  10. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/uv.lock +313 -238
  11. nonebot_plugin_htmlrender-0.6.8/.github/workflows/codecov.yml +0 -43
  12. nonebot_plugin_htmlrender-0.6.8/tests/conftest.py +0 -15
  13. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.dockerignore +0 -0
  14. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.github/workflows/docker_image.yml +0 -0
  15. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.github/workflows/publish.yml +0 -0
  16. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.gitignore +0 -0
  17. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.pre-commit-config.yaml +0 -0
  18. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/.python-version +0 -0
  19. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/LICENSE +0 -0
  20. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/README.md +0 -0
  21. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docker-compose.yaml +0 -0
  22. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/dockerfile +0 -0
  23. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docs/example.md +0 -0
  24. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docs/html2pic.png +0 -0
  25. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docs/md2pic.png +0 -0
  26. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docs/template2pic.png +0 -0
  27. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/docs/text2pic.png +0 -0
  28. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/entrypoint.sh +0 -0
  29. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/docker-compose.yaml +0 -0
  30. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/entrypoint.sh +0 -0
  31. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/__init__.py +0 -0
  32. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/html2pic.html +0 -0
  33. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/templates/markdown.css +0 -0
  34. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/templates/mystyle.css +0 -0
  35. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/templates/progress.html.jinja2 +0 -0
  36. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/templates/text.html +0 -0
  37. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/plugins/render/utils.py +0 -0
  38. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/example/pyproject.toml +0 -0
  39. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/__init__.py +0 -0
  40. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/consts.py +0 -0
  41. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/data_source.py +0 -0
  42. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/process.py +0 -0
  43. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/signal.py +0 -0
  44. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/github-markdown-light.css +0 -0
  45. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/katex/katex.min.b64_fonts.css +0 -0
  46. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/katex/katex.min.js +0 -0
  47. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/katex/mathtex-script-type.min.js +0 -0
  48. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/katex/mhchem.min.js +0 -0
  49. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/markdown.html +0 -0
  50. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/pygments-default.css +0 -0
  51. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/text.css +0 -0
  52. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/templates/text.html +0 -0
  53. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/nonebot_plugin_htmlrender/utils.py +0 -0
  54. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/__init__.py +0 -0
  55. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/resources/test_template_filter.png +0 -0
  56. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/templates/markdown.css +0 -0
  57. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/templates/mystyle.css +0 -0
  58. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/templates/progress.html.jinja2 +0 -0
  59. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/templates/text.html +0 -0
  60. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/test_browser.py +0 -0
  61. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/test_deprecated_decorator.py +0 -0
  62. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/test_install.py +0 -0
  63. {nonebot_plugin_htmlrender-0.6.8 → nonebot_plugin_htmlrender-0.7.0a2}/tests/test_process.py +0 -0
@@ -0,0 +1,67 @@
1
+ on:
2
+ workflow_call:
3
+ inputs:
4
+ python-version:
5
+ required: true
6
+ type: string
7
+
8
+ jobs:
9
+ test:
10
+ name: Test (Py ${{ inputs.python-version }} — ${{ matrix.os_label }})
11
+ runs-on: ${{ matrix.runs_on }}
12
+ strategy:
13
+ fail-fast: true
14
+ matrix:
15
+ include:
16
+ - runs_on: ubuntu-latest
17
+ os_label: ubuntu-latest x64
18
+ arch: x64
19
+ platform: linux
20
+
21
+ - runs_on: macos-latest
22
+ os_label: macos-latest arm64
23
+ arch: arm64
24
+ platform: macos
25
+
26
+ - runs_on: windows-latest
27
+ os_label: windows-latest x64
28
+ arch: x64
29
+ platform: windows
30
+
31
+ - runs_on: ubuntu-24.04-arm
32
+ os_label: ubuntu-24.04-arm arm64
33
+ arch: arm64
34
+ platform: linux
35
+
36
+ env:
37
+ OS: ${{ matrix.os_label }}
38
+ PYTHON_VERSION: ${{ inputs.python-version }}
39
+
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+
43
+ - name: Set up uv
44
+ uses: astral-sh/setup-uv@v6
45
+ with:
46
+ python-version: ${{ inputs.python-version }}
47
+ enable-cache: true
48
+ cache-suffix: ${{ matrix.runs_on }}-${{ inputs.python-version }}
49
+
50
+ - name: Sync deps
51
+ run: uv sync --locked --all-extras --dev
52
+
53
+ - name: Install Playwright (Linux)
54
+ if: matrix.platform == 'linux'
55
+ run: uv run playwright install --with-deps && uv run playwright install --with-deps
56
+ - name: Install Playwright (non-Linux)
57
+ if: matrix.platform != 'linux'
58
+ run: uv run playwright install && uv run playwright install
59
+
60
+ - name: Run tests
61
+ run: uv run pytest -s -n auto
62
+
63
+ - name: Upload coverage to Codecov
64
+ uses: codecov/codecov-action@v5
65
+ with:
66
+ env_vars: OS,PYTHON_VERSION
67
+ verbose: true
@@ -0,0 +1,20 @@
1
+ name: Code Coverage
2
+
3
+ on:
4
+ push:
5
+ branches: [ master, dev , feat/*]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ per-python:
11
+ name: Python ${{ matrix.python-version }}
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
16
+
17
+ uses: ./.github/workflows/_test-os-arch.yml
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ secrets: inherit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nonebot-plugin-htmlrender
3
- Version: 0.6.8
3
+ Version: 0.7.0a2
4
4
  Summary: 通过浏览器渲染图片
5
5
  Project-URL: Homepage, https://github.com/kexue-z/nonebot-plugin-htmlrender
6
6
  Project-URL: Bug Tracker, https://github.com/kexue-z/nonebot-plugin-htmlrender/issues
@@ -37,6 +37,7 @@ Requires-Dist: playwright>=1.48.0
37
37
  Requires-Dist: pygments>=2.10.0
38
38
  Requires-Dist: pymdown-extensions>=9.1
39
39
  Requires-Dist: python-markdown-math>=0.8
40
+ Requires-Dist: tenacity>=9.1.2
40
41
  Description-Content-Type: text/markdown
41
42
 
42
43
  # nonebot-plugin-htmlrender
@@ -1,5 +1,5 @@
1
1
  from collections.abc import AsyncIterator
2
- from contextlib import asynccontextmanager
2
+ from contextlib import AsyncExitStack, asynccontextmanager
3
3
  from typing import Optional
4
4
 
5
5
  from nonebot.log import logger
@@ -10,6 +10,7 @@ from playwright.async_api import (
10
10
  Playwright,
11
11
  async_playwright,
12
12
  )
13
+ from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_fixed
13
14
 
14
15
  from nonebot_plugin_htmlrender.config import plugin_config
15
16
  from nonebot_plugin_htmlrender.install import install_browser
@@ -127,7 +128,30 @@ async def _connect(browser_type: str, **kwargs) -> Browser:
127
128
  if _playwright is not None:
128
129
  return await _browser_cls.connect(**kwargs)
129
130
  else:
130
- raise RuntimeError("Playwright 未初始化")
131
+ raise RuntimeError("Playwright is not initialized")
132
+
133
+
134
+ @retry(
135
+ retry=retry_if_exception_type(RuntimeError),
136
+ stop=stop_after_attempt(4),
137
+ wait=wait_fixed(1),
138
+ reraise=True,
139
+ before_sleep=lambda retry_state: logger.warning(
140
+ f"Attempt {retry_state.attempt_number} failed, retrying..."
141
+ ),
142
+ )
143
+ async def _check_env_with_install_retry(**kwargs):
144
+ try:
145
+ return await check_playwright_env(**kwargs)
146
+ except RuntimeError:
147
+ if plugin_config.htmlrender_ci_mode:
148
+ raise
149
+ try:
150
+ await install_browser()
151
+ except Exception as e:
152
+ logger.error(f"Browser installation failed: {e!s}")
153
+ raise RuntimeError(f"install_browser failed: {e}") from e
154
+ raise
131
155
 
132
156
 
133
157
  @with_lock
@@ -144,8 +168,10 @@ async def startup_htmlrender(**kwargs) -> Browser:
144
168
  global _browser, _playwright
145
169
 
146
170
  await shutdown_htmlrender()
147
- clean_playwright_cache()
148
- _prepare_playwright_env_vars()
171
+
172
+ if not plugin_config.htmlrender_ci_mode:
173
+ clean_playwright_cache()
174
+ _prepare_playwright_env_vars()
149
175
 
150
176
  _playwright = await async_playwright().start()
151
177
  logger.debug("Playwright started")
@@ -177,31 +203,69 @@ async def startup_htmlrender(**kwargs) -> Browser:
177
203
  f" '{plugin_config.htmlrender_browser_executable_path}': {e}"
178
204
  ) from e
179
205
  else:
180
- try:
181
- _browser = await check_playwright_env(**kwargs)
182
- except RuntimeError:
183
- await install_browser()
184
- _browser = await check_playwright_env(**kwargs)
206
+ _browser = await _check_env_with_install_retry(**kwargs)
185
207
 
186
208
  return _browser
187
209
 
188
210
 
189
211
  async def shutdown_htmlrender() -> None:
190
- """关闭浏览器和 Playwright 实例。"""
191
- if _browser:
192
- if not _browser.is_connected():
193
- logger.info("Browser was already disconnected, skipping close.")
194
- else:
195
- with suppress_and_log():
196
- logger.debug("Disconnecting browser...")
197
- await _browser.close()
198
- logger.info("Disconnected browser.")
199
- if _playwright:
212
+ is_remote = bool(
213
+ plugin_config.htmlrender_connect or plugin_config.htmlrender_connect_over_cdp
214
+ )
215
+ async with AsyncExitStack() as stack:
216
+ await _schedule_browser_shutdown(stack, is_remote=is_remote)
217
+ await _schedule_playwright_shutdown(stack)
218
+ _clear_globals()
219
+
220
+
221
+ async def _schedule_browser_shutdown(stack: AsyncExitStack, *, is_remote: bool) -> None:
222
+ global _browser
223
+ if not _browser:
224
+ return
225
+
226
+ should_close = (not is_remote) and plugin_config.htmlrender_shutdown_browser_on_exit
227
+ if not should_close:
228
+ logger.info(
229
+ "Skipping browser shutdown due to configuration or remote connection."
230
+ )
231
+ return
232
+
233
+ browser = _browser
234
+ if not browser.is_connected():
235
+ logger.info("Browser was already disconnected.")
236
+ return
237
+
238
+ logger.debug("Disconnecting browser...")
239
+
240
+ async def _close_browser():
241
+ with suppress_and_log():
242
+ await browser.close()
243
+ logger.info("Disconnected browser.")
244
+
245
+ stack.push_async_callback(_close_browser)
246
+
247
+
248
+ async def _schedule_playwright_shutdown(stack: AsyncExitStack) -> None:
249
+ global _playwright
250
+ if not _playwright:
251
+ return
252
+
253
+ pw = _playwright
254
+ logger.debug("Stopping Playwright...")
255
+
256
+ async def _stop_pw():
200
257
  with suppress_and_log():
201
- logger.debug("Stopping Playwright...")
202
- await _playwright.stop()
258
+ await pw.stop()
203
259
  logger.info("Playwright stopped.")
204
260
 
261
+ stack.push_async_callback(_stop_pw)
262
+
263
+
264
+ def _clear_globals() -> None:
265
+ global _browser, _playwright
266
+ _browser = None
267
+ _playwright = None
268
+
205
269
 
206
270
  async def check_playwright_env(**kwargs) -> Browser:
207
271
  """
@@ -3,6 +3,7 @@ from typing import Any, Optional
3
3
 
4
4
  from nonebot import get_driver, get_plugin_config
5
5
  from nonebot.compat import model_validator
6
+ from nonebot.log import logger
6
7
  import nonebot_plugin_localstore as store
7
8
  from pydantic import BaseModel, Field
8
9
 
@@ -32,6 +33,14 @@ class Config(BaseModel):
32
33
  default=plugin_config_dir,
33
34
  description="配置路径,不填则使用 `nonebot-plugin-localstore` 管理",
34
35
  )
36
+ htmlrender_shutdown_browser_on_exit: bool = Field(
37
+ default=True,
38
+ description="在插件关闭时关闭浏览器实例,在连接到远程浏览器时默认为 False。",
39
+ )
40
+ htmlrender_ci_mode: bool = Field(
41
+ default=False,
42
+ description="启用CI模式,跳过浏览器安装和环境变量",
43
+ )
35
44
  htmlrender_download_host: Optional[str] = Field(
36
45
  default=None, description="下载Playwright浏览器时的主机地址。"
37
46
  )
@@ -93,3 +102,8 @@ class Config(BaseModel):
93
102
 
94
103
  global_config = get_driver().config
95
104
  plugin_config = get_plugin_config(Config)
105
+
106
+ if plugin_config.htmlrender_ci_mode:
107
+ logger.info(
108
+ "CI mode enabled, skipping browser installation and environment variable setup."
109
+ )
@@ -4,6 +4,7 @@ from contextlib import asynccontextmanager
4
4
  import os
5
5
  from typing import Callable, Optional
6
6
  from urllib.parse import urlparse
7
+ import sys
7
8
 
8
9
  from nonebot import logger
9
10
 
@@ -171,6 +172,8 @@ async def execute_install_command(timeout: int) -> tuple[bool, str]:
171
172
  install_signal_handler()
172
173
 
173
174
  process = await create_process(
175
+ sys.executable,
176
+ "-m",
174
177
  "playwright",
175
178
  "install",
176
179
  "--with-deps",
@@ -202,7 +205,7 @@ async def execute_install_command(timeout: int) -> tuple[bool, str]:
202
205
  asyncio.gather(stdout_task, stderr_task), timeout=timeout
203
206
  )
204
207
  except asyncio.TimeoutError:
205
- logger.error(f"Timed out ({timeout})")
208
+ logger.error(f"Timed out ({timeout}s)")
206
209
  await terminate_process(process)
207
210
  return False, f"Timed out ({timeout}s)"
208
211
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nonebot-plugin-htmlrender"
3
- version = "0.6.8"
3
+ version = "0.7.0.alpha.2"
4
4
  description = "通过浏览器渲染图片"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "kexue", email = "x@kexue-cloud.cn" }]
@@ -16,6 +16,7 @@ dependencies = [
16
16
  "pygments>=2.10.0",
17
17
  "pymdown-extensions>=9.1",
18
18
  "python-markdown-math>=0.8",
19
+ "tenacity>=9.1.2",
19
20
  ]
20
21
 
21
22
  [project.urls]
@@ -0,0 +1,42 @@
1
+ import gc
2
+
3
+ import anyio
4
+ import nonebot
5
+ from nonebug import NONEBOT_INIT_KWARGS
6
+ import pytest
7
+ from pytest_asyncio import is_async_test
8
+
9
+
10
+ def pytest_configure(config: pytest.Config) -> None:
11
+ config.stash[NONEBOT_INIT_KWARGS] = {
12
+ "superusers": {"10001"},
13
+ "command_start": {""},
14
+ "log_level": "DEBUG",
15
+ "htmlrender_ci_mode": True,
16
+ }
17
+
18
+
19
+ def pytest_collection_modifyitems(items: list[pytest.Item]):
20
+ pytest_asyncio_tests = (item for item in items if is_async_test(item))
21
+ session_scope_marker = pytest.mark.asyncio(loop_scope="session")
22
+ for async_test in pytest_asyncio_tests:
23
+ async_test.add_marker(session_scope_marker, append=False)
24
+
25
+
26
+ @pytest.fixture(scope="session", autouse=True)
27
+ async def after_nonebot_init(after_nonebot_init: None):
28
+ nonebot.require("nonebot_plugin_htmlrender")
29
+
30
+
31
+ @pytest.fixture(scope="session", autouse=True)
32
+ async def _cleanup_playwright_session():
33
+ from nonebot_plugin_htmlrender import shutdown_htmlrender
34
+
35
+ yield
36
+
37
+ await shutdown_htmlrender()
38
+
39
+ gc.collect()
40
+ gc.collect()
41
+
42
+ await anyio.lowlevel.checkpoint()
@@ -152,7 +152,8 @@ async def test_capture_element(mocker: MockerFixture) -> None:
152
152
 
153
153
  mock_page = mocker.AsyncMock()
154
154
  mock_page.goto = mocker.AsyncMock()
155
- mock_page.on = mocker.AsyncMock()
155
+ mock_page.on = mocker.MagicMock()
156
+ mock_page.off = mocker.MagicMock()
156
157
  mock_page.locator = mocker.MagicMock(return_value=mock_locator)
157
158
 
158
159
  mock_cm = mocker.MagicMock()