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
2 changes: 2 additions & 0 deletions roborock/devices/traits/v1/clean_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def convert(self, response: common.V1ResponseData) -> CleanRecord:
if isinstance(response, dict):
return CleanRecord.from_dict(response)
if isinstance(response, list):
if not response:
raise ValueError("Empty clean record response")
if isinstance(response[-1], dict):
records = [CleanRecord.from_dict(rec) for rec in response]
final_record = records[-1]
Expand Down
54 changes: 53 additions & 1 deletion tests/devices/traits/v1/test_clean_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from roborock.data import CleanSummary
from roborock.devices.device import RoborockDevice
from roborock.devices.traits.v1.clean_summary import CleanSummaryTrait
from roborock.exceptions import RoborockException
from roborock.exceptions import RoborockException, RoborockParsingException
from roborock.roborock_typing import RoborockCommand
from tests.mock_data import CLEAN_RECORD

Expand Down Expand Up @@ -193,6 +193,58 @@ async def test_get_clean_record_success(
)


@pytest.mark.parametrize("response", [[], [[]]], ids=["empty", "wrapped-empty"])
async def test_get_clean_record_empty_response(
clean_summary_trait: CleanSummaryTrait, mock_rpc_channel: AsyncMock, response: list
) -> None:
"""Report empty records through the public parsing exception boundary."""
mock_rpc_channel.send_command.return_value = response

with pytest.raises(RoborockParsingException, match="GET_CLEAN_RECORD") as exc:
await clean_summary_trait.get_clean_record(1738864366)

assert isinstance(exc.value.__cause__, ValueError)
assert f"Payload: {response!r}" in str(exc.value)
mock_rpc_channel.send_command.assert_called_once_with(RoborockCommand.GET_CLEAN_RECORD, params=[1738864366])


@pytest.mark.parametrize(
"response",
[
[CLEAN_RECORD],
[
{
"begin": 1700000000,
"end": 1700000100,
"duration": 100,
"area": 1000000,
"avoid_count": 1,
"wash_count": 1,
},
{
"begin": 1700000200,
"end": 1700000400,
"duration": 200,
"area": 2000000,
"avoid_count": 2,
"wash_count": 2,
},
],
],
ids=["wrapped-dict", "multi-phase"],
)
async def test_get_clean_record_structured_responses(
clean_summary_trait: CleanSummaryTrait, mock_rpc_channel: AsyncMock, response: list[dict]
) -> None:
"""Keep wrapped and multi-phase records working through the public API."""
mock_rpc_channel.send_command.return_value = response

record = await clean_summary_trait.get_clean_record(1738864366)

assert record.begin == response[0]["begin"]
assert record.end == response[-1]["end"]


async def test_get_clean_record_dict_response(
clean_summary_trait: CleanSummaryTrait,
mock_rpc_channel: AsyncMock,
Expand Down
Loading