async def test_get_device_not_adopted_enabled(protect_client: ProtectApiClient, camera): camera["isAdopted"] = False protect_client.ignore_unadopted = False protect_client.api_request_obj = AsyncMock(return_value=camera) # type: ignore obj = create_from_unifi_dict(camera) assert obj == await protect_client.get_camera("test_id")
def shell( username: str = OPTION_USERNAME, password: str = OPTION_PASSWORD, address: str = OPTION_ADDRESS, port: int = OPTION_PORT, verify: bool = OPTION_VERIFY, ) -> None: if embed is None or colored is None: typer.echo("ipython and termcolor required for shell subcommand") sys.exit(1) protect = ProtectApiClient(address, port, username, password, verify_ssl=verify) loop = asyncio.get_event_loop() loop.run_until_complete(protect.update(True)) _setup_logger(show_level=True) c = get_config() c.InteractiveShellEmbed.colors = "Linux" embed(header=colored("protect = ProtectApiClient(*args)", "green"), config=c, using="asyncio")
async def test_check_ws_initial(protect_client: ProtectApiClient, caplog: pytest.LogCaptureFixture): caplog.set_level(logging.DEBUG) protect_client._last_websocket_check = NEVER_RAN protect_client.reset_ws() active_ws = await protect_client.check_ws() assert active_ws is True assert ["Checking websocket"] == [rec.message for rec in caplog.records]
def test_connection_host(protect_client: ProtectApiClient): protect_client.bootstrap.nvr.hosts = [ IPv4Address("192.168.1.1"), IPv4Address("192.168.2.1"), IPv4Address("192.168.3.1"), "se-gw.local", ] # mismatch between client IP and IP that NVR returns protect_client._connection_host = None protect_client._host = "192.168.10.1" assert protect_client.connection_host == IPv4Address("192.168.1.1") # same IP from client and NVR (first match) protect_client._connection_host = None protect_client._host = "192.168.1.1" assert protect_client.connection_host == IPv4Address("192.168.1.1") # same IP from client and NVR (not first match) protect_client._connection_host = None protect_client._host = "192.168.3.1" assert protect_client.connection_host == IPv4Address("192.168.3.1") # same IP from client and NVR (not first match, DNS host) protect_client._connection_host = None protect_client._host = "se-gw.local" assert protect_client.connection_host == "se-gw.local"
async def test_check_ws_no_ws(protect_client: ProtectApiClient, caplog: pytest.LogCaptureFixture): caplog.set_level(logging.DEBUG) protect_client._last_websocket_check = time.monotonic() protect_client.reset_ws() active_ws = await protect_client.check_ws() assert active_ws is False expected_logs = [ "Unifi OS: Websocket connection not active, failing back to polling" ] assert expected_logs == [rec.message for rec in caplog.records] assert caplog.records[0].levelname == "DEBUG"
def profile_ws( username: str = OPTION_USERNAME, password: str = OPTION_PASSWORD, address: str = OPTION_ADDRESS, port: int = OPTION_PORT, verify: bool = OPTION_VERIFY, wait_time: int = OPTION_WAIT, output_path: Optional[Path] = OPTION_OUTPUT, ) -> None: protect = ProtectApiClient(address, port, username, password, verify_ssl=verify, debug=True) async def callback() -> None: await protect.update() await profile_ws_job(protect, wait_time, output_path=output_path, ws_progress=_progress_bar) _setup_logger() loop = asyncio.get_event_loop() loop.run_until_complete(callback())
def shell( username: str = OPTION_USERNAME, password: str = OPTION_PASSWORD, address: str = OPTION_ADDRESS, port: int = OPTION_PORT, verify: bool = OPTION_VERIFY, new: bool = OPTION_NEW, ) -> None: if embed is None or colored is None: typer.echo("ipython and termcolor required for shell subcommand") sys.exit(1) if new: protect: Union[UpvServer, ProtectApiClient] = ProtectApiClient( address, port, username, password, verify_ssl=verify ) else: protect = UpvServer(None, address, port, username, password, verify_ssl=verify) loop = asyncio.get_event_loop() loop.run_until_complete(protect.update(True)) console_handler = logging.StreamHandler() console_handler.setLevel(logging.DEBUG) _LOGGER.setLevel(logging.DEBUG) _LOGGER.addHandler(console_handler) klass = "UpvServer" if new: klass = "ProtectApiClient" c = get_config() c.InteractiveShellEmbed.colors = "Linux" embed(header=colored(f"protect = {klass}(*args)", "green"), config=c, using="asyncio")
async def test_bootstrap_fix_record_mode(bootstrap): expected_updates = 1 orig_bootstrap = deepcopy(bootstrap) bootstrap["cameras"][0]["recordingSettings"]["mode"] = "motion" if len(bootstrap["cameras"]) > 1: expected_updates = 2 bootstrap["cameras"][1]["recordingSettings"]["mode"] = "smartDetect" client = ProtectApiClient("127.0.0.1", 0, "username", "password", debug=True) client.api_request_obj = AsyncMock(side_effect=[bootstrap, orig_bootstrap]) client.update_device = AsyncMock() await client.get_bootstrap() assert client.api_request_obj.call_count == 2 assert client.update_device.call_count == expected_updates
def test_base_url(protect_client: ProtectApiClient): assert protect_client.base_url == "https://127.0.0.1:0" assert protect_client.base_ws_url == "wss://127.0.0.1:0" protect_client._port = 443 assert protect_client.base_url == "https://127.0.0.1" assert protect_client.base_ws_url == "wss://127.0.0.1"
async def test_get_events_not_event_with_type(protect_client: ProtectApiClient, camera): camera["type"] = EventType.MOTION.value protect_client.get_events_raw = AsyncMock(return_value=[camera ]) # type: ignore assert await protect_client.get_events() == []
async def test_check_ws_reconnect(protect_client: ProtectApiClient, caplog: pytest.LogCaptureFixture): caplog.set_level(logging.DEBUG) protect_client._last_websocket_check = time.monotonic( ) - WEBSOCKET_CHECK_INTERVAL - 1 protect_client.reset_ws() active_ws = await protect_client.check_ws() assert active_ws is True expected_logs = [ "Checking websocket", "Unifi OS: Websocket connection not active, failing back to polling" ] assert expected_logs == [rec.message for rec in caplog.records] assert caplog.records[1].levelname == "WARNING"
def test_api_client_creation(): """Test we can create the object.""" client = ProtectApiClient("127.0.0.1", 0, "username", "password", debug=True) assert client
def test_early_bootstrap(): client = ProtectApiClient("127.0.0.1", 0, "username", "password", debug=True) with pytest.raises(BadRequest): client.bootstrap
def test_base_url(protect_client: ProtectApiClient): arg = f"{protect_client.ws_path}?lastUpdateId={protect_client.bootstrap.last_update_id}" assert protect_client.base_url == "https://127.0.0.1:0" assert protect_client.ws_url == f"wss://127.0.0.1:0{arg}" protect_client._port = 443 assert protect_client.base_url == "https://127.0.0.1" assert protect_client.ws_url == f"wss://127.0.0.1{arg}"
async def test_get_events(protect_client: ProtectApiClient, raw_events): expected_events = [] for event in raw_events: if event["score"] >= 50 and event["type"] in EventType.device_events(): expected_events.append(event) protect_client._minimum_score = 50 events = await protect_client.get_events() assert len(events) == len(expected_events) for index, event in enumerate(events): compare_objs(event.model.value, expected_events[index], event.unifi_dict()) if event.type.value in EventType.motion_events(): await check_motion_event(event)
def generate_sample_data( username: str = OPTION_USERNAME, password: str = OPTION_PASSWORD, address: str = OPTION_ADDRESS, port: int = OPTION_PORT, verify: bool = OPTION_VERIFY, anonymize: bool = OPTION_ANON, wait_time: int = OPTION_WAIT, output_folder: Optional[Path] = OPTION_OUTPUT, do_zip: bool = OPTION_ZIP, ) -> None: if output_folder is None: tests_folder = Path(__file__).parent.parent / "tests" if not tests_folder.exists(): typer.secho("Output folder required when not in dev-mode", fg="red") sys.exit(1) output_folder = (tests_folder / "sample_data").absolute() protect = ProtectApiClient(address, port, username, password, verify_ssl=verify, debug=True) def log(msg: str) -> None: typer.echo(msg) def log_warning(msg: str) -> None: typer.secho(msg, fg="yellow") SampleDataGenerator( protect, output_folder, anonymize, wait_time, log=log, log_warning=log_warning, ws_progress=_progress_bar, do_zip=do_zip, ).generate()
def test_connection_host_override(): protect = ProtectApiClient("127.0.0.1", 443, "test", "test", override_connection_host=True) expected = IPv4Address("127.0.0.1") assert protect._connection_host == expected
async def test_get_devices_not_adopted_enabled(protect_client: ProtectApiClient, cameras): cameras[0]["isAdopted"] = False protect_client.ignore_unadopted = False protect_client.api_request_list = AsyncMock(return_value=cameras) # type: ignore assert len(await protect_client.get_cameras()) == len(cameras)
async def test_get_devices_mismatch(protect_client: ProtectApiClient, cameras): protect_client.api_request_list = AsyncMock(return_value=cameras) # type: ignore with pytest.raises(NvrError): await protect_client.get_bridges()
async def test_get_device_not_adopted(protect_client: ProtectApiClient, camera): camera["isAdopted"] = False protect_client.api_request_obj = AsyncMock(return_value=camera) # type: ignore with pytest.raises(NvrError): await protect_client.get_camera("test_id")
async def test_get_events_not_event(protect_client: ProtectApiClient, camera): protect_client.get_events_raw = AsyncMock(return_value=[camera]) # type: ignore assert await protect_client.get_events() == []
async def test_force_update(protect_client: ProtectApiClient): protect_client._bootstrap = None await protect_client.update(force=True) assert protect_client.bootstrap