Skip to content

Commit 5d767bc

Browse files
committed
Add testing
1 parent 4e72bd2 commit 5d767bc

File tree

5 files changed

+133
-0
lines changed

5 files changed

+133
-0
lines changed

tests/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,16 @@ def setup_websocket_client(
6666
os.environ["HOMEASSISTANTAPI_TOKEN"],
6767
) as client:
6868
yield client
69+
70+
71+
@pytest.fixture(name="async_websocket_client", scope="session")
72+
async def setup_async_websocket_client(
73+
wait_for_server: Literal[None],
74+
) -> AsyncGenerator[Client, None]:
75+
"""Initializes the Client and enters an async WebSocket session."""
76+
async with WebsocketClient(
77+
os.environ["HOMEASSISTANTAPI_WS_URL"],
78+
os.environ["HOMEASSISTANTAPI_TOKEN"],
79+
use_async=True
80+
) as client:
81+
yield client

tests/test_client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,12 @@ def test_websocket_client_ping() -> None:
5555
os.environ["HOMEASSISTANTAPI_TOKEN"],
5656
) as client:
5757
assert client.ping_latency() > 0
58+
59+
60+
async def test_async_websocket_client_ping() -> None:
61+
async with WebsocketClient(
62+
os.environ["HOMEASSISTANTAPI_WS_URL"],
63+
os.environ["HOMEASSISTANTAPI_TOKEN"],
64+
use_async=True
65+
) as client:
66+
assert (await client.async_ping_latency()) > 0

tests/test_endpoints.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,19 @@ def test_websocket_get_rendered_template(websocket_client: WebsocketClient) -> N
130130
}
131131

132132

133+
async def test_async_websocket_get_rendered_template(
134+
async_websocket_client: WebsocketClient
135+
) -> None:
136+
"""Tests the `"type": "render_template"` websocket command."""
137+
rendered_template = await async_websocket_client.async_get_rendered_template(
138+
'The sun is {{ states("sun.sun").replace("_", " the ") }}.'
139+
)
140+
assert rendered_template in {
141+
"The sun is above the horizon.",
142+
"The sun is below the horizon.",
143+
}
144+
145+
133146
def test_check_api_config(cached_client: Client) -> None:
134147
"""Tests the `POST /api/config/core/check_config` endpoint."""
135148
assert cached_client.check_api_config()
@@ -158,6 +171,14 @@ def test_websocket_get_entities(websocket_client: WebsocketClient) -> None:
158171
assert "sun" in entities
159172

160173

174+
async def test_async_websocket_get_entities(
175+
async_websocket_client: WebsocketClient
176+
) -> None:
177+
"""Tests the `"type": "get_entities"` websocket command."""
178+
entities = await async_websocket_client.async_get_entities()
179+
assert "sun" in entities
180+
181+
161182
def test_get_domains(cached_client: Client) -> None:
162183
"""Tests the `GET /api/services` endpoint."""
163184
domains = cached_client.get_domains()
@@ -176,6 +197,14 @@ def test_websocket_get_domains(websocket_client: WebsocketClient) -> None:
176197
assert "homeassistant" in domains
177198

178199

200+
async def test_async_websocket_get_domains(
201+
async_websocket_client: WebsocketClient
202+
) -> None:
203+
"""Tests the `"type": "get_domains"` websocket command."""
204+
domains = await async_websocket_client.async_get_domains()
205+
assert "homeassistant" in domains
206+
207+
179208
def test_get_domain(cached_client: Client) -> None:
180209
"""Tests the `GET /api/services` endpoint."""
181210
domain = cached_client.get_domain("homeassistant")
@@ -197,6 +226,15 @@ def test_websocket_get_domain(websocket_client: WebsocketClient) -> None:
197226
assert domain.services
198227

199228

229+
async def test_async_websocket_get_domain(
230+
async_websocket_client: WebsocketClient
231+
) -> None:
232+
"""Tests the `"type": "get_domain"` websocket command."""
233+
domain = await async_websocket_client.async_get_domain("homeassistant")
234+
assert domain is not None
235+
assert domain.services
236+
237+
200238
def test_trigger_service(cached_client: Client) -> None:
201239
"""Tests the `POST /api/services/<domain>/<service>` endpoint."""
202240
notify = cached_client.get_domain("notify")
@@ -231,6 +269,19 @@ def test_websocket_trigger_service(websocket_client: WebsocketClient) -> None:
231269
assert resp is None
232270

233271

