Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Connection details for the UniFi Controller (for development purposes)
# Connection details for the UniFi Controller (for optional live smoke tests)
UNIFI_CONTROLLER_URL=https://192.168.1.1
UNIFI_USERNAME=admin
UNIFI_PASSWORD=password
UNIFI_IS_UDM_PRO=false
UNIFI_IS_UDM_PRO=true
UNIFI_VERIFY_SSL=false
UNIFI_REQUEST_TIMEOUT=15
# Optional: enables the read-only device-list smoke test
UNIFI_SITE_NAME=default
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ except Exception as e:

---

## Optional Live Controller Smoke Tests

The normal test suite uses local fakes and does not contact a controller. To run read-only smoke tests against a real UniFi controller, provide environment variables and run the live-marked tests:

```bash
export UNIFI_CONTROLLER_URL="https://192.168.1.1"
export UNIFI_USERNAME="<LOCAL_ADMIN_USER>"
export UNIFI_PASSWORD="<PASSWORD>"
export UNIFI_IS_UDM_PRO=true
export UNIFI_VERIFY_SSL=false
export UNIFI_REQUEST_TIMEOUT=15
# Optional: also exercise read-only device listing for one site
export UNIFI_SITE_NAME=default

python -m pytest -m live -q
```

The live tests authenticate, list sites, and optionally list devices for `UNIFI_SITE_NAME`. They are skipped automatically when the required environment variables are absent.

---

## Data Models

The library automatically maps JSON API responses to Python data classes located in `unifi_controller_api.models`. Key models include:
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ include = ["unifi_controller_api*"]
[tool.setuptools.package-data]
"unifi_controller_api" = ["device-models.json"]

[tool.pytest.ini_options]
markers = [
"live: read-only tests that authenticate to a real UniFi controller when env vars are set",
]

[project.optional-dependencies]
dev = [
"pytest>=6.0",
Expand Down
73 changes: 73 additions & 0 deletions tests/test_live_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import os
from typing import TypedDict

import pytest

from unifi_controller_api import UnifiController


class LiveControllerConfig(TypedDict):
controller_url: str
username: str
password: str
is_udm_pro: bool
verify_ssl: bool
request_timeout: float


REQUIRED_ENV_VARS = (
"UNIFI_CONTROLLER_URL",
"UNIFI_USERNAME",
"UNIFI_PASSWORD",
)


def _env_bool(name: str, default: bool) -> bool:
value = os.environ.get(name)
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}


def _require_live_controller_config() -> LiveControllerConfig:
missing = [name for name in REQUIRED_ENV_VARS if not os.environ.get(name)]
if missing:
pytest.skip(
"live UniFi controller config not provided; missing "
+ ", ".join(missing)
)

return {
"controller_url": os.environ["UNIFI_CONTROLLER_URL"],
"username": os.environ["UNIFI_USERNAME"],
"password": os.environ["UNIFI_PASSWORD"],
"is_udm_pro": _env_bool("UNIFI_IS_UDM_PRO", True),
"verify_ssl": _env_bool("UNIFI_VERIFY_SSL", True),
"request_timeout": float(os.environ.get("UNIFI_REQUEST_TIMEOUT", "15")),
}


@pytest.mark.live
def test_live_controller_authenticates_and_lists_sites():
"""Read-only smoke test against a real UniFi controller when env vars are set."""
controller = UnifiController(**_require_live_controller_config())

sites = controller.get_unifi_site(include_health=False, raw=True)

assert isinstance(sites, list)
assert all(isinstance(site, dict) for site in sites)


@pytest.mark.live
def test_live_controller_can_fetch_devices_for_configured_site():
"""Optional read-only device smoke test for a configured site name."""
site_name = os.environ.get("UNIFI_SITE_NAME")
if not site_name:
pytest.skip("UNIFI_SITE_NAME not provided")

controller = UnifiController(**_require_live_controller_config())

devices = controller.get_unifi_site_device(site_name=site_name, raw=True)

assert isinstance(devices, list)
assert all(isinstance(device, dict) for device in devices)
Loading