Skip to content
Merged
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
52 changes: 30 additions & 22 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


@pytest.fixture(name="controller_state", scope="session")
def controller_state_fixture():
def controller_state_fixture() -> dict[str, Any]:
"""Load the controller state fixture data."""
return json.loads(load_fixture("controller_state.json"))

Expand Down Expand Up @@ -128,14 +128,14 @@ def lock_ultraloq_ubolt_pro_state_fixture():


@pytest.fixture(name="client_session")
def client_session_fixture(ws_client):
def client_session_fixture(ws_client: AsyncMock) -> AsyncMock:
"""Mock an aiohttp client session."""
client_session = AsyncMock(spec_set=ClientSession)
client_session.ws_connect.side_effect = AsyncMock(return_value=ws_client)
return client_session


def create_ws_message(result):
def create_ws_message(result: dict[str, Any]) -> Mock:
"""Return a mock WSMessage."""
message = Mock(spec_set=WSMessage)
message.type = WSMsgType.TEXT
Expand All @@ -145,20 +145,20 @@ def create_ws_message(result):


@pytest.fixture(name="messages")
def messages_fixture():
def messages_fixture() -> deque[Mock]:
"""Return a message buffer for the WS client."""
return deque()


@pytest.fixture(name="ws_client")
async def ws_client_fixture(
version_data,
ws_message,
result,
messages,
initialize_data,
get_log_config_data,
):
version_data: dict[str, Any],
ws_message: Mock,
result: dict[str, Any],
messages: deque[Mock],
initialize_data: dict[str, Any],
get_log_config_data: dict[str, Any],
) -> AsyncMock:
"""Mock a websocket client.

This fixture only allows a single message to be received.
Expand All @@ -173,7 +173,7 @@ async def ws_client_fixture(
for data in (version_data, initialize_data, get_log_config_data, result):
messages.append(create_ws_message(data))

async def receive():
async def receive() -> Mock:
"""Return a websocket message."""
await asyncio.sleep(0)

Expand All @@ -187,7 +187,7 @@ async def receive():

ws_client.receive.side_effect = receive

async def close_client(msg):
async def close_client(msg: dict[str, Any]) -> None:
"""Close the client."""
if msg["command"] in ("initialize", "start_listening"):
return
Expand All @@ -204,7 +204,7 @@ async def close_client(msg):

ws_client.send_json.side_effect = close_client

async def reset_close():
async def reset_close() -> None:
"""Reset the websocket client close method."""
ws_client.closed = True

Expand Down Expand Up @@ -232,7 +232,7 @@ async def driver_ready_fixture():


@pytest.fixture(name="version_data")
def version_data_fixture():
def version_data_fixture() -> dict[str, Any]:
"""Return mock version data."""
return {
"type": "version",
Expand All @@ -245,7 +245,7 @@ def version_data_fixture():


@pytest.fixture(name="initialize_data")
def initialize_data_fixture():
def initialize_data_fixture() -> dict[str, Any]:
"""Return mock initialize data."""
return {
"type": "result",
Expand All @@ -256,7 +256,7 @@ def initialize_data_fixture():


@pytest.fixture(name="log_config")
def log_config_fixture():
def log_config_fixture() -> dict[str, Any]:
"""Return log config."""
return {
"enabled": True,
Expand All @@ -268,7 +268,7 @@ def log_config_fixture():


@pytest.fixture(name="get_log_config_data")
def get_log_config_data_fixture(log_config):
def get_log_config_data_fixture(log_config: dict[str, Any]) -> dict[str, Any]:
"""Return mock get_log_config data."""
return {
"type": "result",
Expand All @@ -285,7 +285,7 @@ def url_fixture():


@pytest.fixture(name="result")
def result_fixture(controller_state, uuid4):
def result_fixture(controller_state: dict[str, Any], uuid4: str) -> dict[str, Any]:
"""Return a server result message."""
return {
"type": "result",
Expand All @@ -296,7 +296,7 @@ def result_fixture(controller_state, uuid4):


@pytest.fixture(name="ws_message")
def ws_message_fixture(result):
def ws_message_fixture(result: dict[str, Any]) -> Mock:
"""Return a mock WSMessage."""
return create_ws_message(result)

Expand All @@ -311,7 +311,11 @@ def mock_uuid_fixture() -> Generator[str, None, None]:


@pytest.fixture(name="client")
async def client_fixture(client_session, ws_client, uuid4):
async def client_fixture(
client_session: AsyncMock,
ws_client: AsyncMock,
uuid4: str,
) -> Client:
"""Return a client with a mock websocket transport.

This fixture needs to be a coroutine function to get an event loop
Expand Down Expand Up @@ -365,7 +369,11 @@ async def set_response(message: dict[str, Any]) -> None:


@pytest.fixture(name="driver")
def driver_fixture(client, controller_state, log_config):
def driver_fixture(
client: Client,
controller_state: dict[str, Any],
log_config: dict[str, Any],
) -> Driver:
"""Return a driver instance with a supporting client."""
client.driver = Driver(client, deepcopy(controller_state), log_config)
return client.driver
Expand Down
21 changes: 12 additions & 9 deletions test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from aiohttp.http_websocket import WSMsgType
import pytest

from test.common import MockCommandProtocol
from zwave_js_server.client import LOGGER, Client
from zwave_js_server.const import MAX_SERVER_SCHEMA_VERSION, LogLevel, __version__
from zwave_js_server.event import Event
Expand All @@ -23,6 +24,7 @@
InvalidState,
NotConnected,
)
from zwave_js_server.model.driver import Driver
from zwave_js_server.model.log_config import LogConfig


Expand Down Expand Up @@ -486,8 +488,11 @@ async def test_pop_future_none(client_session, url, driver_ready):


async def test_log_server(
client: Client, driver, caplog: pytest.LogCaptureFixture, mock_command
):
client: Client,
driver: Driver,
caplog: pytest.LogCaptureFixture,
mock_command: MockCommandProtocol,
) -> None:
"""Test logging from server."""
# pylint: disable=protected-access
assert client.connected
Expand Down Expand Up @@ -564,21 +569,19 @@ async def test_log_server(
assert caplog.records[3].name == "zwave_js_server.server"

# First time we disable should be clean
await client.disable_server_logging()
client.disable_server_logging()
assert not client.server_logging_enabled
assert len(caplog.records) == 4

# Second time we should log a warning
await client.disable_server_logging()
# Test that disabling again is a no-op
client.disable_server_logging()
assert not client.server_logging_enabled
assert len(caplog.records) == 5

# Test that both functions raise errors when client is not connected
# Test that enabling server logging raises an error when client is not connected
client.driver = None
client._client = None

with pytest.raises(InvalidState):
await client.enable_server_logging()

with pytest.raises(InvalidState):
await client.disable_server_logging()
client.disable_server_logging()
7 changes: 1 addition & 6 deletions zwave_js_server/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,9 @@ def handle_log_config_updates(event: dict) -> None:

await self.async_start_listening_logs()

async def disable_server_logging(self) -> None:
def disable_server_logging(self) -> None:
"""Disable logging from the server."""
if not self.connected or not self.driver:
raise InvalidState(
"Can't disable server logging when not connected to server"
)
if not self._server_logging_enabled or not self._server_logger_unsubs:
LOGGER.info("Server logging is already disabled")
return

for unsub in self._server_logger_unsubs:
Expand Down