70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
from unittest.mock import Mock, patch
|
|||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from pigway_frame_flow.drivers.kokonna.widgets import WidgetReader
|
||
|
|
from pigway_frame_flow.errors import FlowError
|
||
|
|
|
||
|
|
|
||
|
|
def test_snapshot_does_not_contact_official_service():
|
||
|
|
with patch("requests.post") as post:
|
||
|
|
result = WidgetReader().read()
|
||
|
|
assert result.source == "snapshot"
|
||
|
|
assert len(result.catalog) == 75
|
||
|
|
assert not result.configured and not result.current_verified and not result.writable
|
||
|
|
post.assert_not_called()
|
||
|
|
|
||
|
|
|
||
|
|
def test_live_current_and_cache():
|
||
|
|
response = Mock(status_code=200)
|
||
|
|
response.json.return_value = {
|
||
|
|
"result": {
|
||
|
|
"rows": [
|
||
|
|
{"id": 29, "name": "古诗词", "tags": [], "args": {"城市": "private"}}
|
||
|
|
],
|
||
|
|
"frameCoverRobot": {
|
||
|
|
"frameCover": {"id": 29},
|
||
|
|
"args": {"private": "secret"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
with patch("requests.post", return_value=response) as post:
|
||
|
|
reader = WidgetReader("official-secret", 123)
|
||
|
|
result = reader.read()
|
||
|
|
assert reader.read() is result
|
||
|
|
assert result.current_verified and result.current.id == 29
|
||
|
|
assert "private" not in result.model_dump_json()
|
||
|
|
assert "official-secret" not in result.model_dump_json()
|
||
|
|
assert post.call_count == 1
|
||
|
|
assert post.call_args.kwargs["json"]["method"] == "appFrame.getFrameCovers"
|
||
|
|
assert post.call_args.kwargs["allow_redirects"] is False
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize(
|
||
|
|
"payload", [{"error": {"message": "official-secret"}}, {"result": {}}]
|
||
|
|
)
|
||
|
|
def test_vendor_errors_are_not_exposed(payload):
|
||
|
|
response = Mock(status_code=200)
|
||
|
|
response.json.return_value = payload
|
||
|
|
with (
|
||
|
|
patch("requests.post", return_value=response),
|
||
|
|
pytest.raises(FlowError) as error,
|
||
|
|
):
|
||
|
|
WidgetReader("official-secret", 123).read()
|
||
|
|
assert "official-secret" not in str(error.value)
|
||
|
|
|
||
|
|
|
||
|
|
def test_missing_robot_id_never_uses_session():
|
||
|
|
with patch("requests.post") as post:
|
||
|
|
assert not WidgetReader("secret").read().configured
|
||
|
|
post.assert_not_called()
|
||
|
|
|
||
|
|
|
||
|
|
def test_widget_api_mock_and_auth(client):
|
||
|
|
response = client.get("/api/v1/devices/living-room/widgets")
|
||
|
|
assert response.status_code == 200
|
||
|
|
assert response.json()["source"] == "mock"
|
||
|
|
assert len(response.json()["catalog"]) == 75
|
||
|
|
client.headers.clear()
|
||
|
|
assert client.get("/api/v1/devices/living-room/widgets").status_code == 401
|