272+
async def test_async_websocket_trigger_service(
273+
async_websocket_client: WebsocketClient
274+
) -> None:
275+
"""Tests the `"type": "trigger_service"` websocket command."""
276+
notify = await async_websocket_client.async_get_domain("notify")
277+
assert notify is not None
278+
resp = await notify.persistent_notification(
279+
message="Your API Test Suite just said hello!", title="Test Suite Notifcation"
280+
)
281+
# Websocket API doesnt return changed states so we check for None
282+
assert resp is None
283+
284+
234285
def test_trigger_service_with_response(cached_client: Client) -> None:
235286
"""Tests the `POST /api/services/<domain>/<service>?return_response` endpoint."""
236287
weather = cached_client.get_domain("weather")
@@ -267,6 +318,20 @@ def test_websocket_trigger_service_with_response(
267318
assert data is not None
268319

269320

321+
async def test_async_websocket_trigger_service_with_response(
322+
async_websocket_client: WebsocketClient
323+
) -> None:
324+
"""Tests the `"type": "trigger_service_with_response"` websocket command."""
325+
weather = await async_websocket_client.async_get_domain("weather")
326+
assert weather is not None
327+
data = weather.get_forecasts(
328+
entity_id="weather.forecast_home",
329+
type="hourly",
330+
)
331+
# Websocket API doesnt return changed states so we check data is not None because we expect a response
332+
assert data is not None
333+
334+
270335
def test_get_states(cached_client: Client) -> None:
271336
"""Tests the `GET /api/states` endpoint."""
272337
states = cached_client.get_states()
@@ -288,6 +353,15 @@ def test_websocket_get_states(websocket_client: WebsocketClient) -> None:
288353
assert isinstance(state, State)
289354

290355

356+
async def test_async_websocket_get_states(
357+
async_websocket_client: WebsocketClient
358+
) -> None:
359+
"""Tests the `"type": "get_states"` websocket command."""
360+
states = await async_websocket_client.async_get_states()
361+
for state in states:
362+
assert isinstance(state, State)
363+
364+
291365
def test_get_state(cached_client: Client) -> None:
292366
"""Tests the `GET /api/states/<entity_id>` endpoint."""
293367
state = cached_client.get_state(entity_id="sun.sun")

tests/test_errors.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ def test_websocket_unauthorized() -> None:
4242
pass
4343

4444

45+
async def test_async_websocket_unauthorized() -> None:
46+
with pytest.raises(UnauthorizedError):
47+
async with WebsocketClient(
48+
os.environ["HOMEASSISTANTAPI_WS_URL"],
49+
"lolthisisawrongtokenforsure",
50+
use_async=True,
51+
):
52+
pass
53+
54+
4555
async def test_async_unauthorized() -> None:
4656
with pytest.raises(UnauthorizedError):
4757
async with Client(

tests/test_events.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ def test_listen_events(websocket_client: WebsocketClient) -> None:
1616
assert event.data["message"] == "Triggered by websocket client"
1717

1818

19+
async def test_async_listen_events(async_websocket_client: WebsocketClient) -> None:
20+
async with async_websocket_client.async_listen_events("async_test_event") as events:
21+
await async_websocket_client.async_fire_event(
22+
"async_test_event", message="Triggered by async websocket client"
23+
)
24+
async for _, event in zip(range(1), events):
25+
assert event.origin == "LOCAL"
26+
assert event.event_type == "async_test_event"
27+
assert event.data["message"] == "Triggered by async websocket client"
28+
29+
1930
def test_listen_trigger(websocket_client: WebsocketClient) -> None:
2031
future = datetime.fromisoformat(
2132
websocket_client.get_rendered_template("{{ (now() + timedelta(seconds=1)) }}")
@@ -28,3 +39,19 @@ def test_listen_trigger(websocket_client: WebsocketClient) -> None:
2839
assert datetime.fromisoformat(
2940
trigger["trigger"]["now"]
3041
).timestamp() == pytest.approx(future.timestamp(), abs=1)
42+
43+
44+
async def test_async_listen_trigger(async_websocket_client: WebsocketClient) -> None:
45+
future = datetime.fromisoformat(
46+
await async_websocket_client.async_get_rendered_template(
47+
"{{ (now() + timedelta(seconds=1)) }}"
48+
)
49+
)
50+
async with async_websocket_client.async_listen_trigger(
51+
"time", at=future.strftime("%H:%M:%S")
52+
) as triggers:
53+
async for _, trigger in zip(range(1), triggers):
54+
assert trigger["trigger"]["platform"] == "time"
55+
assert datetime.fromisoformat(
56+
trigger["trigger"]["now"]
57+
).timestamp() == pytest.approx(future.timestamp(), abs=1)

0 commit comments

Comments
 (0)