aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/tests/conftest.py
blob: 8ef91892aace60084168f4aeb467ea810932c94a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""
Every test runs with its own home, and never touches the developer's own.

Redirecting HOME alone isolates nothing on Windows — `Path.home()` reads
USERPROFILE there, and the CLI's directories come from LOCALAPPDATA — so all of
them are pointed at a throwaway directory. The OS key storage is replaced by
keyring's refusing backend: a test must never write into the developer's real
credential store, and the store's file fallback is what a headless machine uses
anyway. A test that needs a working key storage installs its own backend.
"""

import logging

import pytest


@pytest.fixture(autouse=True)
def isolated_home(tmp_path, monkeypatch):
    home = tmp_path / "home"
    home.mkdir()
    for var in ("HOME", "USERPROFILE"):
        monkeypatch.setenv(var, str(home))
    for var, sub in (("APPDATA", "AppData/Roaming"), ("LOCALAPPDATA", "AppData/Local"),
                     ("XDG_CONFIG_HOME", ".config"), ("XDG_DATA_HOME", ".local/share")):
        monkeypatch.setenv(var, str(home / sub))
    for var in ("MESHBAY_CLI_HOME", "MESHBAY_HUB", "MESHBAY_USER", "MESHBAY_PASSWORD"):
        monkeypatch.delenv(var, raising=False)
    monkeypatch.setenv("PYTHON_KEYRING_BACKEND", "keyring.backends.fail.Keyring")
    return home


@pytest.fixture(autouse=True)
def restored_logging():
    """`main()` configures logging, as an entry point does; a test that calls it
    in-process must not leave that configuration to the next package's tests."""
    root = logging.getLogger()
    names = ("meshbay_cli", "aiortc", "aioice", "httpx", "httpcore")
    saved = (list(root.handlers), root.level, root.disabled,
             {n: logging.getLogger(n).level for n in names})
    yield
    handlers, level, disabled, levels = saved
    for h in root.handlers:
        if h not in handlers:
            h.close()
    root.handlers[:] = handlers
    root.setLevel(level)
    root.disabled = disabled
    for n, lv in levels.items():
        logging.getLogger(n).setLevel(lv)