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