rename ui to clan-app and move clan-app one layer up
This commit is contained in:
66
pkgs/clan-app/tests/command.py
Normal file
66
pkgs/clan-app/tests/command.py
Normal file
@@ -0,0 +1,66 @@
|
||||
import contextlib
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import IO, Any
|
||||
|
||||
import pytest
|
||||
|
||||
_FILE = None | int | IO[Any]
|
||||
|
||||
|
||||
class Command:
|
||||
def __init__(self) -> None:
|
||||
self.processes: list[subprocess.Popen[str]] = []
|
||||
|
||||
def run(
|
||||
self,
|
||||
command: list[str],
|
||||
extra_env: dict[str, str] | None = None,
|
||||
stdin: _FILE = None,
|
||||
stdout: _FILE = None,
|
||||
stderr: _FILE = None,
|
||||
workdir: Path | None = None,
|
||||
) -> subprocess.Popen[str]:
|
||||
if extra_env is None:
|
||||
extra_env = {}
|
||||
env = os.environ.copy()
|
||||
env.update(extra_env)
|
||||
# We start a new session here so that we can than more reliably kill all children as well
|
||||
p = subprocess.Popen(
|
||||
command,
|
||||
env=env,
|
||||
start_new_session=True,
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
stdin=stdin,
|
||||
text=True,
|
||||
cwd=workdir,
|
||||
)
|
||||
self.processes.append(p)
|
||||
return p
|
||||
|
||||
def terminate(self) -> None:
|
||||
# Stop in reverse order in case there are dependencies.
|
||||
# We just kill all processes as quickly as possible because we don't
|
||||
# care about corrupted state and want to make tests fasts.
|
||||
for p in reversed(self.processes):
|
||||
with contextlib.suppress(OSError):
|
||||
os.killpg(os.getpgid(p.pid), signal.SIGKILL)
|
||||
p.wait()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def command() -> Iterator[Command]:
|
||||
"""
|
||||
Starts a background command. The process is automatically terminated in the end.
|
||||
>>> p = command.run(["some", "daemon"])
|
||||
>>> print(p.pid)
|
||||
"""
|
||||
c = Command()
|
||||
try:
|
||||
yield c
|
||||
finally:
|
||||
c.terminate()
|
||||
40
pkgs/clan-app/tests/conftest.py
Normal file
40
pkgs/clan-app/tests/conftest.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from clan_cli.custom_logger import setup_logging
|
||||
from clan_cli.nix import nix_shell
|
||||
|
||||
pytest_plugins = [
|
||||
"temporary_dir",
|
||||
"root",
|
||||
"command",
|
||||
"wayland",
|
||||
]
|
||||
|
||||
|
||||
# Executed on pytest session start
|
||||
def pytest_sessionstart(session: pytest.Session) -> None:
|
||||
# This function will be called once at the beginning of the test session
|
||||
print("Starting pytest session")
|
||||
# You can access the session config, items, testsfailed, etc.
|
||||
print(f"Session config: {session.config}")
|
||||
|
||||
setup_logging(level="DEBUG")
|
||||
|
||||
|
||||
# fixture for git_repo
|
||||
@pytest.fixture
|
||||
def git_repo(tmp_path: Path) -> Path:
|
||||
# initialize a git repository
|
||||
cmd = nix_shell(["git"], ["git", "init"])
|
||||
subprocess.run(cmd, cwd=tmp_path, check=True)
|
||||
# set user.name and user.email
|
||||
cmd = nix_shell(["git"], ["git", "config", "user.name", "test"])
|
||||
subprocess.run(cmd, cwd=tmp_path, check=True)
|
||||
cmd = nix_shell(["git"], ["git", "config", "user.email", "test@test.test"])
|
||||
subprocess.run(cmd, cwd=tmp_path, check=True)
|
||||
# return the path to the git repository
|
||||
return tmp_path
|
||||
0
pkgs/clan-app/tests/helpers/__init__.py
Normal file
0
pkgs/clan-app/tests/helpers/__init__.py
Normal file
24
pkgs/clan-app/tests/helpers/cli.py
Normal file
24
pkgs/clan-app/tests/helpers/cli.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
|
||||
from clan_app import main
|
||||
from clan_cli.custom_logger import get_callers
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def print_trace(msg: str) -> None:
|
||||
trace_depth = int(os.environ.get("TRACE_DEPTH", "0"))
|
||||
callers = get_callers(2, 2 + trace_depth)
|
||||
|
||||
if "run_no_stdout" in callers[0]:
|
||||
callers = get_callers(3, 3 + trace_depth)
|
||||
callers_str = "\n".join(f"{i + 1}: {caller}" for i, caller in enumerate(callers))
|
||||
log.debug(f"{msg} \nCallers: \n{callers_str}")
|
||||
|
||||
|
||||
def run(args: list[str]) -> None:
|
||||
cmd = shlex.join(["clan", *args])
|
||||
print_trace(f"$ {cmd}")
|
||||
main(args)
|
||||
35
pkgs/clan-app/tests/root.py
Normal file
35
pkgs/clan-app/tests/root.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
TEST_ROOT = Path(__file__).parent.resolve()
|
||||
PROJECT_ROOT = TEST_ROOT.parent
|
||||
if CLAN_CORE_ := os.environ.get("CLAN_CORE_PATH"):
|
||||
CLAN_CORE = Path(CLAN_CORE_)
|
||||
else:
|
||||
CLAN_CORE = PROJECT_ROOT.parent.parent
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def project_root() -> Path:
|
||||
"""
|
||||
Root directory the clan-cli
|
||||
"""
|
||||
return PROJECT_ROOT
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_root() -> Path:
|
||||
"""
|
||||
Root directory of the tests
|
||||
"""
|
||||
return TEST_ROOT
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def clan_core() -> Path:
|
||||
"""
|
||||
Directory of the clan-core flake
|
||||
"""
|
||||
return CLAN_CORE
|
||||
28
pkgs/clan-app/tests/temporary_dir.py
Normal file
28
pkgs/clan-app/tests/temporary_dir.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temporary_home(monkeypatch: pytest.MonkeyPatch) -> Iterator[Path]:
|
||||
env_dir = os.getenv("TEST_TEMPORARY_DIR")
|
||||
if env_dir is not None:
|
||||
path = Path(env_dir).resolve()
|
||||
log.debug("Temp HOME directory: %s", str(path))
|
||||
monkeypatch.setenv("HOME", str(path))
|
||||
monkeypatch.chdir(str(path))
|
||||
yield path
|
||||
else:
|
||||
with tempfile.TemporaryDirectory(prefix="pytest-") as _dirpath:
|
||||
dirpath = Path(_dirpath)
|
||||
monkeypatch.setenv("HOME", str(dirpath))
|
||||
monkeypatch.setenv("XDG_CONFIG_HOME", str(dirpath / ".config"))
|
||||
monkeypatch.chdir(str(dirpath))
|
||||
log.debug("Temp HOME directory: %s", str(dirpath))
|
||||
yield dirpath
|
||||
7
pkgs/clan-app/tests/test_cli.py
Normal file
7
pkgs/clan-app/tests/test_cli.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import pytest
|
||||
from helpers import cli
|
||||
|
||||
|
||||
def test_help() -> None:
|
||||
with pytest.raises(SystemExit):
|
||||
cli.run(["clan-app", "--help"])
|
||||
5
pkgs/clan-app/tests/test_join.py
Normal file
5
pkgs/clan-app/tests/test_join.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from wayland import GtkProc
|
||||
|
||||
|
||||
def test_open(app: GtkProc) -> None:
|
||||
assert app.poll() is None
|
||||
31
pkgs/clan-app/tests/wayland.py
Normal file
31
pkgs/clan-app/tests/wayland.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import sys
|
||||
from collections.abc import Generator
|
||||
from subprocess import Popen
|
||||
from typing import NewType
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def wayland_compositor() -> Generator[Popen, None, None]:
|
||||
# Start the Wayland compositor (e.g., Weston)
|
||||
# compositor = Popen(["weston", "--backend=headless-backend.so"])
|
||||
compositor = Popen(["weston"])
|
||||
yield compositor
|
||||
# Cleanup: Terminate the compositor
|
||||
compositor.terminate()
|
||||
|
||||
|
||||
GtkProc = NewType("GtkProc", Popen)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app() -> Generator[GtkProc, None, None]:
|
||||
cmd = [sys.executable, "-m", "clan_app"]
|
||||
print(f"Running: {cmd}")
|
||||
rapp = Popen(
|
||||
cmd, text=True, stdout=sys.stdout, stderr=sys.stderr, start_new_session=True
|
||||
)
|
||||
yield GtkProc(rapp)
|
||||
# Cleanup: Terminate your application
|
||||
rapp.terminate()
|
||||
Reference in New Issue
Block a user