Isolate official account RPC capabilities from API key device driver
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from pigway_frame_flow.errors import ErrorCode, FlowError
|
||||
from pigway_frame_flow.integrations.kokonna_official.capabilities import capabilities
|
||||
from pigway_frame_flow.integrations.kokonna_official.rpc import OfficialRPC
|
||||
|
||||
|
||||
def test_login_session_not_password_used_for_reads():
|
||||
login = Mock(status_code=200)
|
||||
login.json.return_value = {"result": {"token": "session-secret"}}
|
||||
devices = Mock(status_code=200)
|
||||
devices.json.return_value = {"result": {"data": []}}
|
||||
rpc = OfficialRPC()
|
||||
with patch("requests.post", side_effect=[login, devices]) as post:
|
||||
rpc.login("account", "password-secret")
|
||||
assert rpc.devices() == {"data": []}
|
||||
assert post.call_args.kwargs["headers"] == {
|
||||
"Authorization": "Bearer session-secret"
|
||||
}
|
||||
assert "password-secret" not in str(post.call_args.kwargs)
|
||||
rpc.disconnect()
|
||||
assert not rpc.authorized
|
||||
with patch("requests.post") as post, pytest.raises(FlowError):
|
||||
rpc.devices()
|
||||
post.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method",
|
||||
[
|
||||
"appFrame.setFrameCover",
|
||||
"appFrame.reset",
|
||||
"appFrame.uploadImage",
|
||||
"arbitrary.method",
|
||||
],
|
||||
)
|
||||
def test_all_unenabled_operations_blocked_without_network(method):
|
||||
with patch("requests.post") as post, pytest.raises(FlowError) as error:
|
||||
OfficialRPC("session")._call(method, {})
|
||||
assert error.value.code == ErrorCode.UNSUPPORTED_CAPABILITY
|
||||
post.assert_not_called()
|
||||
|
||||
|
||||
def test_rpc_http_500_relogin_is_auth_error_not_cloud_failure():
|
||||
response = Mock(status_code=500)
|
||||
response.json.return_value = {"error": {"code": -1, "message": "请重新登陆"}}
|
||||
with (
|
||||
patch("requests.post", return_value=response),
|
||||
pytest.raises(FlowError) as error,
|
||||
):
|
||||
OfficialRPC("secret").devices()
|
||||
assert error.value.code == ErrorCode.UNAUTHORIZED
|
||||
assert "secret" not in str(error.value)
|
||||
|
||||
|
||||
def test_inventory_does_not_claim_unverified_writes_implemented():
|
||||
entries = {entry.method: entry for entry in capabilities()}
|
||||
assert entries["appFrame.setRotate"].implemented is False
|
||||
assert entries["appFrame.getFrameCovers"].evidence == "live_verified"
|
||||
assert all(
|
||||
not entry.implemented
|
||||
for entry in entries.values()
|
||||
if entry.evidence == "apk_discovered"
|
||||
)
|
||||
|
||||
|
||||
def test_api_key_driver_has_no_official_dependency():
|
||||
for name in ["client.py", "driver.py"]:
|
||||
source = (Path("pigway_frame_flow/drivers/kokonna") / name).read_text()
|
||||
assert "kokonna_official" not in source
|
||||
assert "WidgetReader" not in source
|
||||
|
||||
|
||||
def test_widget_disconnect_does_not_return_authenticated_cache():
|
||||
from pigway_frame_flow.integrations.kokonna_official.widgets import WidgetReader
|
||||
|
||||
response = Mock(status_code=200)
|
||||
response.json.return_value = {
|
||||
"result": {
|
||||
"rows": [],
|
||||
"robot": {"frameCoverRobotId": None},
|
||||
"frameCoverRobot": None,
|
||||
}
|
||||
}
|
||||
reader = WidgetReader("session", 123)
|
||||
with patch("requests.post", return_value=response):
|
||||
assert reader.read().status == "NO_WIDGET"
|
||||
reader.rpc.disconnect()
|
||||
with patch("requests.post") as post:
|
||||
assert reader.read().status == "AUTH_REQUIRED"
|
||||
post.assert_not_called()
|
||||
Reference in New Issue
Block a user