Skip to content

Commit dc7a93a

Browse files
Patch76Patch76
andauthored
test(e2e): add negative-input tests for ha_get_history and ha_get_automation_traces (homeassistant-ai#945)
* test(e2e): add negative-input tests for ha_get_history and ha_get_automation_traces Covers three genuinely uncovered paths identified via source-level analysis and cross-checked against the full test suite (unit + E2E). ha_get_history — two new cases in workflows/core/test_history.py: - entity_ids="": single-string branch → entity_id_list=[""] → no pre-flight guard → WS call → HA valid_entity_id("")=False → Command failed → INTERNAL_ERROR - entity_ids=[]: list branch → if-not-entity_id_list → VALIDATION_MISSING_PARAMETER (no WS call) ha_get_automation_traces — new file workflows/automation/test_traces_negative.py: - automation_id="sensor.some_entity": domain-guard (tools_traces.py) rejects non-automation/script prefix → VALIDATION_INVALID_PARAMETER (no WS call) No prior hard coverage in unit (57 files) or E2E suite for any of these paths. Verified: tools_history.py, tools_traces.py, websocket_client.py, helpers.py. * fix(test): address review feedback on homeassistant-ai#945 - Move ha_get_automation_traces test into existing test_traces.py - Remove standalone test_traces_negative.py (new file was wrong) - Remove @pytest.mark.asyncio (asyncio_mode = auto) - Add type hints: mcp_client: Any, -> None - Use result directly (no data wrapper on safe_call_tool results) - Shorten docstrings to one sentence each * fix(test): sort imports per ruff I001 * fix(test): remove asyncio decorator and shorten docstrings per review --------- Co-authored-by: Patch76 <patch76@local> Co-authored-by: Patch76 <patch76@users.noreply.github.com>
1 parent 8aa176e commit dc7a93a

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

tests/src/e2e/workflows/automation/test_traces.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
"""
77

88
import logging
9+
from typing import Any
910

1011
import pytest
1112

1213
from ...utilities.assertions import (
1314
assert_mcp_success,
1415
parse_mcp_result,
16+
safe_call_tool,
1517
)
1618
from ...utilities.wait_helpers import wait_for_condition
1719

@@ -337,3 +339,17 @@ async def check_traces():
337339
assert trace_count > 0, (
338340
f"Expected at least 1 trace after running script, got {trace_count}"
339341
)
342+
343+
@pytest.mark.automation
344+
class TestGetAutomationTracesNegativeInputs:
345+
"""Negative-input tests for ha_get_automation_traces."""
346+
347+
async def test_wrong_domain_prefix_rejected(self, mcp_client: Any) -> None:
348+
"""Rejects an entity ID that does not belong to a supported domain."""
349+
result = await safe_call_tool(
350+
mcp_client,
351+
"ha_get_automation_traces",
352+
{"automation_id": "sensor.some_entity"},
353+
)
354+
assert result["success"] is False
355+
assert result["error"]["code"] == "VALIDATION_INVALID_PARAMETER"

tests/src/e2e/workflows/core/test_history.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import logging
99
from datetime import UTC, datetime, timedelta
10+
from typing import Any
1011

1112
import pytest
1213

@@ -571,7 +572,6 @@ async def test_get_statistics_entity_without_state_class(self, mcp_client):
571572
logger.info("Properly returned error for entity without state_class")
572573

573574

574-
@pytest.mark.asyncio
575575
@pytest.mark.core
576576
async def test_get_history_query_params_in_response(mcp_client):
577577
"""Test that query parameters are included in response."""
@@ -603,3 +603,28 @@ async def test_get_history_query_params_in_response(mcp_client):
603603
assert params.get("limit") == 10, f"limit mismatch: {params}"
604604
else:
605605
logger.info("query_params not in response (may be by design)")
606+
607+
608+
@pytest.mark.core
609+
class TestGetHistoryNegativeInputs:
610+
"""Negative-input tests for ha_get_history."""
611+
612+
async def test_empty_string_entity_id_rejected(self, mcp_client: Any) -> None:
613+
"""Rejects an invalid entity ID that cannot be resolved by the WebSocket handler."""
614+
result = await safe_call_tool(
615+
mcp_client,
616+
"ha_get_history",
617+
{"entity_ids": "", "start_time": "1h"},
618+
)
619+
assert result["success"] is False
620+
assert result["error"]["code"] == "INTERNAL_ERROR"
621+
622+
async def test_empty_list_entity_ids_rejected(self, mcp_client: Any) -> None:
623+
"""Rejects an empty list before any network call is made."""
624+
result = await safe_call_tool(
625+
mcp_client,
626+
"ha_get_history",
627+
{"entity_ids": [], "start_time": "1h"},
628+
)
629+
assert result["success"] is False
630+
assert result["error"]["code"] == "VALIDATION_MISSING_PARAMETER"

0 commit comments

Comments
 (0)