1from __future__ import annotations
2
3from collections.abc import Generator
4from typing import Any
5
6import pytest
7from plain.runtime import settings as plain_settings
8from plain.runtime import setup
9
10from .browser import TestBrowser
11
12
13def pytest_configure(config: Any) -> None:
14 # Run Plain setup before anything else
15 setup()
16
17
18class SettingsProxy:
19 def __init__(self) -> None:
20 self._original: dict[str, Any] = {}
21
22 def __getattr__(self, name: str) -> Any:
23 return getattr(plain_settings, name)
24
25 def __setattr__(self, name: str, value: Any) -> None:
26 if name.startswith("_"):
27 super().__setattr__(name, value)
28 else:
29 if name not in self._original:
30 self._original[name] = getattr(plain_settings, name, None)
31 setattr(plain_settings, name, value)
32
33 def _restore(self) -> None:
34 for key, value in self._original.items():
35 setattr(plain_settings, key, value)
36
37
38@pytest.fixture
39def settings() -> Generator[SettingsProxy, None, None]:
40 proxy = SettingsProxy()
41 yield proxy
42 proxy._restore()
43
44
45@pytest.fixture
46def testbrowser(browser: Any, request: Any) -> Generator[TestBrowser, None, None]:
47 """Use playwright and pytest-playwright to run browser tests against a test server."""
48 try:
49 # Check if isolated_db fixture is available from the plain-models package.
50 # If it is, then we need to run a server that has a database connection to the isolated database for this test.
51 request.getfixturevalue("isolated_db")
52
53 from plain.models import db_connection
54 from plain.models.database_url import build_database_url
55
56 # Get a database url for the isolated db that we can have the plain server connect to also.
57 database_url = build_database_url(db_connection.settings_dict)
58 except pytest.FixtureLookupError:
59 # isolated_db fixture not available, use empty database_url
60 database_url = ""
61
62 testbrowser = TestBrowser(browser=browser, database_url=database_url)
63
64 try:
65 testbrowser.run_server()
66 yield testbrowser
67 finally:
68 testbrowser.cleanup_server()